Merge "feat: add a --priority flag to nix-env --install" into main

This commit is contained in:
Andy Hamon
2025-02-27 19:39:02 +00:00
committed by Gerrit Code Review
5 changed files with 68 additions and 13 deletions
+4
View File
@@ -36,6 +36,10 @@ alois31:
forgejo: alois31
github: alois31
andrewhamon:
display_name: Andrew Hamon
github: andrewhamon
artemist:
display_name: Artemis Tosini
forgejo: artemist
+25
View File
@@ -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
```
@@ -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.
+24 -12
View File
@@ -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<int> 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<int> 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<int>(*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
+9 -1
View File
@@ -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 ]