summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-07-21 14:46:01 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-07-21 14:46:01 +0000
commit49231fbe419d37717b0d951377fbfc9bf445dd55 (patch)
tree1802eacb403ad72f6b10805816a06c025116db1f
parent401452e57ae897d3e5829ed12bfcccac82548e91 (diff)
downloadguix-49231fbe419d37717b0d951377fbfc9bf445dd55.tar.gz
* Changes to the command line syntax of Nix.
* A function to find all Nix expressions whose output ids are
  completely contained in some set.  Useful for uploading relevant Nix
  expressions to a shared cache.

-rw-r--r--src/nix.cc128
-rw-r--r--src/normalise.cc49
-rw-r--r--src/normalise.hh6
-rw-r--r--src/store.cc9
-rw-r--r--src/store.hh3
5 files changed, 117 insertions, 78 deletions
diff --git a/src/nix.cc b/src/nix.cc
index ad4e6a468a..de60c28c55 100644
--- a/src/nix.cc
+++ b/src/nix.cc
@@ -9,9 +9,7 @@
 typedef void (* Operation) (Strings opFlags, Strings opArgs);
 
 
-typedef enum { atpHash, atpPath, atpUnknown } ArgType;
-
-static ArgType argType = atpUnknown;
+static bool pathArgs = false;
 
 
 /* Nix syntax:
@@ -39,12 +37,11 @@ static ArgType argType = atpUnknown;
 
    Source selection for --install, --dump:
 
-     --file / -f: by file name  !!! -> path
-     --hash / -h: by hash (identifier)
+     --path / -p: by file name  !!! -> path
 
    Query flags:
 
-     --path / -p: query the path of an fstate 
+     --list / -l: query the output paths (roots) of an fstate 
      --refs / -r: query paths referenced by an fstate
 
    Options:
@@ -53,39 +50,16 @@ static ArgType argType = atpUnknown;
 */
 
 
