* nix -> nix-store, fix -> nix-instantiate.
This commit is contained in:
		
							parent
							
								
									ce92d1bf14
								
							
						
					
					
						commit
						b1117ef29d
					
				
					 21 changed files with 303 additions and 11 deletions
				
			
		
							
								
								
									
										27
									
								
								src/nix-store/Makefile.am
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/nix-store/Makefile.am
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| bin_PROGRAMS = nix-store | ||||
| 
 | ||||
| nix_store_SOURCES = nix.cc dotgraph.cc | ||||
| nix_store_LDADD = ../libmain/libmain.a ../libstore/libstore.a ../libutil/libutil.a \ | ||||
|  ../boost/format/libformat.a -L../../externals/inst/lib -ldb_cxx -lATerm | ||||
| 
 | ||||
| nix.o: nix-help.txt.hh | ||||
| 
 | ||||
| %.hh: % | ||||
| 	echo -n '"' > $@ | ||||
| 	sed 's|\(.*\)|\1\\n\\|' < $< >> $@ | ||||
| 	echo '"' >> $@ | ||||
| 
 | ||||
| AM_CXXFLAGS = \ | ||||
|  -I.. -I../../externals/inst/include -I../libutil -I../libstore -I../libmain | ||||
| 
 | ||||
| install-data-local: | ||||
| 	$(INSTALL) -d $(localstatedir)/nix | ||||
| 	$(INSTALL) -d $(localstatedir)/nix/db | ||||
| 	$(INSTALL) -d $(localstatedir)/nix/links | ||||
| 	rm -f $(prefix)/current | ||||
| 	ln -sf $(localstatedir)/nix/links/current $(prefix)/current | ||||
| 	$(INSTALL) -d $(localstatedir)/log/nix | ||||
| 	$(INSTALL) -d $(prefix)/store | ||||
| 	$(bindir)/nix-store --init | ||||
| 
 | ||||
| EXTRA_DIST = *.hh | ||||
							
								
								
									
										135
									
								
								src/nix-store/dotgraph.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/nix-store/dotgraph.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,135 @@ | |||
| #include "dotgraph.hh" | ||||
| #include "normalise.hh" | ||||
| 
 | ||||
| 
 | ||||
