summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-02-17 17:47:54 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-02-17 17:47:54 +0000
commit7a3e715980c3fcd84b6d12f54a18a920ebba208d (patch)
treedd936690c8fa0e8397db3253adc1d8c302ce5072
parent58fc420b365b8f8d6faaa332ab3ba4e97ad584e0 (diff)
downloadguix-7a3e715980c3fcd84b6d12f54a18a920ebba208d.tar.gz
* 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.

-rw-r--r--src/nix-env/main.cc70
-rw-r--r--tests/user-envs.sh4
2 files changed, 64 insertions, 10 deletions
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 4acbb6db03..985918c470 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<string, DrvInfo> newest;
+
+            for (DrvInfos::const_iterator j = matches.begin();
+                 j != matches.end(); ++j)
+            {
+                DrvName drvName(j->name);
+                map<string, DrvInfo>::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<string, DrvInfo>::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 bd14f51080..59565cff0d 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