about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am9
-rw-r--r--src/nix-help.txt36
-rw-r--r--src/nix.cc108
3 files changed, 116 insertions, 37 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 98d76b75364c..23e2429191ac 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,6 +33,13 @@ libshared_a_CXXFLAGS = \
  -DNIX_LOG_DIR=\"$(localstatedir)/log/nix\" \
  $(AM_CXXFLAGS)
 
+nix.o: nix-help.txt.hh
+
+%.hh: %
+	echo -n '"' > $@
+	sed 's|\(.*\)|\1\\n\\|' < $< >> $@
+	echo '"' >> $@
+
 install-data-local:
 	$(INSTALL) -d $(localstatedir)/nix
 	$(INSTALL) -d $(localstatedir)/nix/links
@@ -40,4 +47,4 @@ install-data-local:
 	$(INSTALL) -d $(prefix)/store
 	$(bindir)/nix --init
 
-EXTRA_DIST = *.hh *.h
\ No newline at end of file
+EXTRA_DIST = *.hh *.h
diff --git a/src/nix-help.txt b/src/nix-help.txt
new file mode 100644
index 000000000000..ecf9b5c16d25
--- /dev/null
+++ b/src/nix-help.txt
@@ -0,0 +1,36 @@
+nix [OPTIONS...] [ARGUMENTS...]
+
+Operations:
+
+  --install / -i: realise an fstate
+  --delete / -d: delete paths from the Nix store
+  --add / -A: copy a path to the Nix store
+  --query / -q: query information
+
+  --successor: register a successor expression
+  --substitute: register a substitute expression
+
+  --dump: dump a path as a Nix archive
+  --restore: restore a path from a Nix archive
+
+  --init: initialise the Nix database
+  --verify: verify Nix structures
+
+  --version: output version information
+  --help: display help
+
+Source selection for --install, --dump:
+
+  --path / -p: by file name  !!! -> path
+
+Query flags:
+
+  --list / -l: query the output paths (roots) of an fstate (default)
+  --refs / -r: query paths referenced by an fstate
+  --generators / -g: find expressions producing a subset of given ids
+  --expansion / -e: print a path containing id
+  --graph: print a dot graph rooted at given ids
+
+Options:
+
+  --verbose / -v: verbose operation (may be repeated)
diff --git a/src/nix.cc b/src/nix.cc
index 3345f983fba9..9e62fa3950ae 100644
--- a/src/nix.cc
+++ b/src/nix.cc
@@ -13,42 +13,14 @@ typedef void (* Operation) (Strings opFlags, Strings opArgs);
 static bool pathArgs = false;
 
 
-/* Nix syntax:
-
-   nix [OPTIONS...] [ARGUMENTS...]
-
-   Operations:
-
-     --install / -i: realise an fstate
-     --delete / -d: delete paths from the Nix store
-     --add / -A: copy a path to the Nix store
-     --query / -q: query information
-
-     --successor: register a successor expression
-     --substitute: register a substitute expression
-
-     --dump: dump a path as a Nix archive
-     --restore: restore a path from a Nix archive
-
-     --init: initialise the Nix database
-     --verify: verify Nix structures
-
-     --version: output version information
-     --help: display help
-
-   Source selection for --install, --dump:
-
-     --path / -p: by file name  !!! -> path
-
-   Query flags:
-
-     --list / -l: query the output paths (roots) of an fstate 
-     --refs / -r: query paths referenced by an fstate
-
-   Options:
+static void printHelp()
+{
+    cout <<
+#include "nix-help.txt.hh"
+        ;
+    exit(0);
+}
 
-     --verbose / -v: verbose operation
-*/
 
 
 static FSId argToId(const string & arg)
@@ -104,10 +76,17 @@ static void opAdd(Strings opFlags, Strings opArgs)
 }
 
 
+string dotQuote(const string & s)
+{
+    return "\"" + s + "\"";
+}
+
+
 /* Perform various sorts of queries. */
 static void opQuery(Strings opFlags, Strings opArgs)
 {
-    enum { qList, qRefs, qGenerators, qExpansion } query = qList;
+    enum { qList, qRefs, qGenerators, qExpansion, qGraph 
+    } query = qList;
 
     for (Strings::iterator i = opFlags.begin();
          i != opFlags.end(); i++)
@@ -115,6 +94,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
         else if (*i == "--refs" || *i == "-r") query = qRefs;
         else if (*i == "--generators" || *i == "-g") query = qGenerators;
         else if (*i == "--expansion" || *i == "-e") query = qExpansion;
+        else if (*i == "--graph") query = qGraph;
         else throw UsageError(format("unknown flag `%1%'") % *i);
 
     switch (query) {
@@ -170,6 +150,60 @@ static void opQuery(Strings opFlags, Strings opArgs)
             break;
         }
 
+        case qGraph: {
+
+            FSIds workList;
+
+            for (Strings::iterator i = opArgs.begin();
+                 i != opArgs.end(); i++)
+                workList.push_back(argToId(*i));
+
+            FSIdSet doneSet;
+            
+            cout << "digraph G {\n";
+
+            while (!workList.empty()) {
+                FSId id = workList.front();
+                workList.pop_front();
+
+                if (doneSet.find(id) == doneSet.end()) {
+                    doneSet.insert(id);
+                    
+                    FState fs = parseFState(termFromId(id));
+
+                    string label;
+                    
+                    if (fs.type == FState::fsDerive) {
+                        for (FSIds::iterator i = fs.derive.inputs.begin();
+                             i != fs.derive.inputs.end(); i++)
+                        {
+                            workList.push_back(*i);
+                            cout << dotQuote(*i) << " -> "
+                                 << dotQuote(id) << ";\n";
+                        }
+
+                        label = "derive";
+                        for (StringPairs::iterator i = fs.derive.env.begin();
+                             i != fs.derive.env.end(); i++)
+                            if (i->first == "name") label = i->second;
+                    }
+
+                    else if (fs.type == FState::fsSlice) {
+                        label = baseNameOf((*fs.slice.elems.begin()).path);
+                    }
+
+                    else abort();
+
+                    cout << dotQuote(id) << "[label = "
+                         << dotQuote(label)
+                         << "];\n";
+                }
+            }
+
+            cout << "}\n";
+            break;
+        }
+
         default:
             abort();
     }
@@ -309,6 +343,8 @@ void run(Strings args)
             pathArgs = true;
         else if (arg == "--verbose" || arg == "-v")
             verbosity = (Verbosity) ((int) verbosity + 1);
+        else if (arg == "--help")
+            printHelp();
         else if (arg[0] == '-')
             opFlags.push_back(arg);
         else