| static string dotQuote(const string & s) | ||||
| { | ||||
|     return "\"" + s + "\""; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static string nextColour() | ||||
| { | ||||
|     static int n = 0; | ||||
|     static string colours[] = | ||||
| 	{ "black", "red", "green", "blue" | ||||
| 	, "magenta", "burlywood" }; | ||||
|     return colours[n++ % (sizeof(colours) / sizeof(string))]; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static string makeEdge(const string & src, const string & dst) | ||||
| { | ||||
|     format f = format("%1% -> %2% [color = %3%];\n") | ||||
| 	% dotQuote(src) % dotQuote(dst) % dotQuote(nextColour()); | ||||
|     return f.str(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static string makeNode(const string & id, const string & label, | ||||
|     const string & colour) | ||||
| { | ||||
|     format f = format("%1% [label = %2%, shape = box, " | ||||
| 	"style = filled, fillcolor = %3%];\n") | ||||
| 	% dotQuote(id) % dotQuote(label) % dotQuote(colour); | ||||
|     return f.str(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static string symbolicName(const string & path) | ||||
| { | ||||
|     string p = baseNameOf(path); | ||||
|     if (isHash(string(p, 0, Hash::hashSize * 2)) &&  | ||||
| 	p[Hash::hashSize * 2] == '-') | ||||
| 	p = string(p, Hash::hashSize * 2 + 1); | ||||
|     return p; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| string pathLabel(const Path & nePath, const string & elemPath) | ||||
| { | ||||
|     return (string) nePath + "-" + elemPath; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void printClosure(const Path & nePath, const StoreExpr & fs) | ||||
| { | ||||
|     PathSet workList(fs.closure.roots); | ||||
|     PathSet doneSet; | ||||
| 
 | ||||
|     for (PathSet::iterator i = workList.begin(); i != workList.end(); i++) { | ||||
| 	cout << makeEdge(pathLabel(nePath, *i), nePath); | ||||
|     } | ||||
| 
 | ||||
|     while (!workList.empty()) { | ||||
| 	Path path = *(workList.begin()); | ||||
| 	workList.erase(path); | ||||
| 
 | ||||
| 	if (doneSet.find(path) == doneSet.end()) { | ||||
| 	    doneSet.insert(path); | ||||
| 
 | ||||
| 	    ClosureElems::const_iterator elem = fs.closure.elems.find(path); | ||||
| 	    if (elem == fs.closure.elems.end()) | ||||
| 		throw Error(format("bad closure, missing path `%1%'") % path); | ||||
| 
 | ||||
| 	    for (StringSet::const_iterator i = elem->second.refs.begin(); | ||||
| 		 i != elem->second.refs.end(); i++) | ||||
| 	    { | ||||
| 		workList.insert(*i); | ||||
| 		cout << makeEdge(pathLabel(nePath, *i), pathLabel(nePath, path)); | ||||
| 	    } | ||||
| 
 | ||||
| 	    cout << makeNode(pathLabel(nePath, path),  | ||||
| 		symbolicName(path), "#ff0000"); | ||||
| 	} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void printDotGraph(const PathSet & roots) | ||||
| { | ||||
|     PathSet workList(roots); | ||||
|     PathSet doneSet; | ||||
|              | ||||
|     cout << "digraph G {\n"; | ||||
| 
 | ||||
|     while (!workList.empty()) { | ||||
| 	Path nePath = *(workList.begin()); | ||||
| 	workList.erase(nePath); | ||||
| 
 | ||||
| 	if (doneSet.find(nePath) == doneSet.end()) { | ||||
| 	    doneSet.insert(nePath); | ||||
| 
 | ||||
| 	    StoreExpr ne = storeExprFromPath(nePath); | ||||
| 
 | ||||
| 	    string label, colour; | ||||
|                      | ||||
| 	    if (ne.type == StoreExpr::neDerivation) { | ||||
| 		for (PathSet::iterator i = ne.derivation.inputs.begin(); | ||||
| 		     i != ne.derivation.inputs.end(); i++) | ||||
| 		{ | ||||
| 		    workList.insert(*i); | ||||
| 		    cout << makeEdge(*i, nePath); | ||||
| 		} | ||||
| 
 | ||||
| 		label = "derivation"; | ||||
| 		colour = "#00ff00"; | ||||
| 		for (StringPairs::iterator i = ne.derivation.env.begin(); | ||||
| 		     i != ne.derivation.env.end(); i++) | ||||
| 		    if (i->first == "name") label = i->second; | ||||
| 	    } | ||||
| 
 | ||||
| 	    else if (ne.type == StoreExpr::neClosure) { | ||||
| 		label = "<closure>"; | ||||
| 		colour = "#00ffff"; | ||||
| 		printClosure(nePath, ne); | ||||
| 	    } | ||||
| 
 | ||||
| 	    else abort(); | ||||
| 
 | ||||
| 	    cout << makeNode(nePath, label, colour); | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|     cout << "}\n"; | ||||
| } | ||||
							
								
								
									
										8
									
								
								src/nix-store/dotgraph.hh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/nix-store/dotgraph.hh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| #ifndef __DOTGRAPH_H | ||||
| #define __DOTGRAPH_H | ||||
| 
 | ||||
| #include "storeexpr.hh" | ||||
| 
 | ||||
| void printDotGraph(const PathSet & roots); | ||||
| 
 | ||||
| #endif /* !__DOTGRAPH_H */ | ||||
							
								
								
									
										34
									
								
								src/nix-store/nix-help.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/nix-store/nix-help.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| nix-store [OPTIONS...] [ARGUMENTS...] | ||||
| 
 | ||||
| `nix-store' is a tool to manipulate the Nix store. | ||||
| 
 | ||||
| Operations: | ||||
| 
 | ||||
|   --realise / -r: realise a Nix expression | ||||
|   --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 | ||||
| 
 | ||||
| Query flags: | ||||
| 
 | ||||
|   --list / -l: query the output paths (roots) of a Nix expression (default) | ||||
|   --requisites / -R: print all paths necessary to realise expression | ||||
|   --predecessors: print predecessors of a Nix expression | ||||
|   --graph: print a dot graph rooted at given ids | ||||
| 
 | ||||
| Options: | ||||
| 
 | ||||
|   --verbose / -v: verbose operation (may be repeated) | ||||
|   --keep-failed / -K: keep temporary directories of failed builds | ||||
							
								
								
									
										304
									
								
								src/nix-store/nix.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								src/nix-store/nix.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,304 @@ | |||
| #include <iostream> | ||||
| #include <sstream> | ||||
| 
 | ||||
| #include "globals.hh" | ||||
| #include "normalise.hh" | ||||
| #include "archive.hh" | ||||
| #include "shared.hh" | ||||
| #include "dotgraph.hh" | ||||
| 
 | ||||
| 
 | ||||
| typedef void (* Operation) (Strings opFlags, Strings opArgs); | ||||
| 
 | ||||
| 
 | ||||
| static void printHelp() | ||||
| { | ||||
|     cout << | ||||
| #include "nix-help.txt.hh" | ||||
|         ; | ||||
|     exit(0); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| static Path checkPath(const Path & arg) | ||||
| { | ||||
|     return arg; /* !!! check that arg is in the store */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Realise paths from the given store expressions. */ | ||||
| static void opRealise(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     if (!opFlags.empty()) throw UsageError("unknown flag"); | ||||
| 
 | ||||
|     for (Strings::iterator i = opArgs.begin(); | ||||
|          i != opArgs.end(); i++) | ||||
|     { | ||||
|         Path nfPath = normaliseStoreExpr(checkPath(*i)); | ||||
|         realiseClosure(nfPath); | ||||
|         cout << format("%1%\n") % (string) nfPath; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Delete a path in the Nix store directory. */ | ||||
| static void opDelete(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     if (!opFlags.empty()) throw UsageError("unknown flag"); | ||||
| 
 | ||||
|     for (Strings::iterator it = opArgs.begin(); | ||||
|          it != opArgs.end(); it++) | ||||
|         deleteFromStore(checkPath(*it)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Add paths to the Nix values directory and print the hashes of those
 | ||||
|    paths. */ | ||||
| static void opAdd(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     if (!opFlags.empty()) throw UsageError("unknown flag"); | ||||
| 
 | ||||
|     for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++) | ||||
|         cout << format("%1%\n") % addToStore(*i); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Path maybeNormalise(const Path & ne, bool normalise) | ||||
| { | ||||
|     return normalise ? normaliseStoreExpr(ne) : ne; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Perform various sorts of queries. */ | ||||
| static void opQuery(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     enum { qList, qRequisites, qPredecessors, qGraph  | ||||
|     } query = qList; | ||||
|     bool normalise = false; | ||||
|     bool includeExprs = true; | ||||
|     bool includeSuccessors = false; | ||||
| 
 | ||||
|     for (Strings::iterator i = opFlags.begin(); | ||||
|          i != opFlags.end(); i++) | ||||
|         if (*i == "--list" || *i == "-l") query = qList; | ||||
|         else if (*i == "--requisites" || *i == "-R") query = qRequisites; | ||||
|         else if (*i == "--predecessors") query = qPredecessors; | ||||
|         else if (*i == "--graph") query = qGraph; | ||||
|         else if (*i == "--normalise" || *i == "-n") normalise = true; | ||||
|         else if (*i == "--exclude-exprs") includeExprs = false; | ||||
|         else if (*i == "--include-successors") includeSuccessors = true; | ||||
|         else throw UsageError(format("unknown flag `%1%'") % *i); | ||||
| 
 | ||||
|     switch (query) { | ||||
|          | ||||
|         case qList: { | ||||
|             for (Strings::iterator i = opArgs.begin(); | ||||
|                  i != opArgs.end(); i++) | ||||
|             { | ||||
|                 StringSet paths = storeExprRoots( | ||||
|                     maybeNormalise(checkPath(*i), normalise)); | ||||
|                 for (StringSet::iterator j = paths.begin();  | ||||
|                      j != paths.end(); j++) | ||||
|                     cout << format("%s\n") % *j; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case qRequisites: { | ||||
|             StringSet paths; | ||||
|             for (Strings::iterator i = opArgs.begin(); | ||||
|                  i != opArgs.end(); i++) | ||||
|             { | ||||
|                 StringSet paths2 = storeExprRequisites( | ||||
|                     maybeNormalise(checkPath(*i), normalise), | ||||
|                     includeExprs, includeSuccessors); | ||||
|                 paths.insert(paths2.begin(), paths2.end()); | ||||
|             } | ||||
|             for (StringSet::iterator i = paths.begin();  | ||||
|                  i != paths.end(); i++) | ||||
|                 cout << format("%s\n") % *i; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case qPredecessors: { | ||||
|             for (Strings::iterator i = opArgs.begin(); | ||||
|                  i != opArgs.end(); i++) | ||||
|             { | ||||
|                 Paths preds = queryPredecessors(checkPath(*i)); | ||||
|                 for (Paths::iterator j = preds.begin(); | ||||
|                      j != preds.end(); j++) | ||||
|                     cout << format("%s\n") % *j; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case qGraph: { | ||||
|             PathSet roots; | ||||
|             for (Strings::iterator i = opArgs.begin(); | ||||
|                  i != opArgs.end(); i++) | ||||
|                 roots.insert(maybeNormalise(checkPath(*i), normalise)); | ||||
| 	    printDotGraph(roots); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         default: | ||||
|             abort(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void opSuccessor(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     if (!opFlags.empty()) throw UsageError("unknown flag"); | ||||
|     if (opArgs.size() % 2) throw UsageError("expecting even number of arguments"); | ||||
| 
 | ||||
|     Transaction txn; | ||||
|     createStoreTransaction(txn); | ||||
|     for (Strings::iterator i = opArgs.begin(); | ||||
|          i != opArgs.end(); ) | ||||
|     { | ||||
|         Path path1 = checkPath(*i++); | ||||
|         Path path2 = checkPath(*i++); | ||||
|         registerSuccessor(txn, path1, path2); | ||||
|     } | ||||
|     txn.commit(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void opSubstitute(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     if (!opFlags.empty()) throw UsageError("unknown flag"); | ||||
|     if (opArgs.size() % 2) throw UsageError("expecting even number of arguments"); | ||||
|      | ||||
|     for (Strings::iterator i = opArgs.begin(); | ||||
|          i != opArgs.end(); ) | ||||
|     { | ||||
|         Path src = checkPath(*i++); | ||||
|         Path sub = checkPath(*i++); | ||||
|         registerSubstitute(src, sub); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* A sink that writes dump output to stdout. */ | ||||
| struct StdoutSink : DumpSink | ||||
| { | ||||
|     virtual void operator () | ||||
|         (const unsigned char * data, unsigned int len) | ||||
|     { | ||||
|         writeFull(STDOUT_FILENO, data, len); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /* Dump a path as a Nix archive.  The archive is written to standard
 | ||||
|    output. */ | ||||
| static void opDump(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     if (!opFlags.empty()) throw UsageError("unknown flag"); | ||||
|     if (opArgs.size() != 1) throw UsageError("only one argument allowed"); | ||||
| 
 | ||||
|     StdoutSink sink; | ||||
|     string path = *opArgs.begin(); | ||||
|     dumpPath(path, sink); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* A source that read restore intput to stdin. */ | ||||
| struct StdinSource : RestoreSource | ||||
| { | ||||
|     virtual void operator () (unsigned char * data, unsigned int len) | ||||
|     { | ||||
|         readFull(STDIN_FILENO, data, len); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /* Restore a value from a Nix archive.  The archive is written to
 | ||||
|    standard input. */ | ||||
| static void opRestore(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     if (!opFlags.empty()) throw UsageError("unknown flag"); | ||||
|     if (opArgs.size() != 1) throw UsageError("only one argument allowed"); | ||||
| 
 | ||||
|     StdinSource source; | ||||
|     restorePath(*opArgs.begin(), source); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Initialise the Nix databases. */ | ||||
| static void opInit(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     if (!opFlags.empty()) throw UsageError("unknown flag"); | ||||
|     if (!opArgs.empty()) | ||||
|         throw UsageError("--init does not have arguments"); | ||||
|     initDB(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Verify the consistency of the Nix environment. */ | ||||
| static void opVerify(Strings opFlags, Strings opArgs) | ||||
| { | ||||
|     verifyStore(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Scan the arguments; find the operation, set global flags, put all
 | ||||
|    other flags in a list, and put all other arguments in another | ||||
|    list. */ | ||||
| void run(Strings args) | ||||
| { | ||||
|     Strings opFlags, opArgs; | ||||
|     Operation op = 0; | ||||
| 
 | ||||
|     for (Strings::iterator it = args.begin(); it != args.end(); ) | ||||
|     { | ||||
|         string arg = *it++; | ||||
| 
 | ||||
|         Operation oldOp = op; | ||||
| 
 | ||||
|         if (arg == "--realise" || arg == "-r") | ||||
|             op = opRealise; | ||||
|         else if (arg == "--delete" || arg == "-d") | ||||
|             op = opDelete; | ||||
|         else if (arg == "--add" || arg == "-A") | ||||
|             op = opAdd; | ||||
|         else if (arg == "--query" || arg == "-q") | ||||
|             op = opQuery; | ||||
|         else if (arg == "--successor") | ||||
|             op = opSuccessor; | ||||
|         else if (arg == "--substitute") | ||||
|             op = opSubstitute; | ||||
|         else if (arg == "--dump") | ||||
|             op = opDump; | ||||
|         else if (arg == "--restore") | ||||
|             op = opRestore; | ||||
|         else if (arg == "--init") | ||||
|             op = opInit; | ||||
|         else if (arg == "--verify") | ||||
|             op = opVerify; | ||||
|         else if (arg == "--verbose" || arg == "-v") | ||||
|             verbosity = (Verbosity) ((int) verbosity + 1); | ||||
|         else if (arg == "--keep-failed" || arg == "-K") | ||||
|             keepFailed = true; | ||||
|         else if (arg == "--help") | ||||
|             printHelp(); | ||||
|         else if (arg[0] == '-') | ||||
|             opFlags.push_back(arg); | ||||
|         else | ||||
|             opArgs.push_back(arg); | ||||
| 
 | ||||
|         if (oldOp && oldOp != op) | ||||
|             throw UsageError("only one operation may be specified"); | ||||
|     } | ||||
| 
 | ||||
|     if (!op) throw UsageError("no operation specified"); | ||||
| 
 | ||||
|     openDB(); | ||||
| 
 | ||||
|     op(opFlags, opArgs); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| string programId = "nix"; | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue