From dfc9c64ead7f24d51ed1a232e4b3ecafa8384f2e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 18 Nov 2003 12:06:07 +0000 Subject: * "Fix expression" -> "Nix expression". * More refactoring. --- src/Makefile.am | 2 +- src/bin2c/Makefile.am | 3 + src/bin2c/bin2c.c | 23 +++ src/nix-instantiate/Makefile.am | 12 +- src/nix-instantiate/bin2c.c | 23 --- src/nix-instantiate/eval.hh | 2 +- src/nix-instantiate/fix.cc | 117 ---------------- src/nix-instantiate/fix.sdf | 203 --------------------------- src/nix-instantiate/fixexpr.cc | 215 ---------------------------- src/nix-instantiate/fixexpr.hh | 75 ---------- src/nix-instantiate/main.cc | 117 ++++++++++++++++ src/nix-instantiate/nix.sdf | 203 +++++++++++++++++++++++++++ src/nix-instantiate/nixexpr.cc | 215 ++++++++++++++++++++++++++++ src/nix-instantiate/nixexpr.hh | 75 ++++++++++ src/nix-instantiate/parser.cc | 9 +- src/nix-instantiate/parser.hh | 2 +- src/nix-store/Makefile.am | 8 +- src/nix-store/help.txt | 34 +++++ src/nix-store/main.cc | 303 +++++++++++++++++++++++++++++++++++++++ src/nix-store/nix-help.txt | 34 ----- src/nix-store/nix.cc | 304 ---------------------------------------- 21 files changed, 987 insertions(+), 992 deletions(-) create mode 100644 src/bin2c/Makefile.am create mode 100644 src/bin2c/bin2c.c delete mode 100644 src/nix-instantiate/bin2c.c delete mode 100644 src/nix-instantiate/fix.cc delete mode 100644 src/nix-instantiate/fix.sdf delete mode 100644 src/nix-instantiate/fixexpr.cc delete mode 100644 src/nix-instantiate/fixexpr.hh create mode 100644 src/nix-instantiate/main.cc create mode 100644 src/nix-instantiate/nix.sdf create mode 100644 src/nix-instantiate/nixexpr.cc create mode 100644 src/nix-instantiate/nixexpr.hh create mode 100644 src/nix-store/help.txt create mode 100644 src/nix-store/main.cc delete mode 100644 src/nix-store/nix-help.txt delete mode 100644 src/nix-store/nix.cc diff --git a/src/Makefile.am b/src/Makefile.am index e35b82a889f0..1f2aafcdba6d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1 +1 @@ -SUBDIRS = boost libutil libstore libmain nix-store nix-hash nix-instantiate +SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash nix-instantiate diff --git a/src/bin2c/Makefile.am b/src/bin2c/Makefile.am new file mode 100644 index 000000000000..bdd58808a159 --- /dev/null +++ b/src/bin2c/Makefile.am @@ -0,0 +1,3 @@ +noinst_PROGRAMS = bin2c + +bin2c_SOURCES = bin2c.c diff --git a/src/bin2c/bin2c.c b/src/bin2c/bin2c.c new file mode 100644 index 000000000000..18bf81d69e25 --- /dev/null +++ b/src/bin2c/bin2c.c @@ -0,0 +1,23 @@ +#include +#include +#include + +void print(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + if (vprintf(format, ap) < 0) abort(); + va_end(ap); +} + +int main(int argc, char * * argv) +{ + int c; + if (argc != 2) abort(); + print("static unsigned char %s[] = {", argv[1]); + while ((c = getchar()) != EOF) { + print("0x%02x, ", (unsigned char) c); + } + print("};\n"); + return 0; +} diff --git a/src/nix-instantiate/Makefile.am b/src/nix-instantiate/Makefile.am index cdaec1390d9e..3a09add0c645 100644 --- a/src/nix-instantiate/Makefile.am +++ b/src/nix-instantiate/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS = nix-instantiate -nix_instantiate_SOURCES = fixexpr.cc parser.cc eval.cc primops.cc fix.cc +nix_instantiate_SOURCES = nixexpr.cc parser.cc eval.cc primops.cc main.cc nix_instantiate_LDADD = ../libmain/libmain.a ../libstore/libstore.a ../libutil/libutil.a \ ../boost/format/libformat.a -L../../externals/inst/lib -ldb_cxx \ -lsglr -lATB -lconversion -lasfix2 -lmept -lATerm @@ -13,14 +13,10 @@ AM_CXXFLAGS = \ parser.o: parse-table.h -parse-table.h: fix.tbl bin2c - ./bin2c fixParseTable < $< > $@ || (rm $@ && exit 1) - -noinst_PROGRAMS = bin2c - -bin2c_SOURCES = bin2c.c +parse-table.h: nix.tbl + ../bin2c/bin2c nixParseTable < $< > $@ || (rm $@ && exit 1) %.tbl: %.sdf ../../externals/inst/bin/sdf2table -i $< -o $@ -CLEANFILES = parse-table.h fix.tbl +CLEANFILES = parse-table.h nix.tbl diff --git a/src/nix-instantiate/bin2c.c b/src/nix-instantiate/bin2c.c deleted file mode 100644 index 18bf81d69e25..000000000000 --- a/src/nix-instantiate/bin2c.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include - -void print(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - if (vprintf(format, ap) < 0) abort(); - va_end(ap); -} - -int main(int argc, char * * argv) -{ - int c; - if (argc != 2) abort(); - print("static unsigned char %s[] = {", argv[1]); - while ((c = getchar()) != EOF) { - print("0x%02x, ", (unsigned char) c); - } - print("};\n"); - return 0; -} diff --git a/src/nix-instantiate/eval.hh b/src/nix-instantiate/eval.hh index 061c840a7576..0bc052676deb 100644 --- a/src/nix-instantiate/eval.hh +++ b/src/nix-instantiate/eval.hh @@ -5,7 +5,7 @@ #include "aterm.hh" #include "hash.hh" -#include "fixexpr.hh" +#include "nixexpr.hh" typedef map DrvPaths; diff --git a/src/nix-instantiate/fix.cc b/src/nix-instantiate/fix.cc deleted file mode 100644 index e407aaf44346..000000000000 --- a/src/nix-instantiate/fix.cc +++ /dev/null @@ -1,117 +0,0 @@ -#include -#include - -#include "globals.hh" -#include "normalise.hh" -#include "shared.hh" -#include "eval.hh" - - -#if 0 -static Path searchPath(const Paths & searchDirs, const Path & relPath) -{ - if (string(relPath, 0, 1) == "/") return relPath; - - for (Paths::const_iterator i = searchDirs.begin(); - i != searchDirs.end(); i++) - { - Path path = *i + "/" + relPath; - if (pathExists(path)) return path; - } - - throw Error( - format("path `%1%' not found in any of the search directories") - % relPath); -} -#endif - - -static Expr evalStdin(EvalState & state) -{ - startNest(nest, lvlTalkative, format("evaluating standard input")); - Expr e = ATreadFromFile(stdin); - if (!e) - throw Error(format("unable to read a term from stdin")); - return evalExpr(state, e); -} - - -static void printNixExpr(EvalState & state, Expr e) -{ - ATMatcher m; - ATermList es; - - if (atMatch(m, e) >> "Attrs" >> es) { - Expr a = queryAttr(e, "type"); - if (a && evalString(state, a) == "derivation") { - a = queryAttr(e, "drvPath"); - if (a) { - cout << format("%1%\n") % evalPath(state, a); - return; - } - } - } - - if (ATgetType(e) == AT_LIST) { - for (ATermIterator i((ATermList) e); i; ++i) - printNixExpr(state, evalExpr(state, *i)); - return; - } - - throw badTerm("top level does not evaluate to one or more Nix expressions", e); -} - - -void run(Strings args) -{ - EvalState state; - Strings files; - bool readStdin = false; - -#if 0 - state.searchDirs.push_back("."); - state.searchDirs.push_back(nixDataDir + "/fix"); -#endif - - for (Strings::iterator it = args.begin(); - it != args.end(); ) - { - string arg = *it++; - -#if 0 - if (arg == "--includedir" || arg == "-I") { - if (it == args.end()) - throw UsageError(format("argument required in `%1%'") % arg); - state.searchDirs.push_back(*it++); - } - else -#endif - if (arg == "--verbose" || arg == "-v") - verbosity = (Verbosity) ((int) verbosity + 1); - else if (arg == "-") - readStdin = true; - else if (arg[0] == '-') - throw UsageError(format("unknown flag `%1%`") % arg); - else - files.push_back(arg); - } - - openDB(); - - if (readStdin) { - Expr e = evalStdin(state); - printNixExpr(state, e); - } - - for (Strings::iterator it = files.begin(); - it != files.end(); it++) - { - Expr e = evalFile(state, absPath(*it)); - printNixExpr(state, e); - } - - printEvalStats(state); -} - - -string programId = "fix"; diff --git a/src/nix-instantiate/fix.sdf b/src/nix-instantiate/fix.sdf deleted file mode 100644 index 54f5d5266f79..000000000000 --- a/src/nix-instantiate/fix.sdf +++ /dev/null @@ -1,203 +0,0 @@ -definition - -module Main -imports Fix - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Top level syntax. - -module Fix -imports Fix-Exprs Fix-Layout - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Expressions. - -module Fix-Exprs -imports Fix-Lexicals URI -exports - sorts Expr Bind Formal - context-free syntax - - Id -> Expr {cons("Var")} - - Int -> Expr {cons("Int")} - - Str -> Expr {cons("Str")} - - Uri -> Expr {cons("Uri")} - - Path -> Expr {cons("Path")} - - "(" Expr ")" -> Expr {bracket} - - Expr Expr -> Expr {cons("Call"), left} - - "{" {Formal ","}* "}" ":" Expr -> Expr {cons("Function"), right} - Id -> Formal {cons("NoDefFormal")} - Id "?" Expr -> Formal {cons("DefFormal")} - - "assert" Expr ";" Expr -> Expr {cons("Assert"), right} - - "rec" "{" Binds "}" -> Expr {cons("Rec")} - "let" "{" Binds "}" -> Expr {cons("LetRec")} - "{" Binds "}" -> Expr {cons("Attrs")} - - Id "=" Expr -> Bind {cons("Bind")} - {Bind ";"}* -> Binds - Bind ";" -> BindSemi - BindSemi* -> Binds - - "[" ExprList "]" -> Expr {cons("List")} - "" -> ExprList {cons("ExprNil")} - Expr ExprList -> ExprList {cons("ExprCons")} - - Expr "." Id -> Expr {cons("Select")} - - "if" Expr "then" Expr "else" Expr -> Expr {cons("If")} - - Expr "==" Expr -> Expr {cons("OpEq"), non-assoc} - Expr "!=" Expr -> Expr {cons("OpNEq"), non-assoc} - - "!" Expr -> Expr {cons("OpNot")} - Expr "&&" Expr -> Expr {cons("OpAnd"), right} - Expr "||" Expr -> Expr {cons("OpOr"), right} - Expr "->" Expr -> Expr {cons("OpImpl"), right} - - Bool -> Expr {cons("Bool")} - - context-free priorities - - Expr "." Id -> Expr - > Expr ExprList -> ExprList - > Expr Expr -> Expr - > "!" Expr -> Expr - > Expr "==" Expr -> Expr - > Expr "!=" Expr -> Expr - > Expr "&&" Expr -> Expr - > Expr "||" Expr -> Expr - > Expr "->" Expr -> Expr - > "assert" Expr ";" Expr -> Expr - > "{" {Formal ","}* "}" ":" Expr -> Expr - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Lexical syntax. - -module Fix-Lexicals -exports - sorts Id Path - lexical syntax - [a-zA-Z\_][a-zA-Z0-9\_\']* -> Id - "rec" -> Id {reject} - "let" -> Id {reject} - "if" -> Id {reject} - "then" -> Id {reject} - "else" -> Id {reject} - "true" -> Id {reject} - "false" -> Id {reject} - "assert" -> Id {reject} - - [0-9]+ -> Int - - "\"" ~[\n\"]* "\"" -> Str - - PathComp ("/" PathComp)+ -> Path - [a-zA-Z0-9\.\_\-\+]+ -> PathComp - - "true" -> Bool - "false" -> Bool - - lexical restrictions - Id -/- [a-zA-Z0-9\_\'] - Int -/- [0-9] - Path -/- [a-zA-Z0-9\.\_\-\+\/] - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% URIs (RFC 2396, appendix A). - -module URI -exports - sorts Uri - lexical syntax - Uscheme ":" (Uhierpath | Uopaquepath) -> Uri - - (Unetpath | Uabspath) ("?" Uquery)? -> Uhierpath - Uuricnoslash Uuric* -> Uopaquepath - - Uunreserved | Uescaped | [\;\?\:\@\&\=\+\$\,] -> Uuricnoslash - - "//" Uauthority Uabspath? -> Unetpath - "/" Upathsegments -> Uabspath - "//" Uuric* -> Uabspath {reject} - Urelsegment Uabspath? -> Urelpath - - (Uunreserved | Uescaped | [\;\@\&\=\+\$\,])+ -> Urelsegment - - Ualpha (Ualpha | Udigit | [\+\-\.])* -> Uscheme - - Userver | Uregname -> Uauthority - - (Uunreserved | Uescaped | [\$\,\;\:\@\&\=\+])+ -> Uregname - - ((Uuserinfo "@") Uhostport) -> Userver - (Uunreserved | Uescaped | [\;\:\&\=\+\$\,])* -> Uuserinfo - - Uhost (":" Uport)? -> Uhostport - Uhostname | UIPv4address -> Uhost - (Udomainlabel ".")+ Utoplabel "."? -> Uhostname - Ualphanum | Ualphanum (Ualphanum | "-")* Ualphanum -> Udomainlabel - Ualpha | Ualpha (Ualphanum | "-")* Ualphanum -> Utoplabel - Udigit+ "." Udigit+ "." Udigit+ "." Udigit+ -> UIPv4address - Udigit* -> Uport - - Uabspath | Uopaquepart -> Upath - Usegment ("/" Usegment)* -> Upathsegments - Upchar* (";" Uparam)* -> Usegment - Upchar* -> Uparam - Uunreserved | Uescaped | [\:\@\&\=\+\$\,] -> Upchar - - Uuric* -> Uquery - - Uuric* -> Ufragment - - Ureserved | Uunreserved | Uescaped -> Uuric - [\;\/\?\:\@\&\=\+\$\,] -> Ureserved - Ualphanum | Umark -> Uunreserved - [\-\_\.\!\~\*\'\(\)] -> Umark - - "%" Uhex Uhex -> Uescaped - Udigit | [A-Fa-f] -> Uhex - - Ualpha | Udigit -> Ualphanum - Ulowalpha | Uupalpha -> Ualpha - - [a-z] -> Ulowalpha - [A-Z] -> Uupalpha - [0-9] -> Udigit - - lexical restrictions - Uri -/- [a-zA-Z0-9\-\_\.\!\~\*\'\(\)] - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Layout. - -module Fix-Layout -exports - lexical syntax - [\ \t\n] -> LAYOUT - HashComment -> LAYOUT - Comment -> LAYOUT - "#" ~[\n]* [\n] -> HashComment - "//" ~[\n]* [\n] -> HashComment - "/*" ( ~[\*] | Asterisk )* "*/" -> Comment - [\*] -> Asterisk - lexical restrictions - Asterisk -/- [\/] - context-free restrictions - LAYOUT? -/- [\ \t\n] | [\#] - syntax - HashComment -> diff --git a/src/nix-instantiate/fixexpr.cc b/src/nix-instantiate/fixexpr.cc deleted file mode 100644 index 721fa8afa5f2..000000000000 --- a/src/nix-instantiate/fixexpr.cc +++ /dev/null @@ -1,215 +0,0 @@ -#include "fixexpr.hh" -#include "storeexpr.hh" - - -ATermMap::ATermMap(unsigned int initialSize, unsigned int maxLoadPct) -{ - table = ATtableCreate(initialSize, maxLoadPct); - if (!table) throw Error("cannot create ATerm table"); -} - - -ATermMap::ATermMap(const ATermMap & map) - : table(0) -{ - ATermList keys = map.keys(); - - /* !!! adjust allocation for load pct */ - table = ATtableCreate(ATgetLength(keys), map.maxLoadPct); - if (!table) throw Error("cannot create ATerm table"); - - for (ATermIterator i(keys); i; ++i) - set(*i, map.get(*i)); -} - - -ATermMap::~ATermMap() -{ - if (table) ATtableDestroy(table); -} - - -void ATermMap::set(ATerm key, ATerm value) -{ - return ATtablePut(table, key, value); -} - - -void ATermMap::set(const string & key, ATerm value) -{ - set(string2ATerm(key), value); -} - - -ATerm ATermMap::get(ATerm key) const -{ - return ATtableGet(table, key); -} - - -ATerm ATermMap::get(const string & key) const -{ - return get(string2ATerm(key)); -} - - -void ATermMap::remove(ATerm key) -{ - ATtableRemove(table, key); -} - - -void ATermMap::remove(const string & key) -{ - remove(string2ATerm(key)); -} - - -ATermList ATermMap::keys() const -{ - ATermList keys = ATtableKeys(table); - if (!keys) throw Error("cannot query aterm map keys"); - return keys; -} - - -ATerm string2ATerm(const string & s) -{ - return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s.c_str(), 0, ATtrue)); -} - - -string aterm2String(ATerm t) -{ - return ATgetName(ATgetAFun(t)); -} - - -ATerm bottomupRewrite(TermFun & f, ATerm e) -{ - if (ATgetType(e) == AT_APPL) { - AFun fun = ATgetAFun(e); - int arity = ATgetArity(fun); - ATermList args = ATempty; - - for (int i = arity - 1; i >= 0; i--) - args = ATinsert(args, bottomupRewrite(f, ATgetArgument(e, i))); - - e = (ATerm) ATmakeApplList(fun, args); - } - - else if (ATgetType(e) == AT_LIST) { - ATermList in = (ATermList) e; - ATermList out = ATempty; - - for (ATermIterator i(in); i; ++i) - out = ATinsert(out, bottomupRewrite(f, *i)); - - e = (ATerm) ATreverse(out); - } - - return f(e); -} - - -void queryAllAttrs(Expr e, ATermMap & attrs) -{ - ATMatcher m; - ATermList bnds; - if (!(atMatch(m, e) >> "Attrs" >> bnds)) - throw badTerm("expected attribute set", e); - - for (ATermIterator i(bnds); i; ++i) { - string s; - Expr e; - if (!(atMatch(m, *i) >> "Bind" >> s >> e)) - abort(); /* can't happen */ - attrs.set(s, e); - } -} - - -Expr queryAttr(Expr e, const string & name) -{ - ATermMap attrs; - queryAllAttrs(e, attrs); - return attrs.get(name); -} - - -Expr makeAttrs(const ATermMap & attrs) -{ - ATermList bnds = ATempty; - for (ATermIterator i(attrs.keys()); i; ++i) - bnds = ATinsert(bnds, - ATmake("Bind(, )", *i, attrs.get(*i))); - return ATmake("Attrs()", ATreverse(bnds)); -} - - -Expr substitute(const ATermMap & subs, Expr e) -{ - ATMatcher m; - string s; - - if (atMatch(m, e) >> "Var" >> s) { - Expr sub = subs.get(s); - return sub ? sub : e; - } - - /* In case of a function, filter out all variables bound by this - function. */ - ATermList formals; - ATerm body; - if (atMatch(m, e) >> "Function" >> formals >> body) { - ATermMap subs2(subs); - for (ATermIterator i(formals); i; ++i) { - Expr def; - if (!(atMatch(m, *i) >> "NoDefFormal" >> s) && - !(atMatch(m, *i) >> "DefFormal" >> s >> def)) - abort(); - subs2.remove(s); - } - return ATmake("Function(, )", formals, - substitute(subs2, body)); - } - - /* Idem for a mutually recursive attribute set. */ - ATermList bindings; - if (atMatch(m, e) >> "Rec" >> bindings) { - ATermMap subs2(subs); - for (ATermIterator i(bindings); i; ++i) { - Expr e; - if (!(atMatch(m, *i) >> "Bind" >> s >> e)) - abort(); /* can't happen */ - subs2.remove(s); - } - return ATmake("Rec()", substitute(subs2, (ATerm) bindings)); - } - - if (ATgetType(e) == AT_APPL) { - AFun fun = ATgetAFun(e); - int arity = ATgetArity(fun); - ATermList args = ATempty; - - for (int i = arity - 1; i >= 0; i--) - args = ATinsert(args, substitute(subs, ATgetArgument(e, i))); - - return (ATerm) ATmakeApplList(fun, args); - } - - if (ATgetType(e) == AT_LIST) { - ATermList out = ATempty; - for (ATermIterator i((ATermList) e); i; ++i) - out = ATinsert(out, substitute(subs, *i)); - return (ATerm) ATreverse(out); - } - - return e; -} - - -Expr makeBool(bool b) -{ - return b ? ATmake("Bool(True)") : ATmake("Bool(False)"); -} diff --git a/src/nix-instantiate/fixexpr.hh b/src/nix-instantiate/fixexpr.hh deleted file mode 100644 index 6c1e51d9ccd6..000000000000 --- a/src/nix-instantiate/fixexpr.hh +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef __FIXEXPR_H -#define __FIXEXPR_H - -#include - -#include - -#include "util.hh" - - -/* Fix expressions are represented as ATerms. The maximal sharing - property of the ATerm library allows us to implement caching of - normals forms efficiently. */ -typedef ATerm Expr; - - -/* Mappings from ATerms to ATerms. This is just a wrapper around - ATerm tables. */ -class ATermMap -{ -private: - unsigned int maxLoadPct; - ATermTable table; - -public: - ATermMap(unsigned int initialSize = 16, unsigned int maxLoadPct = 75); - ATermMap(const ATermMap & map); - ~ATermMap(); - - void set(ATerm key, ATerm value); - void set(const string & key, ATerm value); - - ATerm get(ATerm key) const; - ATerm get(const string & key) const; - - void remove(ATerm key); - void remove(const string & key); - - ATermList keys() const; -}; - - -/* Convert a string to an ATerm (i.e., a quoted nullary function - applicaton). */ -ATerm string2ATerm(const string & s); -string aterm2String(ATerm t); - -/* Generic bottomup traversal over ATerms. The traversal first - recursively descends into subterms, and then applies the given term - function to the resulting term. */ -struct TermFun -{ - virtual ATerm operator () (ATerm e) = 0; -}; -ATerm bottomupRewrite(TermFun & f, ATerm e); - -/* Query all attributes in an attribute set expression. The - expression must be in normal form. */ -void queryAllAttrs(Expr e, ATermMap & attrs); - -/* Query a specific attribute from an attribute set expression. The - expression must be in normal form. */ -Expr queryAttr(Expr e, const string & name); - -/* Create an attribute set expression from an Attrs value. */ -Expr makeAttrs(const ATermMap & attrs); - -/* Perform a set of substitutions on an expression. */ -Expr substitute(const ATermMap & subs, Expr e); - -/* Create an expression representing a boolean. */ -Expr makeBool(bool b); - - -#endif /* !__FIXEXPR_H */ diff --git a/src/nix-instantiate/main.cc b/src/nix-instantiate/main.cc new file mode 100644 index 000000000000..aa6883ff84b8 --- /dev/null +++ b/src/nix-instantiate/main.cc @@ -0,0 +1,117 @@ +#include +#include + +#include "globals.hh" +#include "normalise.hh" +#include "shared.hh" +#include "eval.hh" + + +#if 0 +static Path searchPath(const Paths & searchDirs, const Path & relPath) +{ + if (string(relPath, 0, 1) == "/") return relPath; + + for (Paths::const_iterator i = searchDirs.begin(); + i != searchDirs.end(); i++) + { + Path path = *i + "/" + relPath; + if (pathExists(path)) return path; + } + + throw Error( + format("path `%1%' not found in any of the search directories") + % relPath); +} +#endif + + +static Expr evalStdin(EvalState & state) +{ + startNest(nest, lvlTalkative, format("evaluating standard input")); + Expr e = ATreadFromFile(stdin); + if (!e) + throw Error(format("unable to read a term from stdin")); + return evalExpr(state, e); +} + + +static void printNixExpr(EvalState & state, Expr e) +{ + ATMatcher m; + ATermList es; + + if (atMatch(m, e) >> "Attrs" >> es) { + Expr a = queryAttr(e, "type"); + if (a && evalString(state, a) == "derivation") { + a = queryAttr(e, "drvPath"); + if (a) { + cout << format("%1%\n") % evalPath(state, a); + return; + } + } + } + + if (ATgetType(e) == AT_LIST) { + for (ATermIterator i((ATermList) e); i; ++i) + printNixExpr(state, evalExpr(state, *i)); + return; + } + + throw badTerm("top level does not evaluate to one or more Nix expressions", e); +} + + +void run(Strings args) +{ + EvalState state; + Strings files; + bool readStdin = false; + +#if 0 + state.searchDirs.push_back("."); + state.searchDirs.push_back(nixDataDir + "/nix"); +#endif + + for (Strings::iterator it = args.begin(); + it != args.end(); ) + { + string arg = *it++; + +#if 0 + if (arg == "--includedir" || arg == "-I") { + if (it == args.end()) + throw UsageError(format("argument required in `%1%'") % arg); + state.searchDirs.push_back(*it++); + } + else +#endif + if (arg == "--verbose" || arg == "-v") + verbosity = (Verbosity) ((int) verbosity + 1); + else if (arg == "-") + readStdin = true; + else if (arg[0] == '-') + throw UsageError(format("unknown flag `%1%`") % arg); + else + files.push_back(arg); + } + + openDB(); + + if (readStdin) { + Expr e = evalStdin(state); + printNixExpr(state, e); + } + + for (Strings::iterator it = files.begin(); + it != files.end(); it++) + { + Expr e = evalFile(state, absPath(*it)); + printNixExpr(state, e); + } + + printEvalStats(state); +} + + +string programId = "nix-instantiate"; diff --git a/src/nix-instantiate/nix.sdf b/src/nix-instantiate/nix.sdf new file mode 100644 index 000000000000..54f5d5266f79 --- /dev/null +++ b/src/nix-instantiate/nix.sdf @@ -0,0 +1,203 @@ +definition + +module Main +imports Fix + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top level syntax. + +module Fix +imports Fix-Exprs Fix-Layout + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Expressions. + +module Fix-Exprs +imports Fix-Lexicals URI +exports + sorts Expr Bind Formal + context-free syntax + + Id -> Expr {cons("Var")} + + Int -> Expr {cons("Int")} + + Str -> Expr {cons("Str")} + + Uri -> Expr {cons("Uri")} + + Path -> Expr {cons("Path")} + + "(" Expr ")" -> Expr {bracket} + + Expr Expr -> Expr {cons("Call"), left} + + "{" {Formal ","}* "}" ":" Expr -> Expr {cons("Function"), right} + Id -> Formal {cons("NoDefFormal")} + Id "?" Expr -> Formal {cons("DefFormal")} + + "assert" Expr ";" Expr -> Expr {cons("Assert"), right} + + "rec" "{" Binds "}" -> Expr {cons("Rec")} + "let" "{" Binds "}" -> Expr {cons("LetRec")} + "{" Binds "}" -> Expr {cons("Attrs")} + + Id "=" Expr -> Bind {cons("Bind")} + {Bind ";"}* -> Binds + Bind ";" -> BindSemi + BindSemi* -> Binds + + "[" ExprList "]" -> Expr {cons("List")} + "" -> ExprList {cons("ExprNil")} + Expr ExprList -> ExprList {cons("ExprCons")} + + Expr "." Id -> Expr {cons("Select")} + + "if" Expr "then" Expr "else" Expr -> Expr {cons("If")} + + Expr "==" Expr -> Expr {cons("OpEq"), non-assoc} + Expr "!=" Expr -> Expr {cons("OpNEq"), non-assoc} + + "!" Expr -> Expr {cons("OpNot")} + Expr "&&" Expr -> Expr {cons("OpAnd"), right} + Expr "||" Expr -> Expr {cons("OpOr"), right} + Expr "->" Expr -> Expr {cons("OpImpl"), right} + + Bool -> Expr {cons("Bool")} + + context-free priorities + + Expr "." Id -> Expr + > Expr ExprList -> ExprList + > Expr Expr -> Expr + > "!" Expr -> Expr + > Expr "==" Expr -> Expr + > Expr "!=" Expr -> Expr + > Expr "&&" Expr -> Expr + > Expr "||" Expr -> Expr + > Expr "->" Expr -> Expr + > "assert" Expr ";" Expr -> Expr + > "{" {Formal ","}* "}" ":" Expr -> Expr + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Lexical syntax. + +module Fix-Lexicals +exports + sorts Id Path + lexical syntax + [a-zA-Z\_][a-zA-Z0-9\_\']* -> Id + "rec" -> Id {reject} + "let" -> Id {reject} + "if" -> Id {reject} + "then" -> Id {reject} + "else" -> Id {reject} + "true" -> Id {reject} + "false" -> Id {reject} + "assert" -> Id {reject} + + [0-9]+ -> Int + + "\"" ~[\n\"]* "\"" -> Str + + PathComp ("/" PathComp)+ -> Path + [a-zA-Z0-9\.\_\-\+]+ -> PathComp + + "true" -> Bool + "false" -> Bool + + lexical restrictions + Id -/- [a-zA-Z0-9\_\'] + Int -/- [0-9] + Path -/- [a-zA-Z0-9\.\_\-\+\/] + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% URIs (RFC 2396, appendix A). + +module URI +exports + sorts Uri + lexical syntax + Uscheme ":" (Uhierpath | Uopaquepath) -> Uri + + (Unetpath | Uabspath) ("?" Uquery)? -> Uhierpath + Uuricnoslash Uuric* -> Uopaquepath + + Uunreserved | Uescaped | [\;\?\:\@\&\=\+\$\,] -> Uuricnoslash + + "//" Uauthority Uabspath? -> Unetpath + "/" Upathsegments -> Uabspath + "//" Uuric* -> Uabspath {reject} + Urelsegment Uabspath? -> Urelpath + + (Uunreserved | Uescaped | [\;\@\&\=\+\$\,])+ -> Urelsegment + + Ualpha (Ualpha | Udigit | [\+\-\.])* -> Uscheme + + Userver | Uregname -> Uauthority + + (Uunreserved | Uescaped | [\$\,\;\:\@\&\=\+])+ -> Uregname + + ((Uuserinfo "@") Uhostport) -> Userver + (Uunreserved | Uescaped | [\;\:\&\=\+\$\,])* -> Uuserinfo + + Uhost (":" Uport)? -> Uhostport + Uhostname | UIPv4address -> Uhost + (Udomainlabel ".")+ Utoplabel "."? -> Uhostname + Ualphanum | Ualphanum (Ualphanum | "-")* Ualphanum -> Udomainlabel + Ualpha | Ualpha (Ualphanum | "-")* Ualphanum -> Utoplabel + Udigit+ "." Udigit+ "." Udigit+ "." Udigit+ -> UIPv4address + Udigit* -> Uport + + Uabspath | Uopaquepart -> Upath + Usegment ("/" Usegment)* -> Upathsegments + Upchar* (";" Uparam)* -> Usegment + Upchar* -> Uparam + Uunreserved | Uescaped | [\:\@\&\=\+\$\,] -> Upchar + + Uuric* -> Uquery + + Uuric* -> Ufragment + + Ureserved | Uunreserved | Uescaped -> Uuric + [\;\/\?\:\@\&\=\+\$\,] -> Ureserved + Ualphanum | Umark -> Uunreserved + [\-\_\.\!\~\*\'\(\)] -> Umark + + "%" Uhex Uhex -> Uescaped + Udigit | [A-Fa-f] -> Uhex + + Ualpha | Udigit -> Ualphanum + Ulowalpha | Uupalpha -> Ualpha + + [a-z] -> Ulowalpha + [A-Z] -> Uupalpha + [0-9] -> Udigit + + lexical restrictions + Uri -/- [a-zA-Z0-9\-\_\.\!\~\*\'\(\)] + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Layout. + +module Fix-Layout +exports + lexical syntax + [\ \t\n] -> LAYOUT + HashComment -> LAYOUT + Comment -> LAYOUT + "#" ~[\n]* [\n] -> HashComment + "//" ~[\n]* [\n] -> HashComment + "/*" ( ~[\*] | Asterisk )* "*/" -> Comment + [\*] -> Asterisk + lexical restrictions + Asterisk -/- [\/] + context-free restrictions + LAYOUT? -/- [\ \t\n] | [\#] + syntax + HashComment -> diff --git a/src/nix-instantiate/nixexpr.cc b/src/nix-instantiate/nixexpr.cc new file mode 100644 index 000000000000..816b39dc1ae3 --- /dev/null +++ b/src/nix-instantiate/nixexpr.cc @@ -0,0 +1,215 @@ +#include "nixexpr.hh" +#include "storeexpr.hh" + + +ATermMap::ATermMap(unsigned int initialSize, unsigned int maxLoadPct) +{ + table = ATtableCreate(initialSize, maxLoadPct); + if (!table) throw Error("cannot create ATerm table"); +} + + +ATermMap::ATermMap(const ATermMap & map) + : table(0) +{ + ATermList keys = map.keys(); + + /* !!! adjust allocation for load pct */ + table = ATtableCreate(ATgetLength(keys), map.maxLoadPct); + if (!table) throw Error("cannot create ATerm table"); + + for (ATermIterator i(keys); i; ++i) + set(*i, map.get(*i)); +} + + +ATermMap::~ATermMap() +{ + if (table) ATtableDestroy(table); +} + + +void ATermMap::set(ATerm key, ATerm value) +{ + return ATtablePut(table, key, value); +} + + +void ATermMap::set(const string & key, ATerm value) +{ + set(string2ATerm(key), value); +} + + +ATerm ATermMap::get(ATerm key) const +{ + return ATtableGet(table, key); +} + + +ATerm ATermMap::get(const string & key) const +{ + return get(string2ATerm(key)); +} + + +void ATermMap::remove(ATerm key) +{ + ATtableRemove(table, key); +} + + +void ATermMap::remove(const string & key) +{ + remove(string2ATerm(key)); +} + + +ATermList ATermMap::keys() const +{ + ATermList keys = ATtableKeys(table); + if (!keys) throw Error("cannot query aterm map keys"); + return keys; +} + + +ATerm string2ATerm(const string & s) +{ + return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s.c_str(), 0, ATtrue)); +} + + +string aterm2String(ATerm t) +{ + return ATgetName(ATgetAFun(t)); +} + + +ATerm bottomupRewrite(TermFun & f, ATerm e) +{ + if (ATgetType(e) == AT_APPL) { + AFun fun = ATgetAFun(e); + int arity = ATgetArity(fun); + ATermList args = ATempty; + + for (int i = arity - 1; i >= 0; i--) + args = ATinsert(args, bottomupRewrite(f, ATgetArgument(e, i))); + + e = (ATerm) ATmakeApplList(fun, args); + } + + else if (ATgetType(e) == AT_LIST) { + ATermList in = (ATermList) e; + ATermList out = ATempty; + + for (ATermIterator i(in); i; ++i) + out = ATinsert(out, bottomupRewrite(f, *i)); + + e = (ATerm) ATreverse(out); + } + + return f(e); +} + + +void queryAllAttrs(Expr e, ATermMap & attrs) +{ + ATMatcher m; + ATermList bnds; + if (!(atMatch(m, e) >> "Attrs" >> bnds)) + throw badTerm("expected attribute set", e); + + for (ATermIterator i(bnds); i; ++i) { + string s; + Expr e; + if (!(atMatch(m, *i) >> "Bind" >> s >> e)) + abort(); /* can't happen */ + attrs.set(s, e); + } +} + + +Expr queryAttr(Expr e, const string & name) +{ + ATermMap attrs; + queryAllAttrs(e, attrs); + return attrs.get(name); +} + + +Expr makeAttrs(const ATermMap & attrs) +{ + ATermList bnds = ATempty; + for (ATermIterator i(attrs.keys()); i; ++i) + bnds = ATinsert(bnds, + ATmake("Bind(, )", *i, attrs.get(*i))); + return ATmake("Attrs()", ATreverse(bnds)); +} + + +Expr substitute(const ATermMap & subs, Expr e) +{ + ATMatcher m; + string s; + + if (atMatch(m, e) >> "Var" >> s) { + Expr sub = subs.get(s); + return sub ? sub : e; + } + + /* In case of a function, filter out all variables bound by this + function. */ + ATermList formals; + ATerm body; + if (atMatch(m, e) >> "Function" >> formals >> body) { + ATermMap subs2(subs); + for (ATermIterator i(formals); i; ++i) { + Expr def; + if (!(atMatch(m, *i) >> "NoDefFormal" >> s) && + !(atMatch(m, *i) >> "DefFormal" >> s >> def)) + abort(); + subs2.remove(s); + } + return ATmake("Function(, )", formals, + substitute(subs2, body)); + } + + /* Idem for a mutually recursive attribute set. */ + ATermList bindings; + if (atMatch(m, e) >> "Rec" >> bindings) { + ATermMap subs2(subs); + for (ATermIterator i(bindings); i; ++i) { + Expr e; + if (!(atMatch(m, *i) >> "Bind" >> s >> e)) + abort(); /* can't happen */ + subs2.remove(s); + } + return ATmake("Rec()", substitute(subs2, (ATerm) bindings)); + } + + if (ATgetType(e) == AT_APPL) { + AFun fun = ATgetAFun(e); + int arity = ATgetArity(fun); + ATermList args = ATempty; + + for (int i = arity - 1; i >= 0; i--) + args = ATinsert(args, substitute(subs, ATgetArgument(e, i))); + + return (ATerm) ATmakeApplList(fun, args); + } + + if (ATgetType(e) == AT_LIST) { + ATermList out = ATempty; + for (ATermIterator i((ATermList) e); i; ++i) + out = ATinsert(out, substitute(subs, *i)); + return (ATerm) ATreverse(out); + } + + return e; +} + + +Expr makeBool(bool b) +{ + return b ? ATmake("Bool(True)") : ATmake("Bool(False)"); +} diff --git a/src/nix-instantiate/nixexpr.hh b/src/nix-instantiate/nixexpr.hh new file mode 100644 index 000000000000..011c2900e12a --- /dev/null +++ b/src/nix-instantiate/nixexpr.hh @@ -0,0 +1,75 @@ +#ifndef __NIXEXPR_H +#define __NIXEXPR_H + +#include + +#include + +#include "util.hh" + + +/* Nix expressions are represented as ATerms. The maximal sharing + property of the ATerm library allows us to implement caching of + normals forms efficiently. */ +typedef ATerm Expr; + + +/* Mappings from ATerms to ATerms. This is just a wrapper around + ATerm tables. */ +class ATermMap +{ +private: + unsigned int maxLoadPct; + ATermTable table; + +public: + ATermMap(unsigned int initialSize = 16, unsigned int maxLoadPct = 75); + ATermMap(const ATermMap & map); + ~ATermMap(); + + void set(ATerm key, ATerm value); + void set(const string & key, ATerm value); + + ATerm get(ATerm key) const; + ATerm get(const string & key) const; + + void remove(ATerm key); + void remove(const string & key); + + ATermList keys() const; +}; + + +/* Convert a string to an ATerm (i.e., a quoted nullary function + applicaton). */ +ATerm string2ATerm(const string & s); +string aterm2String(ATerm t); + +/* Generic bottomup traversal over ATerms. The traversal first + recursively descends into subterms, and then applies the given term + function to the resulting term. */ +struct TermFun +{ + virtual ATerm operator () (ATerm e) = 0; +}; +ATerm bottomupRewrite(TermFun & f, ATerm e); + +/* Query all attributes in an attribute set expression. The + expression must be in normal form. */ +void queryAllAttrs(Expr e, ATermMap & attrs); + +/* Query a specific attribute from an attribute set expression. The + expression must be in normal form. */ +Expr queryAttr(Expr e, const string & name); + +/* Create an attribute set expression from an Attrs value. */ +Expr makeAttrs(const ATermMap & attrs); + +/* Perform a set of substitutions on an expression. */ +Expr substitute(const ATermMap & subs, Expr e); + +/* Create an expression representing a boolean. */ +Expr makeBool(bool b); + + +#endif /* !__NIXEXPR_H */ diff --git a/src/nix-instantiate/parser.cc b/src/nix-instantiate/parser.cc index eaa41b3963ef..f950a51f69ce 100644 --- a/src/nix-instantiate/parser.cc +++ b/src/nix-instantiate/parser.cc @@ -13,7 +13,6 @@ extern "C" { #include "aterm.hh" #include "parser.hh" #include "shared.hh" -#include "fixexpr.hh" #include "parse-table.h" @@ -76,12 +75,12 @@ Expr parseExprFromFile(Path path) if (e) return e; #endif - /* If `path' refers to a directory, append `/default.fix'. */ + /* If `path' refers to a directory, append `/default.nix'. */ struct stat st; if (stat(path.c_str(), &st)) throw SysError(format("getting status of `%1%'") % path); if (S_ISDIR(st.st_mode)) - path = canonPath(path + "/default.fix"); + path = canonPath(path + "/default.nix"); /* Initialise the SDF libraries. */ static bool initialised = false; @@ -95,12 +94,12 @@ Expr parseExprFromFile(Path path) ATprotect(&parseTable); parseTable = ATreadFromBinaryString( - (char *) fixParseTable, sizeof fixParseTable); + (char *) nixParseTable, sizeof nixParseTable); if (!parseTable) throw Error(format("cannot construct parse table term")); ATprotect(&lang); - lang = ATmake("Fix"); + lang = ATmake("Nix"); if (!SGopenLanguageFromTerm( (char *) programId.c_str(), lang, parseTable)) throw Error(format("cannot open language")); diff --git a/src/nix-instantiate/parser.hh b/src/nix-instantiate/parser.hh index e44987dd014b..5983ec5629e4 100644 --- a/src/nix-instantiate/parser.hh +++ b/src/nix-instantiate/parser.hh @@ -1,7 +1,7 @@ #ifndef __PARSER_H #define __PARSER_H -#include "fixexpr.hh" +#include "nixexpr.hh" Expr parseExprFromFile(Path path); diff --git a/src/nix-store/Makefile.am b/src/nix-store/Makefile.am index a39d1e2ad985..516d78efc5c2 100644 --- a/src/nix-store/Makefile.am +++ b/src/nix-store/Makefile.am @@ -1,15 +1,13 @@ bin_PROGRAMS = nix-store -nix_store_SOURCES = nix.cc dotgraph.cc +nix_store_SOURCES = main.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 +main.o: help.txt.hh %.hh: % - echo -n '"' > $@ - sed 's|\(.*\)|\1\\n\\|' < $< >> $@ - echo '"' >> $@ + ../bin2c/bin2c helpText < $< > $@ || (rm $@ && exit 1) AM_CXXFLAGS = \ -I.. -I../../externals/inst/include -I../libutil -I../libstore -I../libmain diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt new file mode 100644 index 000000000000..d7f977025440 --- /dev/null +++ b/src/nix-store/help.txt @@ -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 diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc new file mode 100644 index 000000000000..0d87db9dfbb9 --- /dev/null +++ b/src/nix-store/main.cc @@ -0,0 +1,303 @@ +#include +#include + +#include "globals.hh" +#include "normalise.hh" +#include "archive.hh" +#include "shared.hh" +#include "dotgraph.hh" +#include "help.txt.hh" + + +typedef void (* Operation) (Strings opFlags, Strings opArgs); + + +static void printHelp() +{ + cout << string((char *) helpText, sizeof helpText); + 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-store"; diff --git a/src/nix-store/nix-help.txt b/src/nix-store/nix-help.txt deleted file mode 100644 index d7f977025440..000000000000 --- a/src/nix-store/nix-help.txt +++ /dev/null @@ -1,34 +0,0 @@ -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 diff --git a/src/nix-store/nix.cc b/src/nix-store/nix.cc deleted file mode 100644 index d1766de39b7e..000000000000 --- a/src/nix-store/nix.cc +++ /dev/null @@ -1,304 +0,0 @@ -#include -#include - -#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"; -- cgit 1.4.1