about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChristian Theune <ct@flyingcircus.io>2015-05-19T18·03+0200
committerChristian Theune <ct@flyingcircus.io>2015-05-19T18·03+0200
commitea39c98d419a816029299b99f70455798e66f6b7 (patch)
tree9cdea14533783e93e0c7b1a4972bb6c58adb5edf
parent3d8318870289d7b6b08677fcd2da6ceb0b082f8c (diff)
Implement alternative to lazy generations:
* only the last generation can be lazy
* depend on the '--lazy-generation' flag to be set
-rw-r--r--src/nix-env/nix-env.cc15
-rw-r--r--src/nix-env/profiles.cc19
-rw-r--r--src/nix-env/profiles.hh2
-rw-r--r--src/nix-env/user-env.cc4
-rw-r--r--src/nix-env/user-env.hh2
-rw-r--r--tests/user-envs.sh18
6 files changed, 39 insertions, 21 deletions
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 10b95dad168c..8a7f5f0596b8 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -58,6 +58,7 @@ struct Globals
     bool removeAll;
     string forceName;
     bool prebuiltOnly;
+    bool lazyGeneration;
 };
 
 
@@ -510,7 +511,7 @@ static void installDerivations(Globals & globals,
         if (globals.dryRun) return;
 
         if (createUserEnv(*globals.state, allElems,
-                profile, settings.envKeepDerivations, lockToken)) break;
+                profile, settings.envKeepDerivations, lockToken, globals.lazyGeneration)) break;
     }
 }
 
@@ -524,6 +525,8 @@ static void opInstall(Globals & globals, Strings opFlags, Strings opArgs)
             globals.preserveInstalled = true;
         else if (arg == "--remove-all" || arg == "-r")
             globals.removeAll = true;
+        else if (arg == "--lazy-generation")
+            globals.lazyGeneration = true;
         else throw UsageError(format("unknown flag ‘%1%’") % arg);
     }
 
@@ -617,7 +620,7 @@ static void upgradeDerivations(Globals & globals,
         if (globals.dryRun) return;
 
         if (createUserEnv(*globals.state, newElems,
-                globals.profile, settings.envKeepDerivations, lockToken)) break;
+                globals.profile, settings.envKeepDerivations, lockToken, globals.lazyGeneration)) break;
     }
 }
 
@@ -681,7 +684,7 @@ static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs)
 
         /* Write the new user environment. */
         if (createUserEnv(*globals.state, installedElems,
-                globals.profile, settings.envKeepDerivations, lockToken)) break;
+                globals.profile, settings.envKeepDerivations, lockToken, globals.lazyGeneration)) break;
     }
 }
 
@@ -718,7 +721,8 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
     }
 
     debug(format("switching to new user environment"));
-    Path generation = createGeneration(globals.profile, drv.queryOutPath());
+    Path generation = createGeneration(globals.profile, drv.queryOutPath(),
+                                       globals.lazyGeneration);
     switchLink(globals.profile, generation);
 }
 
@@ -751,7 +755,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
         if (globals.dryRun) return;
 
         if (createUserEnv(*globals.state, newElems,
-                profile, settings.envKeepDerivations, lockToken)) break;
+                profile, settings.envKeepDerivations, lockToken, globals.lazyGeneration)) break;
     }
 }
 
@@ -1355,6 +1359,7 @@ int main(int argc, char * * argv)
         globals.preserveInstalled = false;
         globals.removeAll = false;
         globals.prebuiltOnly = false;
+        globals.lazyGeneration = false;
 
         parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
             Operation oldOp = op;
diff --git a/src/nix-env/profiles.cc b/src/nix-env/profiles.cc
index 1691dc099f4c..f2caa9868209 100644
--- a/src/nix-env/profiles.cc
+++ b/src/nix-env/profiles.cc
@@ -74,7 +74,7 @@ static void makeName(const Path & profile, unsigned int num,
 }
 
 
