diff --git a/doc/manual/nix-env.xml b/doc/manual/nix-env.xml
index 8a496da25..4772c2b11 100644
--- a/doc/manual/nix-env.xml
+++ b/doc/manual/nix-env.xml
@@ -183,6 +183,10 @@
+
+
+
+
drvnames
@@ -197,6 +201,35 @@
in the active Nix expression are added.
+
+ Currently installed derivations with a name equal to the name
+ of a derivation being added are removed unless the option
+ is specified.
+
+
+
+
+
+ Flags
+
+
+
+
+ /
+
+
+ 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.
+
+
+
+
+
@@ -204,7 +237,11 @@
$ nix-env --install gcc-3.3.2 (install specific version)
+installing `gcc-3.3.2'
+uninstalling `gcc-3.1' (previously installed version is removed)
+
$ nix-env --install gcc (just pick any version)
+
$ nix-env -f ~/foo.nix -i '*' (install everything in foo.nix)
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 1f16e72ae..09604a2d0 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