* nix-env -i: instead of breaking package ties by version, break them
by priority and version install. That is, if there are multiple packages with the same name, then pick the package with the highest priority, and only use the version if there are multiple packages with the same priority. This makes it possible to mark specific versions/variant in Nixpkgs more or less desirable than others. A typical example would be a beta version of some package (e.g., "gcc-4.2.0rc1") which should not be installed even though it is the highest version, except when it is explicitly selected (e.g., "nix-env -i gcc-4.2.0rc1"). * Idem for nix-env -u, only the semantics are a bit trickier since we also need to take into account the priority of the currently installed package (we never upgrade to a lower priority, unless --always is given).
This commit is contained in:
parent
cbfac2fdcc
commit
a9d15d4f43
4 changed files with 54 additions and 13 deletions
|
@ -70,12 +70,18 @@
|
||||||
info about installed packages in user environments. <option>-q
|
info about installed packages in user environments. <option>-q
|
||||||
--xml --meta</option> to show all meta info.</para></listitem>
|
--xml --meta</option> to show all meta info.</para></listitem>
|
||||||
|
|
||||||
|
|
||||||
<listitem><para>TODO: <command>nix-env</command>
|
<listitem><para>TODO: <command>nix-env</command>
|
||||||
<option>--set-flag</option>. Specific flags:
|
<option>--set-flag</option>. Specific flags:
|
||||||
<literal>active</literal>, <literal>priority</literal>,
|
<literal>active</literal>, <literal>priority</literal>,
|
||||||
<literal>keep</literal>.</para></listitem>
|
<literal>keep</literal>.</para></listitem>
|
||||||
|
|
||||||
|
|
||||||
|
<listitem><para>TODO: <command>nix-env</command> <option>-i</option>
|
||||||
|
/ <option>-u</option> take package priorities into
|
||||||
|
account.</para></listitem>
|
||||||
|
|
||||||
|
|
||||||
<listitem><para><command>nix-env -q</command> now has a flag
|
<listitem><para><command>nix-env -q</command> now has a flag
|
||||||
<option>--prebuilt-only</option> (<option>-b</option>) that causes
|
<option>--prebuilt-only</option> (<option>-b</option>) that causes
|
||||||
<command>nix-env</command> to show only those derivations whose
|
<command>nix-env</command> to show only those derivations whose
|
||||||
|
|
|
@ -60,6 +60,15 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string DrvInfo::queryMetaInfo(EvalState & state, const string & name) const
|
||||||
|
{
|
||||||
|
/* !!! evaluates all meta attributes => inefficient */
|
||||||
|
MetaInfo meta = queryMetaInfo(state);
|
||||||
|
MetaInfo::iterator i = meta.find(name);
|
||||||
|
return i == meta.end() ? "" : i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DrvInfo::setMetaInfo(const MetaInfo & meta)
|
void DrvInfo::setMetaInfo(const MetaInfo & meta)
|
||||||
{
|
{
|
||||||
ATermMap metaAttrs;
|
ATermMap metaAttrs;
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
string queryDrvPath(EvalState & state) const;
|
string queryDrvPath(EvalState & state) const;
|
||||||
string queryOutPath(EvalState & state) const;
|
string queryOutPath(EvalState & state) const;
|
||||||
MetaInfo queryMetaInfo(EvalState & state) const;
|
MetaInfo queryMetaInfo(EvalState & state) const;
|
||||||
|
string queryMetaInfo(EvalState & state, const string & name) const;
|
||||||
|
|
||||||
void setDrvPath(const string & s)
|
void setDrvPath(const string & s)
|
||||||
{
|
{
|
||||||
|
|
|
@ -232,6 +232,16 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int comparePriorities(EvalState & state,
|
||||||
|
const DrvInfo & drv1, const DrvInfo & drv2)
|
||||||
|
{
|
||||||
|
int prio1, prio2;
|
||||||
|
if (!string2Int(drv1.queryMetaInfo(state, "priority"), prio1)) prio1 = 0;
|
||||||
|
if (!string2Int(drv2.queryMetaInfo(state, "priority"), prio2)) prio2 = 0;
|
||||||
|
return prio2 - prio1; /* higher number = lower priority, so negate */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static DrvInfos filterBySelector(EvalState & state,
|
static DrvInfos filterBySelector(EvalState & state,
|
||||||
const DrvInfos & allElems,
|
const DrvInfos & allElems,
|
||||||
const Strings & args, bool newestOnly)
|
const Strings & args, bool newestOnly)
|
||||||
|
@ -258,8 +268,10 @@ static DrvInfos filterBySelector(EvalState & state,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If `newestOnly', if a selector matches multiple derivations
|
/* If `newestOnly', if a selector matches multiple derivations
|
||||||
with the same name, pick the one with the highest version.
|
with the same name, pick the one with the highest priority.
|
||||||
If there are multiple derivations with the same name *and*
|
If there are multiple derivations with the same priority,
|
||||||
|
pick the one with the highest version. If there are
|
||||||
|
multiple derivations with the same priority and name and
|
||||||
version, then pick the first one. */
|
version, then pick the first one. */
|
||||||
if (newestOnly) {
|
if (newestOnly) {
|
||||||
|
|
||||||
|
@ -270,13 +282,22 @@ static DrvInfos filterBySelector(EvalState & state,
|
||||||
|
|
||||||
for (Matches::iterator j = matches.begin(); j != matches.end(); ++j) {
|
for (Matches::iterator j = matches.begin(); j != matches.end(); ++j) {
|
||||||
DrvName drvName(j->first.name);
|
DrvName drvName(j->first.name);
|
||||||
|
int d = 1;
|
||||||
|
|
||||||
Newest::iterator k = newest.find(drvName.name);
|
Newest::iterator k = newest.find(drvName.name);
|
||||||
|
|
||||||
if (k != newest.end()) {
|
if (k != newest.end()) {
|
||||||
int d = compareVersions(drvName.version, DrvName(k->second.first.name).version);
|
d = comparePriorities(state, j->first, k->second.first);
|
||||||
if (d > 0) newest[drvName.name] = *j;
|
if (d == 0)
|
||||||
else if (d == 0) multiple.insert(j->first.name);
|
d = compareVersions(drvName.version, DrvName(k->second.first.name).version);
|
||||||
} else
|
}
|
||||||
|
|
||||||
|
if (d > 0) {
|
||||||
newest[drvName.name] = *j;
|
newest[drvName.name] = *j;
|
||||||
|
multiple.erase(j->first.name);
|
||||||
|
} else if (d == 0) {
|
||||||
|
multiple.insert(j->first.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matches.clear();
|
matches.clear();
|
||||||
|
@ -549,9 +570,10 @@ static void upgradeDerivations(Globals & globals,
|
||||||
if (meta["keep"] == "true") continue;
|
if (meta["keep"] == "true") continue;
|
||||||
|
|
||||||
/* Find the derivation in the input Nix expression with the
|
/* Find the derivation in the input Nix expression with the
|
||||||
same name and satisfying the version constraints specified
|
same name that satisfies the version constraints specified
|
||||||
by upgradeType. If there are multiple matches, take the
|
by upgradeType. If there are multiple matches, take the
|
||||||
one with highest version. */
|
one with the highest priority. If there are still multiple
|
||||||
|
matches, take the one with the highest version. */
|
||||||
DrvInfos::iterator bestElem = availElems.end();
|
DrvInfos::iterator bestElem = availElems.end();
|
||||||
DrvName bestName;
|
DrvName bestName;
|
||||||
for (DrvInfos::iterator j = availElems.begin();
|
for (DrvInfos::iterator j = availElems.begin();
|
||||||
|
@ -559,16 +581,19 @@ static void upgradeDerivations(Globals & globals,
|
||||||
{
|
{
|
||||||
DrvName newName(j->name);
|
DrvName newName(j->name);
|
||||||
if (newName.name == drvName.name) {
|
if (newName.name == drvName.name) {
|
||||||
int d = compareVersions(drvName.version, newName.version);
|
int d = comparePriorities(globals.state, *i, *j);
|
||||||
|
if (d == 0) d = compareVersions(drvName.version, newName.version);
|
||||||
if (upgradeType == utLt && d < 0 ||
|
if (upgradeType == utLt && d < 0 ||
|
||||||
upgradeType == utLeq && d <= 0 ||
|
upgradeType == utLeq && d <= 0 ||
|
||||||
upgradeType == utEq && d == 0 ||
|
upgradeType == utEq && d == 0 ||
|
||||||
upgradeType == utAlways)
|
upgradeType == utAlways)
|
||||||
{
|
{
|
||||||
if ((bestElem == availElems.end() ||
|
int d2 = -1;
|
||||||
compareVersions(
|
if (bestElem != availElems.end()) {
|
||||||
bestName.version, newName.version) < 0))
|
d2 = comparePriorities(globals.state, *bestElem, *j);
|
||||||
{
|
if (d2 == 0) d2 = compareVersions(bestName.version, newName.version);
|
||||||
|
}
|
||||||
|
if (d2 < 0) {
|
||||||
bestElem = j;
|
bestElem = j;
|
||||||
bestName = newName;
|
bestName = newName;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue