diff --git a/doc/manual/change-authors.yml b/doc/manual/change-authors.yml index c41614e1e..d62684598 100644 --- a/doc/manual/change-authors.yml +++ b/doc/manual/change-authors.yml @@ -36,6 +36,10 @@ alois31: forgejo: alois31 github: alois31 +andrewhamon: + display_name: Andrew Hamon + github: andrewhamon + artemist: display_name: Artemis Tosini forgejo: artemist diff --git a/doc/manual/rl-next/nix-env-priority.md b/doc/manual/rl-next/nix-env-priority.md new file mode 100644 index 000000000..23a6605dd --- /dev/null +++ b/doc/manual/rl-next/nix-env-priority.md @@ -0,0 +1,25 @@ +--- +synopsis: "`nix-env --install` now accepts a `--priority` flag" +cls: [2607] +category: Features +credits: andrewhamon +--- + +`nix-env --install` now has an optional `--priority` flag. + +Previously, it was only possible to specify a priority by adding a +`meta.priority` attribute to a derivation. `meta` attributes only exist during +eval, so that wouldn't work for installing a store path. It was also possible +to change a priority after initial installation using `nix-env --set-flag`, +however if there is already a conflict that needs to be resolved via priorities, +this will not work. + +Now, a priority can be set at install time using `--priority`, which allows for +cleanly overriding the priority at install time. + +#### Example + +```console +$ nix-build +$ nix-env --install --priority 100 ./result +``` diff --git a/doc/manual/src/command-ref/nix-env/install.md b/doc/manual/src/command-ref/nix-env/install.md index 5c532b856..aa1204328 100644 --- a/doc/manual/src/command-ref/nix-env/install.md +++ b/doc/manual/src/command-ref/nix-env/install.md @@ -11,6 +11,7 @@ [`--from-profile` *path*] [`--preserve-installed` | `-P`] [`--remove-all` | `-r`] + [`--priority` *priority*] # Description @@ -59,6 +60,11 @@ a number of possible ways: unambiguous way, which is necessary if there are multiple derivations with the same name. + - If `--priority` *priority* is given, the priority of the derivations being + installed is set to *priority*. This can be used to override the priority of + the derivations being installed. This is useful if *args* are store paths, + which don't have any priority information. + - If *args* are [store derivations](@docroot@/glossary.md#gloss-store-derivation), then these are [realised](@docroot@/command-ref/nix-store/realise.md), and the resulting output paths are installed. diff --git a/lix/legacy/nix-env.cc b/lix/legacy/nix-env.cc index c6cc858c0..de9ed16c8 100644 --- a/lix/legacy/nix-env.cc +++ b/lix/legacy/nix-env.cc @@ -513,9 +513,16 @@ static bool keep(EvalState & state, DrvInfo & drv) return drv.queryMetaBool(state, "keep", false); } +static void setMetaFlag(EvalState & state, DrvInfo & drv, + const std::string & name, const std::string & value) +{ + auto v = state.ctx.mem.allocValue(); + v->mkString(value); + drv.setMeta(state, name, v); +} static void installDerivations(Globals & globals, - const Strings & args, const Path & profile) + const Strings & args, const Path & profile, std::optional priority) { debug("installing derivations"); @@ -541,6 +548,11 @@ static void installDerivations(Globals & globals, newNames.insert(DrvName(i.queryName(*state)).name); } + if (priority) { + for (auto & drv : newElems) { + setMetaFlag(*state, drv, "priority", std::to_string((priority.value()))); + } + } while (true) { auto lockToken = optimisticLockProfile(profile); @@ -578,6 +590,7 @@ static void installDerivations(Globals & globals, static void opInstall(Globals & globals, Strings opFlags, Strings opArgs) { + std::optional priority; for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { auto arg = *i++; if (parseInstallSourceOptions(globals, i, opFlags, arg)) ; @@ -585,10 +598,17 @@ static void opInstall(Globals & globals, Strings opFlags, Strings opArgs) globals.preserveInstalled = true; else if (arg == "--remove-all" || arg == "-r") globals.removeAll = true; + else if (arg == "--priority") { + if (i == opFlags.end()) + throw UsageError("'%1%' requires an argument", arg); + priority = string2Int(*i++); + if (!priority) + throw UsageError("'--priority' requires an integer argument"); + } else throw UsageError("unknown flag '%1%'", arg); } - installDerivations(globals, opArgs, globals.profile); + installDerivations(globals, opArgs, globals.profile, priority); } @@ -705,15 +725,6 @@ static void opUpgrade(Globals & globals, Strings opFlags, Strings opArgs) } -static void setMetaFlag(EvalState & state, DrvInfo & drv, - const std::string & name, const std::string & value) -{ - auto v = state.ctx.mem.allocValue(); - v->mkString(value); - drv.setMeta(state, name, v); -} - - static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) @@ -1523,7 +1534,8 @@ static int main_nix_env(AsyncIoRoot & aio, std::string programName, Strings argv opFlags.push_back(*arg); /* FIXME: hacky */ if (*arg == "--from-profile" || - (op == opQuery && (*arg == "--attr" || *arg == "-A"))) + (op == opQuery && (*arg == "--attr" || *arg == "-A")) || + (op == opInstall && (*arg == "--priority"))) opFlags.push_back(getArg(*arg, arg, end)); } else diff --git a/tests/functional/user-envs.sh b/tests/functional/user-envs.sh index dcd6b1b97..bb48a8430 100644 --- a/tests/functional/user-envs.sh +++ b/tests/functional/user-envs.sh @@ -177,13 +177,21 @@ nix-env -q '*' | grepQuiet bar-0.1.1 # Test priorities: foo-0.1 has a lower priority than foo-1.0, so it # should be possible to install both without a collision. Also test -# ‘--set-flag priority’ to manually override the declared priorities. +# '-i --priority' and '--set-flag priority' to manually override the +# declared priorities. nix-env -e '*' nix-env -i foo-0.1 foo-1.0 [ "$($profiles/test/bin/foo)" = "foo-1.0" ] nix-env --set-flag priority 1 foo-0.1 [ "$($profiles/test/bin/foo)" = "foo-0.1" ] +# Priorities can be overridden with the --priority flag +nix-env -e '*' +nix-env -i foo-1.0 +[ "$($profiles/test/bin/foo)" = "foo-1.0" ] +nix-env -i --priority 1 foo-0.1 +[ "$($profiles/test/bin/foo)" = "foo-0.1" ] + # Test nix-env --set. nix-env --set $outPath10 [ "$(nix-store -q --resolve $profiles/test)" = $outPath10 ]