diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index a43b103f6ec6..894f64ec208b 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -464,6 +464,9 @@ static void installDerivations(Globals & globals, StringSet newNames; for (auto & i : newElems) { + /* Evaluate (and possibly fail) now before giving any mixed signals to the user. */ + i.queryOutPath(); + /* `forceName' is a hack to get package names right in some one-click installs, namely those where the name used in the path is not the one we want (e.g., `java-front' versus @@ -897,6 +900,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) bool jsonOutput = false; enum { sInstalled, sAvailable } source = sInstalled; + enum { eAll, eApproximate, eStrict } evaluate = eApproximate; settings.readOnlyMode = true; /* makes evaluation a bit faster */ @@ -912,6 +916,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) else if (arg == "--meta") printMeta = true; else if (arg == "--installed") source = sInstalled; else if (arg == "--available" || arg == "-a") source = sAvailable; + else if (arg == "--all") evaluate = eAll; + else if (arg == "--approximate") evaluate = eApproximate; + else if (arg == "--strict") evaluate = eStrict; else if (arg == "--xml") xmlOutput = true; else if (arg == "--json") jsonOutput = true; else if (arg == "--attr-path" || arg == "-P") printAttrPath = true; @@ -993,6 +1000,24 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) //Activity act(*logger, lvlDebug, format("outputting query result '%1%'") % i.attrPath); + /* Filter. */ + if (!printStatus && !globals.prebuiltOnly && evaluate != eAll) { + if (evaluate == eStrict) + /* Force evaluation. The above `try` will skip this element + if this throws an exception. */ + i.queryOutPath(); + else { + /* Skip derivations based on `.meta.available`. */ + Value * check = i.queryMeta("available"); + if (!check || check->type != tBool) + /* Fallback to evaluation as above. */ + i.queryOutPath(); + else if (check->boolean == false) + /* Just skip it. */ + continue; + } + } + if (globals.prebuiltOnly && validPaths.find(i.queryOutPath()) == validPaths.end() && substitutablePaths.find(i.queryOutPath()) == substitutablePaths.end())