about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/manual/nix-env.xml37
-rw-r--r--src/nix-env/main.cc24
2 files changed, 58 insertions, 3 deletions
diff --git a/doc/manual/nix-env.xml b/doc/manual/nix-env.xml
index 8a496da25988..4772c2b1109b 100644
--- a/doc/manual/nix-env.xml
+++ b/doc/manual/nix-env.xml
@@ -183,6 +183,10 @@
           <arg choice='plain'><option>--install</option></arg>
           <arg choice='plain'><option>-i</option></arg>
         </group>
+        <group choice='opt'>
+          <arg choice='plain'><option>--preserve-installed</option></arg>
+          <arg choice='plain'><option>-P</option></arg>
+        </group>
         <arg choice='plain' rep='repeat'><replaceable>drvnames</replaceable></arg>
       </cmdsynopsis>
     </refsection>
@@ -197,6 +201,35 @@
         in the active Nix expression are added.
       </para>
 
+      <para>
+        Currently installed derivations with a name equal to the name
+        of a derivation being added are removed unless the option
+        <option>--preserve-installed</option> is specified.
+      </para>
+
+    </refsection>
+
+    <refsection>
+      <title>Flags</title>
+
+      <variablelist>
+
+        <varlistentry>
+          <term><option>--preserve-installed</option> / <option>-P</option></term>
+          <listitem>
+            <para>
+              Do not remove derivations with a name matching one of
+              the derivations being installed.  Usually, trying to
+              have two versions of the same package installed in the
+              same generation of a profile will lead to an error in
+              building the generation, due to file name clashes
+              between the two versions.  However, this is not the case
+              for all packages.
+            </para>
+          </listitem>
+        </varlistentry>
+
+      </variablelist>
     </refsection>
             
     <refsection>
@@ -204,7 +237,11 @@
 
       <screen>
 $ nix-env --install gcc-3.3.2 <lineannotation>(install specific version)</lineannotation>
+installing `gcc-3.3.2'
+uninstalling `gcc-3.1' <lineannotation>(previously installed version is removed)</lineannotation>
+
 $ nix-env --install gcc <lineannotation>(just pick any version)</lineannotation>
+
 $ nix-env -f ~/foo.nix -i '*' <lineannotation>(install everything in <filename>foo.nix</filename>)</lineannotation></screen>
 
     </refsection>
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 1f16e72ae0f1..09604a2d0d20 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -17,6 +17,7 @@ struct Globals
     Path nixExprPath;
     EvalState state;
     bool dryRun;
+    bool preserveInstalled;
 };
 
 
@@ -225,7 +226,7 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
 
 static void installDerivations(EvalState & state,
     Path nePath, DrvNames & selectors, const Path & profile,
-    bool dryRun)
+    bool dryRun, bool preserveInstalled)
 {
     debug(format("installing derivations from `%1%'") % nePath);
 
@@ -235,6 +236,7 @@ static void installDerivations(EvalState & state,
 
     /* Filter out the ones we're not interested in. */
     DrvInfos selectedDrvs;
+    StringSet selectedNames;
     for (DrvInfos::iterator i = availDrvs.begin();
          i != availDrvs.end(); ++i)
     {
@@ -247,6 +249,7 @@ static void installDerivations(EvalState & state,
                     format("installing `%1%'") % i->second.name);
                 j->hits++;
                 selectedDrvs.insert(*i);
+                selectedNames.insert(drvName.name);
             }
         }
     }
@@ -261,7 +264,18 @@ static void installDerivations(EvalState & state,
     /* Add in the already installed derivations. */
     DrvInfos installedDrvs;
     queryInstalled(state, installedDrvs, profile);
-    selectedDrvs.insert(installedDrvs.begin(), installedDrvs.end());
+
+    for (DrvInfos::iterator i = installedDrvs.begin();
+         i != installedDrvs.end(); ++i)
+    {
+        DrvName drvName(i->second.name);
+        if (!preserveInstalled &&
+            selectedNames.find(drvName.name) != selectedNames.end())
+            printMsg(lvlInfo,
+                format("uninstalling `%1%'") % i->second.name);
+        else
+            selectedDrvs.insert(*i);
+    }
 
     if (dryRun) return;
 
@@ -278,7 +292,8 @@ static void opInstall(Globals & globals,
     DrvNames drvNames = drvNamesFromArgs(opArgs);
     
     installDerivations(globals.state, globals.nixExprPath,
-        drvNames, globals.profile, globals.dryRun);
+        drvNames, globals.profile, globals.dryRun,
+        globals.preserveInstalled);
 }
 
 
@@ -641,6 +656,7 @@ void run(Strings args)
     Globals globals;
     globals.nixExprPath = getDefNixExprPath();
     globals.dryRun = false;
+    globals.preserveInstalled = false;
 
     for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
         string arg = *i;
@@ -681,6 +697,8 @@ void run(Strings args)
             printMsg(lvlInfo, "(dry run; not doing anything)");
             globals.dryRun = true;
         }
+        else if (arg == "--preserve-installed" || arg == "-P")
+            globals.preserveInstalled = true;
         else if (arg[0] == '-')
             opFlags.push_back(arg);
         else