about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2004-09-10T13·32+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-09-10T13·32+0000
commitdcc433de47d4bf4a27fe63bc8996e946164ae885 (patch)
tree0d27a8f0433094144b7cdab591726f2ec288d937 /src
parentc16be6ac92b86981e8e4bb6703e694b675a28b0d (diff)
* Operation `--delete-generations' to delete generations of a
  profile.  Arguments are either generation number, or `old' to delete
  all non-current generations.  Typical use:

  $ nix-env --delete-generations old
  $ nix-collect-garbage

* istringstream -> string2Int.

Diffstat (limited to 'src')
-rw-r--r--src/libmain/shared.cc4
-rw-r--r--src/libutil/util.cc8
-rw-r--r--src/libutil/util.hh4
-rw-r--r--src/nix-env/main.cc49
-rw-r--r--src/nix-env/names.cc12
-rw-r--r--src/nix-env/profiles.cc40
-rw-r--r--src/nix-env/profiles.hh2
-rw-r--r--src/nix-store/main.cc14
8 files changed, 100 insertions, 33 deletions
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index 5affce77ed..24f6ec4df9 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -155,10 +155,8 @@ static void initAndRun(int argc, char * * argv)
         else if (arg == "--max-jobs" || arg == "-j") {
             ++i;
             if (i == args.end()) throw UsageError("`--max-jobs' requires an argument");
-            istringstream str(*i);
             int n;
-            str >> n;
-            if (!str || !str.eof() || n < 0)
+            if (!string2Int(*i, n) || n < 0)
                 throw UsageError(format("`--max-jobs' requires a non-negative integer"));
             maxBuildJobs = n;
         }
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index a25665e4a8..5a41c09865 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -616,3 +616,11 @@ bool statusOk(int status)
 {
     return WIFEXITED(status) && WEXITSTATUS(status) == 0;
 }
+
+
+bool string2Int(const string & s, int & n)
+{
+    istringstream str(s);
+    str >> n;
+    return str && str.eof();
+}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index ae5b4882e6..a79c07305d 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -246,6 +246,10 @@ string statusToString(int status);
 bool statusOk(int status);
 
 
