From 7a3e715980c3fcd84b6d12f54a18a920ebba208d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 17 Feb 2006 17:47:54 +0000 Subject: [PATCH] * Fix for NIX-31: "nix-env -i foo" installing all derivations named foo. Now it will only install the one with the highest version number. --- src/nix-env/main.cc | 70 +++++++++++++++++++++++++++++++++++++++------ tests/user-envs.sh | 4 +-- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc index 4acbb6db0..985918c47 100644 --- a/src/nix-env/main.cc +++ b/src/nix-env/main.cc @@ -208,13 +208,16 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, } -static DrvInfos filterBySelector(const DrvInfos & allElems, - const Strings & args) +static DrvInfos filterBySelector(EvalState & state, + const DrvInfos & allElems, + const Strings & args, bool newestOnly) { DrvNames selectors = drvNamesFromArgs(args); DrvInfos elems; + PathSet done; +#if 0 /* Filter out the ones we're not interested in. */ for (DrvInfos::const_iterator i = allElems.begin(); i != allElems.end(); ++i) @@ -229,6 +232,56 @@ static DrvInfos filterBySelector(const DrvInfos & allElems, } } } +#endif + + for (DrvNames::iterator i = selectors.begin(); + i != selectors.end(); ++i) + { + DrvInfos matches; + for (DrvInfos::const_iterator j = allElems.begin(); + j != allElems.end(); ++j) + { + DrvName drvName(j->name); + if (i->matches(drvName)) { + i->hits++; + matches.push_back(*j); + } + } + + if (newestOnly) { + + /* Map from package names to derivations. */ + map newest; + + for (DrvInfos::const_iterator j = matches.begin(); + j != matches.end(); ++j) + { + DrvName drvName(j->name); + map::iterator k = newest.find(drvName.name); + if (k != newest.end()) + if (compareVersions(drvName.version, DrvName(k->second.name).version) > 0) + newest[drvName.name] = *j; + else + ; + else + newest[drvName.name] = *j; + } + + matches.clear(); + for (map::iterator j = newest.begin(); + j != newest.end(); ++j) + matches.push_back(j->second); + } + + /* Insert only those elements in the final list that we + haven't inserted before. */ + for (DrvInfos::const_iterator j = matches.begin(); + j != matches.end(); ++j) + if (done.find(j->queryOutPath(state)) == done.end()) { + done.insert(j->queryOutPath(state)); + elems.push_back(*j); + } + } /* Check that all selectors have been used. */ for (DrvNames::iterator i = selectors.begin(); @@ -243,7 +296,7 @@ static DrvInfos filterBySelector(const DrvInfos & allElems, static void queryInstSources(EvalState & state, const InstallSourceInfo & instSource, const Strings & args, - DrvInfos & elems) + DrvInfos & elems, bool newestOnly) { InstallSourceType type = instSource.type; if (type == srcUnknown && args.size() > 0 && args.front()[0] == '/') @@ -263,7 +316,7 @@ static void queryInstSources(EvalState & state, loadDerivations(state, instSource.nixExprPath, instSource.systemFilter, allElems); - elems = filterBySelector(allElems, args); + elems = filterBySelector(state, allElems, args, newestOnly); break; } @@ -328,8 +381,9 @@ static void queryInstSources(EvalState & state, user environment. These are then filtered as in the `srcNixExprDrvs' case. */ case srcProfile: { - elems = filterBySelector( - queryInstalled(state, instSource.profile), args); + elems = filterBySelector(state, + queryInstalled(state, instSource.profile), + args, newestOnly); break; } } @@ -343,7 +397,7 @@ static void installDerivations(Globals & globals, /* Get the set of user environment elements to be installed. */ DrvInfos newElems; - queryInstSources(globals.state, globals.instSource, args, newElems); + queryInstSources(globals.state, globals.instSource, args, newElems, true); StringSet newNames; for (DrvInfos::iterator i = newElems.begin(); i != newElems.end(); ++i) @@ -406,7 +460,7 @@ static void upgradeDerivations(Globals & globals, /* Fetch all derivations from the input file. */ DrvInfos availElems; - queryInstSources(globals.state, globals.instSource, args, availElems); + queryInstSources(globals.state, globals.instSource, args, availElems, false); /* Go through all installed derivations. */ DrvInfos newElems; diff --git a/tests/user-envs.sh b/tests/user-envs.sh index bd14f5108..59565cff0 100644 --- a/tests/user-envs.sh +++ b/tests/user-envs.sh @@ -82,7 +82,7 @@ test "$($nixenv -p $profiles/test -q | wc -l)" -eq 0 # Installing "foo" should only install the newest foo. $nixenv -p $profiles/test -f ./user-envs.nix -i foo -test "$($nixenv -p $profiles/test -q | grep foo- | wc)" -eq 1 +test "$($nixenv -p $profiles/test -q | grep foo- | wc -l)" -eq 1 $nixenv -p $profiles/test -q | grep -q foo-2.0 # On the other hand, this should install both (and should fail due to @@ -93,6 +93,6 @@ if $nixenv -p $profiles/test -f ./user-envs.nix -i foo-1.0 foo-2.0; then false; # Installing "*" should install one foo and one bar. $nixenv -p $profiles/test -f ./user-envs.nix -e '*' $nixenv -p $profiles/test -f ./user-envs.nix -i '*' -test "$($nixenv -p $profiles/test -q | wc)" -eq 2 +test "$($nixenv -p $profiles/test -q | wc -l)" -eq 2 $nixenv -p $profiles/test -q | grep -q foo-2.0 $nixenv -p $profiles/test -q | grep -q bar-0.1.1