diff options
-rw-r--r-- | src/eval.cc | 36 | ||||
-rw-r--r-- | src/fix.cc | 368 | ||||
-rw-r--r-- | src/globals.hh | 8 |
3 files changed, 9 insertions, 403 deletions
diff --git a/src/eval.cc b/src/eval.cc index 4eb222197d38..be8b70a039be 100644 --- a/src/eval.cc +++ b/src/eval.cc @@ -106,7 +106,7 @@ static void runProgram(const string & program, Environment env) } catch (exception & e) { cerr << format("build error: %1%\n") % e.what(); - } + } _exit(1); } @@ -159,38 +159,6 @@ Hash hashTerm(ATerm t) } -#if 0 -/* Evaluate a list of arguments into normal form. */ -void evalArgs(ATermList args, ATermList & argsNF, Environment & env) -{ - argsNF = ATempty; - - while (!ATisEmpty(args)) { - ATerm eName, eVal, arg = ATgetFirst(args); - if (!ATmatch(arg, "Tup(<term>, <term>)", &eName, &eVal)) - throw badTerm("invalid argument", arg); - - string name = evalString(eName); - eVal = evalValue(eVal); - - char * s; - if (ATmatch(eVal, "Str(<str>)", &s)) { - env[name] = s; - } else if (ATmatch(eVal, "Hash(<str>)", &s)) { - env[name] = queryValuePath(parseHash(s)); - } else throw badTerm("invalid argument value", eVal); - - argsNF = ATinsert(argsNF, - ATmake("Tup(Str(<str>), <term>)", name.c_str(), eVal)); - - args = ATgetNext(args); - } - - argsNF = ATreverse(argsNF); -} -#endif - - struct RStatus { /* !!! the comparator of this hash should match the semantics of @@ -362,7 +330,7 @@ static FState realise(RStatus & status, FState fs) return nf; } - throw badTerm("bad file system state expression", fs); + throw badTerm("bad fstate expression", fs); } diff --git a/src/fix.cc b/src/fix.cc deleted file mode 100644 index 3c4c8bf539e0..000000000000 --- a/src/fix.cc +++ /dev/null @@ -1,368 +0,0 @@ -#include <iostream> -#include <map> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> - -extern "C" { -#include <aterm2.h> -} - -#include "util.hh" -#include "hash.hh" - - -static string nixDescriptorDir; - - -static bool verbose = false; - - -/* Mapping of Fix file names to the hashes of the resulting Nix - descriptors. */ -typedef map<string, Hash> DescriptorMap; - - -void registerFile(string filename) -{ - int res = system(("nix regfile " + filename).c_str()); - /* !!! escape */ - if (WEXITSTATUS(res) != 0) - throw Error("cannot register " + filename + " with Nix"); -} - - -void registerURL(Hash hash, string url) -{ - int res = system(("nix regurl " + (string) hash + " " + url).c_str()); - /* !!! escape */ - if (WEXITSTATUS(res) != 0) - throw Error("cannot register " + - (string) hash + " -> " + url + " with Nix"); -} - - -Error badTerm(const string & msg, ATerm e) -{ - char * s = ATwriteToString(e); - return Error(msg + ", in `" + s + "'"); -} - - -/* Term evaluation. */ - -typedef map<string, ATerm> BindingsMap; - -struct EvalContext -{ - string dir; - DescriptorMap * done; - BindingsMap * vars; -}; - - -ATerm evaluate(ATerm e, EvalContext ctx); -Hash instantiateDescriptor(string filename, EvalContext ctx); - - -string evaluateStr(ATerm e, EvalContext ctx) -{ - e = evaluate(e, ctx); - char * s; - if (ATmatch(e, "Str(<str>)", &s)) - return s; - else throw badTerm("string value expected", e); -} - - -bool evaluateBool(ATerm e, EvalContext ctx) -{ - e = evaluate(e, ctx); - if (ATmatch(e, "Bool(True)")) - return true; - else if (ATmatch(e, "Bool(False)")) - return false; - else throw badTerm("boolean value expected", e); -} - - -ATerm evaluate(ATerm e, EvalContext ctx) -{ - char * s; - ATerm e2, e3; - ATerm eCond, eTrue, eFalse; - - /* Check for normal forms first. */ - - if (ATmatch(e, "Str(<str>)", &s) || - ATmatch(e, "Bool(True)") || ATmatch(e, "Bool(False)")) - return e; - - else if ( - ATmatch(e, "Pkg(<str>)", &s) || - ATmatch(e, "File(<str>)", &s)) - { - parseHash(s); - return e; - } - - /* Short-hands. */ - - else if (ATmatch(e, "<str>", &s)) - return ATmake("Str(<str>)", s); - - else if (ATmatch(e, "True", &s)) - return ATmake("Bool(True)", s); - - else if (ATmatch(e, "False", &s)) - return ATmake("Bool(False)", s); - - /* Functions. */ - - /* `Var' looks up a variable. */ - else if (ATmatch(e, "Var(<str>)", &s)) { - string name(s); - ATerm e2 = (*ctx.vars)[name]; - if (!e2) throw Error("undefined variable " + name); - return evaluate(e2, ctx); /* !!! update binding */ - } - - /* `Fix' recursively instantiates a Fix descriptor, returning the - hash of the generated Nix descriptor. */ - else if (ATmatch(e, "Fix(<term>)", &e2)) { - string filename = absPath(evaluateStr(e2, ctx), ctx.dir); /* !!! */ - return ATmake("Pkg(<str>)", - ((string) instantiateDescriptor(filename, ctx)).c_str()); - } - -#if 0 - /* `Source' copies the specified file to nixSourcesDir, registers - it with Nix, and returns the hash of the file. */ - else if (ATmatch(e, "Source(<term>)", &e2)) { - string source = absPath(evaluateStr(e2, ctx), ctx.dir); /* !!! */ - string target = nixSourcesDir + "/" + baseNameOf(source); - - // Don't copy if filename is already in nixSourcesDir. - if (source != target) { - if (verbose) - cerr << "copying source " << source << endl; - string cmd = "cp -p " + source + " " + target; - int res = system(cmd.c_str()); - if (WEXITSTATUS(res) != 0) - throw Error("cannot copy " + source + " to " + target); - } - - registerFile(target); - return ATmake("File(<str>)", hashFile(target).c_str()); - } -#endif - - /* `Local' registers a file with Nix, and returns the file's - hash. */ - else if (ATmatch(e, "Local(<term>)", &e2)) { - string filename = absPath(evaluateStr(e2, ctx), ctx.dir); /* !!! */ - Hash hash = hashFile(filename); - registerFile(filename); /* !!! */ - return ATmake("File(<str>)", ((string) hash).c_str()); - } - - /* `Url' registers a mapping from a hash to an url with Nix, and - returns the hash. */ - else if (ATmatch(e, "Url(<term>, <term>)", &e2, &e3)) { - Hash hash = parseHash(evaluateStr(e2, ctx)); - string url = evaluateStr(e3, ctx); - registerURL(hash, url); - return ATmake("File(<str>)", ((string) hash).c_str()); - } - - /* `If' provides conditional evaluation. */ - else if (ATmatch(e, "If(<term>, <term>, <term>)", - &eCond, &eTrue, &eFalse)) - return evaluate(evaluateBool(eCond, ctx) ? eTrue : eFalse, ctx); - - else throw badTerm("invalid expression", e); -} - - -string getStringFromMap(BindingsMap & bindingsMap, - const string & name) -{ - ATerm e = bindingsMap[name]; - if (!e) throw Error("binding " + name + " is not set"); - char * s; - if (ATmatch(e, "Str(<str>)", &s)) - return s; - else - throw Error("binding " + name + " is not a string"); -} - - -/* Instantiate a Fix descriptors into a Nix descriptor, recursively - instantiating referenced descriptors as well. */ -Hash instantiateDescriptor(string filename, EvalContext ctx) -{ - /* Already done? */ - DescriptorMap::iterator isInMap = ctx.done->find(filename); - if (isInMap != ctx.done->end()) return isInMap->second; - - /* No. */ - ctx.dir = dirOf(filename); - - /* Read the Fix descriptor as an ATerm. */ - ATerm inTerm = ATreadFromNamedFile(filename.c_str()); - if (!inTerm) throw Error("cannot read aterm " + filename); - - ATerm bindings; - if (!ATmatch(inTerm, "Descr(<term>)", &bindings)) - throw Error("invalid term in " + filename); - - /* Iterate over the bindings and evaluate them to normal form. */ - BindingsMap bindingsMap; /* the normal forms */ - ctx.vars = &bindingsMap; - - char * cname; - ATerm value; - while (ATmatch(bindings, "[Bind(<str>, <term>), <list>]", - &cname, &value, &bindings)) - { - string name(cname); - ATerm e = evaluate(value, ctx); - bindingsMap[name] = e; - } - - /* Construct a descriptor identifier by concatenating the package - and release ids. */ - string pkgId = getStringFromMap(bindingsMap, "pkgId"); - string releaseId = getStringFromMap(bindingsMap, "releaseId"); - string id = pkgId + "-" + releaseId; - bindingsMap["id"] = ATmake("Str(<str>)", id.c_str()); - - /* Add a system name. */ - bindingsMap["system"] = ATmake("Str(<str>)", thisSystem.c_str()); - - /* Construct the resulting ATerm. Note that iterating over the - map yields the bindings in sorted order, which is exactly the - canonical form for Nix descriptors. */ - ATermList bindingsList = ATempty; - for (BindingsMap::iterator it = bindingsMap.begin(); - it != bindingsMap.end(); it++) - /* !!! O(n^2) */ - bindingsList = ATappend(bindingsList, - ATmake("Bind(<str>, <term>)", it->first.c_str(), it->second)); - ATerm outTerm = ATmake("Descr(<term>)", bindingsList); - - /* Write out the resulting ATerm. */ - string tmpFilename = nixDescriptorDir + "/tmp"; - if (!ATwriteToNamedTextFile(outTerm, tmpFilename.c_str())) - throw Error("cannot write aterm to " + tmpFilename); - - Hash outHash = hashFile(tmpFilename); - string outFilename = nixDescriptorDir + "/" + - id + "-" + (string) outHash + ".nix"; - if (rename(tmpFilename.c_str(), outFilename.c_str())) - throw Error("cannot rename " + tmpFilename + " to " + outFilename); - - /* Register it with Nix. */ - registerFile(outFilename); - - if (verbose) - cerr << "instantiated " << (string) outHash - << " from " << filename << endl; - - (*ctx.done)[filename] = outHash; - return outHash; -} - - -/* Instantiate a set of Fix descriptors into Nix descriptors. */ -void instantiateDescriptors(Strings filenames) -{ - DescriptorMap done; - - EvalContext ctx; - ctx.done = &done; - - for (Strings::iterator it = filenames.begin(); - it != filenames.end(); it++) - { - string filename = absPath(*it); - cout << (string) instantiateDescriptor(filename, ctx) << endl; - } -} - - -/* Print help. */ -void printUsage() -{ - cerr << -"Usage: fix ...\n\ -"; -} - - -/* Parse the command-line arguments, call the right operation. */ -void run(Strings::iterator argCur, Strings::iterator argEnd) -{ - umask(0022); - - Strings extraArgs; - enum { cmdUnknown, cmdInstantiate } command = cmdUnknown; - - char * homeDir = getenv(nixHomeDirEnvVar.c_str()); - if (homeDir) nixHomeDir = homeDir; - - nixDescriptorDir = nixHomeDir + "/var/nix/descriptors"; - - for ( ; argCur != argEnd; argCur++) { - string arg(*argCur); - if (arg == "-h" || arg == "--help") { - printUsage(); - return; - } else if (arg == "-v" || arg == "--verbose") { - verbose = true; - } else if (arg == "--instantiate" || arg == "-i") { - command = cmdInstantiate; - } else if (arg[0] == '-') - throw UsageError("invalid option `" + arg + "'"); - else - extraArgs.push_back(arg); - } - - switch (command) { - - case cmdInstantiate: - instantiateDescriptors(extraArgs); - break; - - default: - throw UsageError("no operation specified"); - } -} - - -int main(int argc, char * * argv) -{ - ATerm bottomOfStack; - ATinit(argc, argv, &bottomOfStack); - - /* Put the arguments in a vector. */ - Strings args; - while (argc--) args.push_back(*argv++); - Strings::iterator argCur = args.begin(), argEnd = args.end(); - - argCur++; - - try { - run(argCur, argEnd); - } catch (UsageError & e) { - cerr << "error: " << e.what() << endl - << "Try `fix -h' for more information.\n"; - return 1; - } catch (exception & e) { - cerr << "error: " << e.what() << endl; - return 1; - } - - return 0; -} diff --git a/src/globals.hh b/src/globals.hh index 8597ae2f89d7..8c6a763c48e3 100644 --- a/src/globals.hh +++ b/src/globals.hh @@ -21,7 +21,13 @@ extern string dbRefs; with hash h2. Note that a term $y$ is successor of $x$ iff there exists a - sequence of rewrite steps that rewrites $x$ into $y$. */ + sequence of rewrite steps that rewrites $x$ into $y$. + + Also note that instead of a successor, $y$ can be any term + equivalent to $x$, that is, reducing to the same result, as long as + $x$ is equal to or a successor of $y$. (This is useful, e.g., for + shared derivate caching over the network). +*/ extern string dbSuccessors; /* dbNetSources :: Hash -> URL |