about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/nix-env/main.cc34
-rw-r--r--src/nix-env/profiles.cc41
-rw-r--r--src/nix-env/profiles.hh14
3 files changed, 80 insertions, 9 deletions
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 87190b620990..6aa342c1daff 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -1,5 +1,3 @@
-#include <cerrno>
-
 #include "profiles.hh"
 #include "names.hh"
 #include "globals.hh"
@@ -9,6 +7,9 @@
 #include "eval.hh"
 #include "help.txt.hh"
 
+#include <cerrno>
+#include <ctime>
+
 
 struct Globals
 {
@@ -460,9 +461,9 @@ static void opSwitchProfile(Globals & globals,
     Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
-        throw UsageError(format("unknown flags `%1%'") % opFlags.front());
+        throw UsageError(format("unknown flag `%1%'") % opFlags.front());
     if (opArgs.size() != 1)
-        throw UsageError(format("`--profile' takes exactly one argument"));
+        throw UsageError(format("exactly one argument expected"));
 
     Path profile = opArgs.front();
     Path profileLink = getHomeDir() + "/.nix-profile";
@@ -471,13 +472,34 @@ static void opSwitchProfile(Globals & globals,
 }
 
 
+static void opListGenerations(Globals & globals,
+    Strings opFlags, Strings opArgs)
+{
+    if (opFlags.size() > 0)
+        throw UsageError(format("unknown flag `%1%'") % opFlags.front());
+    if (opArgs.size() != 0)
+        throw UsageError(format("no arguments expected"));
+
+    Generations gens = findGenerations(globals.profile);
+
+    for (Generations::iterator i = gens.begin(); i != gens.end(); ++i) {
+        tm t;
+        if (!localtime_r(&i->creationTime, &t)) throw Error("cannot convert time");
+        cout << format("%|4|   %|4|-%|02|-%|02| %|02|:%|02|:%|02|\n")
+            % i->number
+            % (t.tm_year + 1900) % (t.tm_mon + 1) % t.tm_mday
+            % t.tm_hour % t.tm_min % t.tm_sec;
+    }
+}
+
+
 static void opDefaultExpr(Globals & globals,
     Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
         throw UsageError(format("unknown flags `%1%'") % opFlags.front());
     if (opArgs.size() != 1)
-        throw UsageError(format("`--import' takes exactly one argument"));
+        throw UsageError(format("exactly one argument expected"));
 
     Path defNixExpr = absPath(opArgs.front());
     Path defNixExprLink = getDefNixExprPath();
@@ -526,6 +548,8 @@ void run(Strings args)
         }
         else if (arg == "--switch-profile" || arg == "-S")
             op = opSwitchProfile;
+        else if (arg == "--list-generations")
+            op = opListGenerations;
         else if (arg[0] == '-')
             opFlags.push_back(arg);
         else
diff --git a/src/nix-env/profiles.cc b/src/nix-env/profiles.cc
index 5b9c004066b5..22da6336bdbf 100644
--- a/src/nix-env/profiles.cc
+++ b/src/nix-env/profiles.cc
@@ -1,13 +1,23 @@
 #include "profiles.hh"
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
-Path createGeneration(Path profile, Path outPath, Path drvPath)
+
+static bool cmpGensByNumber(const Generation & a, const Generation & b)
 {
+    return a.number < b.number;
+}
+
+
+Generations findGenerations(Path profile)
+{
+    Generations gens;
+
     Path profileDir = dirOf(profile);
     string profileName = baseNameOf(profile);
     
-    unsigned int num = 0;
-    
     Strings names = readDirectory(profileDir);
     for (Strings::iterator i = names.begin(); i != names.end(); ++i) {
         if (string(*i, 0, profileName.size() + 1) != profileName + "-") continue;
@@ -16,9 +26,32 @@ Path createGeneration(Path profile, Path outPath, Path drvPath)
         if (p == string::npos) continue;
         istringstream str(string(s, 0, p));
         unsigned int n;
-        if (str >> n && str.eof() && n >= num) num = n + 1;
+        if (str >> n && str.eof()) {
+            Generation gen;
+            gen.path = profileDir + "/" + *i;
+            gen.number = n;
+            struct stat st;
+            if (lstat(gen.path.c_str(), &st) != 0)
+                throw SysError(format("statting `%1%'") % gen.path);
+            gen.creationTime = st.st_mtime;
+            gens.push_back(gen);
+        }
     }
 
+    gens.sort(cmpGensByNumber);
+
+    return gens;
+}
+
+
+Path createGeneration(Path profile, Path outPath, Path drvPath)
+{
+    /* The new generation number should be higher than old the
+       previous ones. */
+    Generations gens = findGenerations(profile);
+    unsigned int num = gens.size() > 0 ? gens.front().number : 0;
+        
+    /* Create the new generation. */
     Path generation, gcrootSrc;
 
     while (1) {
diff --git a/src/nix-env/profiles.hh b/src/nix-env/profiles.hh
index 3d3c86e50b1a..f9480ed3f3d4 100644
--- a/src/nix-env/profiles.hh
+++ b/src/nix-env/profiles.hh
@@ -6,6 +6,20 @@
 #include "util.hh"
 
 
+struct Generation
+{
+    int number;
+    Path path;
+    time_t creationTime;
+};
+
+typedef list<Generation> Generations;
+
+
+/* Returns the list of currently present generations for the specified
+   profile, sorted by generation number. */
+Generations findGenerations(Path profile);
+    
 Path createGeneration(Path profile, Path outPath, Path drvPath);
 
 void switchLink(Path link, Path target);