about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/profiles.cc82
-rw-r--r--src/libstore/profiles.hh10
-rw-r--r--src/nix-collect-garbage/nix-collect-garbage.cc14
-rw-r--r--src/nix-env/nix-env.cc73
4 files changed, 110 insertions, 69 deletions
diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc
index 5b7a533df290..da3f7da9d19d 100644
--- a/src/libstore/profiles.cc
+++ b/src/libstore/profiles.cc
@@ -129,6 +129,88 @@ void deleteGeneration(const Path & profile, unsigned int gen)
 }
 
 
+static void deleteGeneration2(const Path & profile, unsigned int gen, bool dryRun)
+{
+    if (dryRun)
+        printMsg(lvlInfo, format("would remove generation %1%") % gen);
+    else {
+        printMsg(lvlInfo, format("removing generation %1%") % gen);
+        deleteGeneration(profile, gen);
+    }
+}
+
+
+void deleteGenerations(const Path & profile, const std::set<unsigned int> & gensToDelete, bool dryRun)
+{
+    PathLocks lock;
+    lockProfile(lock, profile);
+
+    int curGen;
+    Generations gens = findGenerations(profile, curGen);
+
+    if (gensToDelete.find(curGen) != gensToDelete.end())
+        throw Error(format("cannot delete current generation of profile %1%’") % profile);
+
+    for (auto & i : gens) {
+        if (gensToDelete.find(i.number) == gensToDelete.end()) continue;
+        deleteGeneration2(profile, i.number, dryRun);
+    }
+}
+
+
+void deleteOldGenerations(const Path & profile, bool dryRun)
+{
+    PathLocks lock;
+    lockProfile(lock, profile);
+
+    int curGen;
+    Generations gens = findGenerations(profile, curGen);
+
+    for (auto & i : gens)
+        if (i.number != curGen)
+            deleteGeneration2(profile, i.number, dryRun);
+}
+
+
+void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun)
+{
+    PathLocks lock;
+    lockProfile(lock, profile);
+
+    int curGen;
+    Generations gens = findGenerations(profile, curGen);
+
+    bool canDelete = false;
+    for (auto i = gens.rbegin(); i != gens.rend(); ++i)
+        if (canDelete) {
+            assert(i->creationTime < t);
+            if (i->number != curGen)
+                deleteGeneration2(profile, i->number, dryRun);
+        } else if (i->creationTime < t) {
+            /* We may now start deleting generations, but we don't
+               delete this generation yet, because this generation was
+               still the one that was active at the requested point in
+               time. */
+            canDelete = true;
+        }
+}
+
+
+void deleteGenerationsOlderThan(const Path & profile, const string & timeSpec, bool dryRun)
+{
+    time_t curTime = time(0);
+    string strDays = string(timeSpec, 0, timeSpec.size() - 1);
+    int days;
+
+    if (!string2Int(strDays, days) || days < 1)
+        throw Error(format("invalid number of days specifier ‘%1%’") % timeSpec);
+
+    time_t oldTime = curTime - days * 24 * 3600;
+
+    deleteGenerationsOlderThan(profile, oldTime, dryRun);
+}
+
+
 void switchLink(Path link, Path target)
 {
     /* Hacky. */
diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh
index 30d2376d998c..e99bbf398a86 100644
--- a/src/libstore/profiles.hh
+++ b/src/libstore/profiles.hh
@@ -30,11 +30,19 @@ typedef list<Generation> Generations;
 /* Returns the list of currently present generations for the specified
    profile, sorted by generation number. */
 Generations findGenerations(Path profile, int & curGen);
-    
+
 Path createGeneration(Path profile, Path outPath);
 
 void deleteGeneration(const Path & profile, unsigned int gen);
 
+void deleteGenerations(const Path & profile, const std::set<unsigned int> & gensToDelete, bool dryRun);
+
+void deleteOldGenerations(const Path & profile, bool dryRun);
+
+void deleteGenerationsOlderThan(const Path & profile, time_t t, bool dryRun);
+
+void deleteGenerationsOlderThan(const Path & profile, const string & timeSpec, bool dryRun);
+
 void switchLink(Path link, Path target);
 
 /* Ensure exclusive access to a profile.  Any command that modifies
diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc
index 740ef88f5395..b671e6cb82dd 100644
--- a/src/nix-collect-garbage/nix-collect-garbage.cc
+++ b/src/nix-collect-garbage/nix-collect-garbage.cc
@@ -1,5 +1,5 @@
 #include "store-api.hh"
-#include "hash.hh"
+#include "profiles.hh"
 #include "shared.hh"
 #include "globals.hh"
 
@@ -7,7 +7,7 @@
 
 using namespace nix;
 
-std::string gen = "old";
+std::string deleteOlderThan;
 bool dryRun = false;
 
 void runProgramSimple(Path program, const Strings & args)
@@ -49,10 +49,10 @@ void removeOldGenerations(std::string dir)
             auto link = readLink(path);
             if (link.find("link") != string::npos) {
                 printMsg(lvlInfo, format("removing old generations of profile %1%") % path);
-
-                auto args = Strings{"-p", path, "--delete-generations", gen};
-                if (dryRun) args.push_back("--dry-run");
-                runProgramSimple(settings.nixBinDir + "/nix-env", args);
+                if (deleteOlderThan != "")
+                    deleteGenerationsOlderThan(path, deleteOlderThan, dryRun);
+                else
+                    deleteOldGenerations(path, dryRun);
             }
         } else if (type == DT_DIR) {
             removeOldGenerations(path);
@@ -76,7 +76,7 @@ int main(int argc, char * * argv)
             else if (*arg == "--delete-old" || *arg == "-d") removeOld = true;
             else if (*arg == "--delete-older-than") {
                 removeOld = true;
-                gen = getArg(*arg, arg, end);
+                deleteOlderThan = getArg(*arg, arg, end);
             }
             else if (*arg == "--dry-run") dryRun = true;
             else
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 5cf41e844e83..3f82345ce43b 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -1262,73 +1262,24 @@ static void opListGenerations(Globals & globals, Strings opFlags, Strings opArgs
 }
 
 
-static void deleteGeneration2(Globals & globals, unsigned int gen)
-{
-    if (globals.dryRun)
-        printMsg(lvlInfo, format("would remove generation %1%") % gen);
-    else {
-        printMsg(lvlInfo, format("removing generation %1%") % gen);
-        deleteGeneration(globals.profile, gen);
-    }
-
-}
-
-
 static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
         throw UsageError(format("unknown flag ‘%1%’") % opFlags.front());
 
-    PathLocks lock;
-    lockProfile(lock, globals.profile);
-
-    int curGen;
-    Generations gens = findGenerations(globals.profile, curGen);
-
-    for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) {
-
-        if (*i == "old") {
-            for (Generations::iterator j = gens.begin(); j != gens.end(); ++j)
-                if (j->number != curGen)
-                    deleteGeneration2(globals, j->number);
-        } else if (i->size() >= 2 && tolower(*i->rbegin()) == 'd') {
-            time_t curTime = time(NULL);
-            time_t oldTime;
-            string strDays = string(*i, 0, i->size() - 1);
-            int days;
-
-            if (!string2Int(strDays, days) || days < 1)
-                throw UsageError(format("invalid number of days specifier ‘%1%’") % *i);
-
-            oldTime = curTime - days * 24 * 3600;
-
-            bool canDelete = false;
-            for (Generations::reverse_iterator j = gens.rbegin(); j != gens.rend(); ++j) {
-                if (canDelete) {
-                    assert(j->creationTime < oldTime);
-                    deleteGeneration2(globals, j->number);
-                } else if (j->creationTime < oldTime) {
-                    /* We may now start deleting generations, but we don't delete
-                       this generation yet, because this generation was still the
-                       one that was active at the requested point in time. */
-                    canDelete = true;
-                }
-            }
-        } else {
-            int n;
-            if (!string2Int(*i, n) || n < 0)
-                throw UsageError(format("invalid generation specifier ‘%1%’")  % *i);
-            bool found = false;
-            for (Generations::iterator j = gens.begin(); j != gens.end(); ++j) {
-                if (j->number == n) {
-                    deleteGeneration2(globals, j->number);
-                    found = true;
-                    break;
-                }
-            }
-            if (!found)
-                printMsg(lvlError, format("generation %1% does not exist") % n);
+    if (opArgs.size() == 1 && opArgs.front() == "old") {
+        deleteOldGenerations(globals.profile, globals.dryRun);
+    } else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) {
+        deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun);
+    } else {
+        std::set<unsigned int> gens;
+        for (auto & i : opArgs) {
+            unsigned int n;
+            if (!string2Int(i, n) || n < 0)
+                throw UsageError(format("invalid generation number ‘%1%’") % i);
+            gens.insert(n);
         }
+        deleteGenerations(globals.profile, gens, globals.dryRun);
     }
 }