+/* Parse a string into an integer. */
+bool string2Int(const string & s, int & n);
+
+
 /* !!! HACK HACK HACK - this should be in shared.hh, but it's to
    facilitate a quick hack - will remove this eventually (famous last
    words). */
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 14aa13b866..cf4ac8fc4a 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -643,10 +643,8 @@ static void opSwitchGeneration(Globals & globals,
     if (opArgs.size() != 1)
         throw UsageError(format("exactly one argument expected"));
 
-    istringstream str(opArgs.front());
     int dstGen;
-    str >> dstGen;
-    if (!str || !str.eof())
+    if (!string2Int(opArgs.front(), dstGen))
         throw UsageError(format("expected a generation number"));
 
     switchGeneration(globals, dstGen);
@@ -688,6 +686,49 @@ static void opListGenerations(Globals & globals,
 }
 
 
+static void deleteGeneration2(const Path & profile, unsigned int gen)
+{
+    printMsg(lvlInfo, format("removing generation %1%") % gen);
+    deleteGeneration(profile, gen);
+}
+
+
+static void opDeleteGenerations(Globals & globals,
+    Strings opFlags, Strings opArgs)
+{
+    if (opFlags.size() > 0)
+        throw UsageError(format("unknown flag `%1%'") % opFlags.front());
+
+    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.profile, j->number);
+        }
+
+        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.profile, j->number);
+                    found = true;
+                    break;
+                }
+            }
+            if (!found)
+                printMsg(lvlError, format("generation %1% does not exist") % n);
+        }
+    }
+}
+
+
 static void opDefaultExpr(Globals & globals,
     Strings opFlags, Strings opArgs)
 {
@@ -750,6 +791,8 @@ void run(Strings args)
             op = opRollback;
         else if (arg == "--list-generations")
             op = opListGenerations;
+        else if (arg == "--delete-generations")
+            op = opDeleteGenerations;
         else if (arg == "--dry-run") {
             printMsg(lvlInfo, "(dry run; not doing anything)");
             globals.dryRun = true;
diff --git a/src/nix-env/names.cc b/src/nix-env/names.cc
index c6054d6c1b..93bcfda24e 100644
--- a/src/nix-env/names.cc
+++ b/src/nix-env/names.cc
@@ -56,20 +56,10 @@ static string nextComponent(string::const_iterator & p,
 }
 
 
-#include <fstream>
-
-static bool parseInt(const string & s, int & n)
-{
-    istringstream st(s);
-    st >> n;
-    return !st.fail();
-}
-
-
 static bool componentsLT(const string & c1, const string & c2)
 {
     int n1, n2;
-    bool c1Num = parseInt(c1, n1), c2Num = parseInt(c2, n2);
+    bool c1Num = string2Int(c1, n1), c2Num = string2Int(c2, n2);
 
     if (c1Num && c2Num) return n1 < n2;
     else if (c1 == "" && c2Num) return true;
diff --git a/src/nix-env/profiles.cc b/src/nix-env/profiles.cc
index 1eeddf3326..c52ddc0b69 100644
--- a/src/nix-env/profiles.cc
+++ b/src/nix-env/profiles.cc
@@ -20,9 +20,11 @@ static int parseName(const string & profileName, const string & name)
     string s = string(name, profileName.size() + 1);
     int p = s.find("-link");
     if (p == string::npos) return -1;
-    istringstream str(string(s, 0, p));
-    unsigned int n;
-    if (str >> n && str.eof()) return n; else return -1;
+    int n;
+    if (string2Int(string(s, 0, p), n) && n >= 0)
+        return n;
+    else
+        return -1;
 }
 
 
@@ -59,6 +61,16 @@ Generations findGenerations(Path profile, int & curGen)
 }
 
 
+static void makeNames(const Path & profile, unsigned int num,
+    Path & generation, Path & gcrootDrv, Path & gcrootClr)
+{
+    Path prefix = (format("%1%-%2%") % profile % num).str();
+    generation = prefix + "-link";
+    gcrootDrv = prefix + "-drv.gcroot";
+    gcrootClr = prefix + "-clr.gcroot";
+}
+
+
 Path createGeneration(Path profile, Path outPath,
     Path drvPath, Path clrPath)
 {
@@ -72,10 +84,7 @@ Path createGeneration(Path profile, Path outPath,
     Path generation, gcrootDrv, gcrootClr;
 
     while (1) {
-        Path prefix = (format("%1%-%2%") % profile % num).str();
-        generation = prefix + "-link";
-        gcrootDrv = prefix + "-drv.gcroot";
-        gcrootClr = prefix + "-clr.gcroot";
+        makeNames(profile, num, generation, gcrootDrv, gcrootClr);
         if (symlink(outPath.c_str(), generation.c_str()) == 0) break;
         if (errno != EEXIST)
             throw SysError(format("creating symlink `%1%'") % generation);
@@ -90,6 +99,23 @@ Path createGeneration(Path profile, Path outPath,
 }
 
 
+static void removeFile(const Path & path)
+{
+    if (remove(path.c_str()) == -1)
+        throw SysError(format("cannot unlink `%1%'") % path);
+}
+
+
+void deleteGeneration(const Path & profile, unsigned int gen)
+{
+    Path generation, gcrootDrv, gcrootClr;
+    makeNames(profile, gen, generation, gcrootDrv, gcrootClr);
+    removeFile(generation);
+    if (pathExists(gcrootClr)) removeFile(gcrootClr);
+    if (pathExists(gcrootDrv)) removeFile(gcrootDrv);
+}
+
+
 void switchLink(Path link, Path target)
 {
     /* Hacky. */
diff --git a/src/nix-env/profiles.hh b/src/nix-env/profiles.hh
index 4231344127..bcd882c34c 100644
--- a/src/nix-env/profiles.hh
+++ b/src/nix-env/profiles.hh
@@ -31,6 +31,8 @@ Generations findGenerations(Path profile, int & curGen);
 Path createGeneration(Path profile, Path outPath,
     Path drvPath, Path clrPath);
 
+void deleteGeneration(const Path & profile, unsigned int gen);
+
 void switchLink(Path link, Path target);
 
 
diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc
index a8acd30c77..febe65e5c4 100644
--- a/src/nix-store/main.cc
+++ b/src/nix-store/main.cc
@@ -1,5 +1,4 @@
 #include <iostream>
-#include <sstream>
 
 #include "globals.hh"
 #include "normalise.hh"
@@ -171,10 +170,8 @@ static void opSubstitute(Strings opFlags, Strings opArgs)
         getline(cin, sub.program);
         string s;
         getline(cin, s);
-        istringstream st(s);
         int n;
-        st >> n;
-        if (!st) throw Error("number expected");
+        if (!string2Int(s, n)) throw Error("number expected");
         while (n--) {
             getline(cin, s);
             sub.args.push_back(s);
@@ -224,11 +221,10 @@ static void opGC(Strings opFlags, Strings opArgs)
         else if (*i == "--print-dead") subOp = soPrintDead;
         else if (*i == "--delete") subOp = soDelete;
         else if (*i == "--min-age") {
-            if (opArgs.size() == 0)
-                throw UsageError("`--min-age' requires an argument");
-            istringstream st(opArgs.front());
-            st >> minAge;
-            if (!st) throw Error("number expected");
+            int n;
+            if (opArgs.size() == 0 || !string2Int(opArgs.front(), n))
+                throw UsageError("`--min-age' requires an integer argument");
+            minAge = n;
         }
         else throw UsageError(format("bad sub-operation `%1%' in GC") % *i);