-/* Parse the `-f' / `-h' / flags, i.e., the type of arguments.  These
-   flags are deleted from the referenced vector. */
-static void getArgType(Strings & flags)
-{
-    for (Strings::iterator it = flags.begin();
-         it != flags.end(); )
-    {
-        string arg = *it;
-        ArgType tp;
-        if (arg == "--hash" || arg == "-h") tp = atpHash;
-        else if (arg == "--file" || arg == "-f") tp = atpPath;
-        else { it++; continue; }
-        if (argType != atpUnknown)
-            throw UsageError("only one argument type specified may be specified");
-        argType = tp;
-        it = flags.erase(it);
-    }
-    if (argType == atpUnknown)
-        throw UsageError("argument type not specified");
-}
-
-
 static FSId argToId(const string & arg)
 {
-    if (argType == atpHash)
+    if (!pathArgs)
         return parseHash(arg);
-    else if (argType == atpPath) {
-        string path;
+    else {
         FSId id;
-        addToStore(arg, path, id);
+        if (!queryPathId(arg, id))
+            throw Error(format("don't know id of `%1%'") % arg);
         return id;
     }
-    else abort();
 }
 
 
@@ -93,7 +67,6 @@ static FSId argToId(const string & arg)
    expressions. */
 static void opInstall(Strings opFlags, Strings opArgs)
 {
-    getArgType(opFlags);
     if (!opFlags.empty()) throw UsageError("unknown flag");
 
     for (Strings::iterator it = opArgs.begin();
@@ -117,7 +90,6 @@ static void opDelete(Strings opFlags, Strings opArgs)
    paths. */
 static void opAdd(Strings opFlags, Strings opArgs)
 {
-    getArgType(opFlags);
     if (!opFlags.empty()) throw UsageError("unknown flag");
 
     for (Strings::iterator it = opArgs.begin();
@@ -134,47 +106,61 @@ static void opAdd(Strings opFlags, Strings opArgs)
 /* Perform various sorts of queries. */
 static void opQuery(Strings opFlags, Strings opArgs)
 {
-    enum { qPath, qRefs, qUnknown } query = qPath;
-
-    for (Strings::iterator it = opFlags.begin();
-         it != opFlags.end(); )
-    {
-        string arg = *it;
-        if (arg == "--path" || arg == "-p") query = qPath;
-        else if (arg == "--refs" || arg == "-r") query = qRefs;
-        else { it++; continue; }
-        it = opFlags.erase(it);
-    }
-
-    getArgType(opFlags);
-    if (!opFlags.empty()) throw UsageError("unknown flag");
-
-    for (Strings::iterator it = opArgs.begin();
-         it != opArgs.end(); it++)
-    {
-        FSId id = argToId(*it);
-
-        switch (query) {
-
-        case qPath: {
-            Strings paths = fstatePaths(id, true);
-            for (Strings::iterator j = paths.begin(); 
-                 j != paths.end(); j++)
-                cout << format("%s\n") % *j;
+    enum { qPaths, qRefs, qGenerators, qUnknown } query = qPaths;
+
+    for (Strings::iterator i = opFlags.begin();
+         i != opFlags.end(); i++)
+        if (*i == "--list" || *i == "-l") query = qPaths;
+        else if (*i == "--refs" || *i == "-r") query = qRefs;
+        else if (*i == "--generators" || *i == "-g") query = qGenerators;
+        else throw UsageError(format("unknown flag `%1%'") % *i);
+
+    switch (query) {
+        
+        case qPaths: {
+            StringSet paths;
+            for (Strings::iterator i = opArgs.begin();
+                 i != opArgs.end(); i++)
+            {
+                Strings paths2 = fstatePaths(argToId(*i), true);
+                paths.insert(paths2.begin(), paths2.end());
+            }
+            for (StringSet::iterator i = paths.begin(); 
+                 i != paths.end(); i++)
+                cout << format("%s\n") % *i;
             break;
         }
 
         case qRefs: {
-            StringSet refs = fstateRefs(id);
-            for (StringSet::iterator j = refs.begin(); 
-                 j != refs.end(); j++)
-                cout << format("%s\n") % *j;
+            StringSet paths;
+            for (Strings::iterator i = opArgs.begin();
+                 i != opArgs.end(); i++)
+            {
+                Strings paths2 = fstateRefs(argToId(*i));
+                paths.insert(paths2.begin(), paths2.end());
+            }
+            for (StringSet::iterator i = paths.begin(); 
+                 i != paths.end(); i++)
+                cout << format("%s\n") % *i;
+            break;
+        }
+
+        case qGenerators: {
+            FSIds outIds;
+            for (Strings::iterator i = opArgs.begin();
+                 i != opArgs.end(); i++)
+                outIds.push_back(argToId(*i));
+
+            FSIds genIds = findGenerators(outIds);
+
+            for (FSIds::iterator i = genIds.begin(); 
+                 i != genIds.end(); i++)
+                cout << format("%s\n") % (string) *i;
             break;
         }
 
         default:
             abort();
-        }
     }
 }
 
@@ -224,16 +210,12 @@ struct StdoutSink : DumpSink
    output. */
 static void opDump(Strings opFlags, Strings opArgs)
 {
-    getArgType(opFlags);
     if (!opFlags.empty()) throw UsageError("unknown flag");
     if (opArgs.size() != 1) throw UsageError("only one argument allowed");
 
     StdoutSink sink;
     string arg = *opArgs.begin();
-    string path;
-    
-    if (argType == atpHash) path = expandId(parseHash(arg));
-    else if (argType == atpPath) path = arg;
+    string path = pathArgs ? arg : expandId(parseHash(arg));
 
     dumpPath(path, sink);
 }
@@ -313,6 +295,8 @@ void run(Strings args)
             op = opInit;
         else if (arg == "--verify")
             op = opVerify;
+        else if (arg == "--path" || arg == "-p")
+            pathArgs = true;
         else if (arg[0] == '-')
             opFlags.push_back(arg);
         else
diff --git a/src/normalise.cc b/src/normalise.cc
index bdeddf08dc..fcb9c4d0d3 100644
--- a/src/normalise.cc
+++ b/src/normalise.cc
@@ -248,18 +248,57 @@ Strings fstatePaths(const FSId & id, bool normalise)
 }
 
 
-StringSet fstateRefs(const FSId & id)
+Strings fstateRefs(const FSId & id)
 {
-    StringSet paths;
+    Strings paths;
     Slice slice = normaliseFState(id);
     for (SliceElems::const_iterator i = slice.elems.begin();
          i != slice.elems.end(); i++)
-        paths.insert(i->path);
+        paths.push_back(i->path);
     return paths;
 }
 
 
-void findGenerators(const FSIds & ids)
+FSIds findGenerators(const FSIds & _ids)
 {
-    
+    FSIdSet ids(_ids.begin(), _ids.end());
+    FSIds generators;
+
+    /* !!! hack; for performance, we just look at the rhs of successor
+       mappings, since we know that those are Nix expressions. */
+
+    Strings sucs;
+    enumDB(nixDB, dbSuccessors, sucs);
+
+    for (Strings::iterator i = sucs.begin();
+         i != sucs.end(); i++)
+    {
+        string s;
+        queryDB(nixDB, dbSuccessors, *i, s);
+        FSId id = parseHash(s);
+
+        FState fs;
+        try {
+            /* !!! should substitutes be used? */
+            fs = parseFState(termFromId(id));
+        } catch (...) { /* !!! only catch parse errors */
+            continue;
+        }
+
+        if (fs.type != FState::fsSlice) continue;
+        
+        bool okay = true;
+        for (SliceElems::const_iterator i = fs.slice.elems.begin();
+             i != fs.slice.elems.end(); i++)
+            if (ids.find(i->id) == ids.end()) {
+                okay = false;
+                break;
+            }
+        
+        if (!okay) continue;
+        
+        generators.push_back(id);
+    }
+
+    return generators;
 }
diff --git a/src/normalise.hh b/src/normalise.hh
index 85dbca5ef5..49f9e68eee 100644
--- a/src/normalise.hh
+++ b/src/normalise.hh
@@ -16,7 +16,11 @@ void realiseSlice(const Slice & slice);
 Strings fstatePaths(const FSId & id, bool normalise);
 
 /* Get the list of paths referenced by the given fstate-expression. */
-StringSet fstateRefs(const FSId & id);
+Strings fstateRefs(const FSId & id);
+
+/* Return the list of the ids of all known fstate-expressions whose
+   output ids are completely contained in `ids'. */
+FSIds findGenerators(const FSIds & ids);
 
 /* Register a successor. */
 void registerSuccessor(const FSId & id1, const FSId & id2);
diff --git a/src/store.cc b/src/store.cc
index 6f1a2fc39d..6157b4bc22 100644
--- a/src/store.cc
+++ b/src/store.cc
@@ -148,6 +148,15 @@ void unregisterPath(const string & _path)
 }
 
 
+bool queryPathId(const string & path, FSId & id)
+{
+    string s;
+    if (!queryDB(nixDB, dbPath2Id, path, s)) return false;
+    id = parseHash(s);
+    return true;
+}
+
+
 bool isInPrefix(const string & path, const string & _prefix)
 {
     string prefix = canonPath(_prefix + "/");
diff --git a/src/store.hh b/src/store.hh
index 78d5529e77..faac760099 100644
--- a/src/store.hh
+++ b/src/store.hh
@@ -20,6 +20,9 @@ void registerSubstitute(const FSId & srcId, const FSId & subId);
 /* Register a path keyed on its id. */
 void registerPath(const string & path, const FSId & id);
 
+/* Query the id of a path. */
+bool queryPathId(const string & path, FSId & id);
+
 /* Return a path whose contents have the given hash.  If target is
    not empty, ensure that such a path is realised in target (if
    necessary by copying from another location).  If prefix is not