-Path createGeneration(Path profile, Path outPath)
+Path createGeneration(Path profile, Path outPath, bool lazy)
 {
     /* The new generation number should be higher than old the
        previous ones. */
@@ -83,13 +83,16 @@ Path createGeneration(Path profile, Path outPath)
 
     unsigned int num;
     if (gens.size() > 0) {
-        /* Check existing generations whether they represent an
-           environment we already materialized before.  In that case:
-           avoid cluttering the system with additional symlinks. */
-        for (auto & gen : gens) {
-            if (readLink(gen.path) == outPath) {
-                return gen.path;
-            }
+        Generation last = gens.back();
+
+        if (lazy && readLink(last.path) == outPath) {
+            /* If lazy generations are enabled then we only create a 
+               new generation symlink if it differs from the last one.
+
+               This helps keeping gratuitous installs/rebuilds from piling
+               up uncontrolled numbers of generations, cluttering up the
+               UI like grub. */
+            return last.path;
         }
 
         num = gens.back().number;
diff --git a/src/nix-env/profiles.hh b/src/nix-env/profiles.hh
index 30d2376d998c..64c98e0d6888 100644
--- a/src/nix-env/profiles.hh
+++ b/src/nix-env/profiles.hh
@@ -31,7 +31,7 @@ typedef list<Generation> Generations;
    profile, sorted by generation number. */
 Generations findGenerations(Path profile, int & curGen);
     
-Path createGeneration(Path profile, Path outPath);
+Path createGeneration(Path profile, Path outPath, bool lazy);
 
 void deleteGeneration(const Path & profile, unsigned int gen);
 
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
index 3bc31b9eafeb..43db6b513e1d 100644
--- a/src/nix-env/user-env.cc
+++ b/src/nix-env/user-env.cc
@@ -28,7 +28,7 @@ DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
 
 bool createUserEnv(EvalState & state, DrvInfos & elems,
     const Path & profile, bool keepDerivations,
-    const string & lockToken)
+    const string & lockToken, bool lazyGeneration)
 {
     /* Build the components in the user environment, if they don't
        exist already. */
@@ -141,7 +141,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
     }
 
     debug(format("switching to new user environment"));
-    Path generation = createGeneration(profile, topLevelOut);
+    Path generation = createGeneration(profile, topLevelOut, lazyGeneration);
     switchLink(profile, generation);
 
     return true;
diff --git a/src/nix-env/user-env.hh b/src/nix-env/user-env.hh
index f188efe9b4a9..4fedd19aa7c6 100644
--- a/src/nix-env/user-env.hh
+++ b/src/nix-env/user-env.hh
@@ -8,6 +8,6 @@ DrvInfos queryInstalled(EvalState & state, const Path & userEnv);
 
 bool createUserEnv(EvalState & state, DrvInfos & elems,
     const Path & profile, bool keepDerivations,
-    const string & lockToken);
+    const string & lockToken, bool lazyGeneration);
 
 }
diff --git a/tests/user-envs.sh b/tests/user-envs.sh
index ad15ddc3e441..6b290e50189e 100644
--- a/tests/user-envs.sh
+++ b/tests/user-envs.sh
@@ -99,14 +99,24 @@ if nix-env -q '*' | grep -q bar; then false; fi
 nix-env --list-generations
 test "$(nix-env --list-generations | wc -l)" -eq 7
 
-# Doing the same operation twice should result in the same generation, not an
-# additional one. At this point we just brought back foo. Installing it again
-# should not create a new generation.
+# Doing the same operation twice results in the same generation, but creates an
+# additional one. At this point we just brought back foo.
+
 nix-env -i foo
 
 # Count generations.
 nix-env --list-generations
-test "$(nix-env --list-generations | wc -l)" -eq 7
+test "$(nix-env --list-generations | wc -l)" -eq 8
+
+# Now, doing that again but passing the --lazy-generations flag will not
+# create a new generation.
+
+nix-env -i foo --lazy-generation
+
+# Count generations.
+nix-env --list-generations
+test "$(nix-env --list-generations | wc -l)" -eq 8
+
 
 # Switch to a specified generation.
 nix-env --switch-generation 7