diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 28bbd2859a..12cc272f71 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -270,6 +270,9 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args) % *i % drvName); } + /* !!! the name should not end in the derivation extension (.drv). + Likewise for sources. */ + /* Construct the "masked" derivation store expression, which is the final one except that in the list of outputs, the output paths are empty, and the corresponding environment variables @@ -290,7 +293,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args) DerivationOutput(outPath, outputHashAlgo, outputHash); /* Write the resulting term into the Nix store directory. */ - Path drvPath = writeTerm(unparseDerivation(drv), "d-" + drvName); + Path drvPath = writeDerivation(drv, drvName); printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'") % drvName % drvPath); diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 24a522c1ed..2757a061ec 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -26,65 +26,39 @@ void computeFSClosure(const Path & storePath, } -#if 0 -PathSet storeExprRoots(const Path & nePath) -{ - PathSet paths; - - StoreExpr ne = storeExprFromPath(nePath); - - if (ne.type == StoreExpr::neClosure) - paths.insert(ne.closure.roots.begin(), ne.closure.roots.end()); - else if (ne.type == StoreExpr::neDerivation) - for (DerivationOutputs::iterator i = ne.derivation.outputs.begin(); - i != ne.derivation.outputs.end(); ++i) - paths.insert(i->second.path); - else abort(); - - return paths; -} - - -static void requisitesWorker(const Path & nePath, - bool includeExprs, bool includeSuccessors, - PathSet & paths, PathSet & doneSet) +void storePathRequisites(const Path & storePath, + bool includeOutputs, PathSet & paths) { checkInterrupt(); - if (doneSet.find(nePath) != doneSet.end()) return; - doneSet.insert(nePath); + if (paths.find(storePath) != paths.end()) return; - StoreExpr ne = storeExprFromPath(nePath); + if (isDerivation(storePath)) { - if (ne.type == StoreExpr::neClosure) - for (ClosureElems::iterator i = ne.closure.elems.begin(); - i != ne.closure.elems.end(); ++i) - paths.insert(i->first); - - else if (ne.type == StoreExpr::neDerivation) - for (PathSet::iterator i = ne.derivation.inputs.begin(); - i != ne.derivation.inputs.end(); ++i) - requisitesWorker(*i, - includeExprs, includeSuccessors, paths, doneSet); + paths.insert(storePath); + + Derivation drv = derivationFromPath(storePath); - else abort(); + for (PathSet::iterator i = drv.inputDrvs.begin(); + i != drv.inputDrvs.end(); ++i) + storePathRequisites(*i, includeOutputs, paths); - if (includeExprs) paths.insert(nePath); + for (PathSet::iterator i = drv.inputSrcs.begin(); + i != drv.inputSrcs.end(); ++i) + storePathRequisites(*i, includeOutputs, paths); - Path nfPath; - if (includeSuccessors && querySuccessor(nePath, nfPath)) - requisitesWorker(nfPath, includeExprs, includeSuccessors, - paths, doneSet); + if (includeOutputs) { + + for (DerivationOutputs::iterator i = drv.outputs.begin(); + i != drv.outputs.end(); ++i) + if (isValidPath(i->second.path)) + storePathRequisites(i->second.path, includeOutputs, paths); + + } + + } + + else { + computeFSClosure(storePath, paths); + } } - - -PathSet storeExprRequisites(const Path & nePath, - bool includeExprs, bool includeSuccessors) -{ - PathSet paths; - PathSet doneSet; - requisitesWorker(nePath, includeExprs, includeSuccessors, - paths, doneSet); - return paths; -} -#endif diff --git a/src/libstore/normalise.cc b/src/libstore/normalise.cc index a01b6d8017..9424bd24ab 100644 --- a/src/libstore/normalise.cc +++ b/src/libstore/normalise.cc @@ -1307,6 +1307,9 @@ void SubstitutionGoal::init() return; } + /* !!! build the outgoing references of this path first to + maintain the closure invariant! */ + /* Otherwise, get the substitutes. */ subs = querySubstitutes(storePath); diff --git a/src/libstore/normalise.hh b/src/libstore/normalise.hh index 2a084b7ed4..c5257f9b9d 100644 --- a/src/libstore/normalise.hh +++ b/src/libstore/normalise.hh @@ -3,7 +3,6 @@ #include "storeexpr.hh" - /* Perform the specified derivation, if necessary. That is, do whatever is necessary to create the output paths of the derivation. If the output paths already exists, we're done. If @@ -20,29 +19,29 @@ void ensurePath(const Path & storePath); through ensurePath(). */ Derivation derivationFromPath(const Path & drvPath); - -/* Places in `paths' the set of all store paths in the file system +/* Place in `paths' the set of all store paths in the file system closure of `storePath'; that is, all paths than can be directly or indirectly reached from it. `paths' is not cleared. */ void computeFSClosure(const Path & storePath, PathSet & paths); +/* Place in `paths' the set of paths that are required to `realise' + the given store path, i.e., all paths necessary for valid + deployment of the path. For a derivation, this is the union of + requisites of the inputs, plus the derivation; for other store + paths, it is the set of paths in the FS closure of the path. If + `includeOutputs' is true, include the requisites of the output + paths of derivations as well. -#if 0 -/* Get the list of root (output) paths of the given store - expression. */ -PathSet storeExprRoots(const Path & nePath); - -/* Get the list of paths that are required to realise the given store - expression. For a derive expression, this is the union of - requisites of the inputs; for a closure expression, it is the path - of each element in the closure. If `includeExprs' is true, include - the paths of the store expressions themselves. If - `includeSuccessors' is true, include the requisites of - successors. */ -PathSet storeExprRequisites(const Path & nePath, - bool includeExprs, bool includeSuccessors); -#endif + Note that this function can be used to implement three different + deployment policies: + - Source deployment (when called on a derivation). + - Binary deployment (when called on an output path). + - Source/binary deployment (when called on a derivation with + `includeOutputs' set to true). +*/ +void storePathRequisites(const Path & storePath, + bool includeOutputs, PathSet & paths); #endif /* !__NORMALISE_H */ diff --git a/src/libstore/store.cc b/src/libstore/store.cc index 51e2e7e7d2..01c724b918 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -217,6 +217,8 @@ void setReferences(const Transaction & txn, const Path & storePath, void queryReferences(const Path & storePath, PathSet & references) { Paths references2; + if (!isValidPath(storePath)) + throw Error(format("path `%1%' is not valid") % storePath); nixDB.queryStrings(noTxn, dbReferences, storePath, references2); references.insert(references2.begin(), references2.end()); } diff --git a/src/libstore/storeexpr.cc b/src/libstore/storeexpr.cc index d7c87bfa15..a9240130e7 100644 --- a/src/libstore/storeexpr.cc +++ b/src/libstore/storeexpr.cc @@ -12,11 +12,10 @@ Hash hashTerm(ATerm t) } -Path writeTerm(ATerm t, const string & suffix) +Path writeDerivation(const Derivation & drv, const string & name) { - char * s = ATwriteToString(t); - if (!s) throw Error("cannot print aterm"); - return addTextToStore(suffix + ".store", string(s)); + return addTextToStore(name + drvExtension, + atPrint(unparseDerivation(drv))); } @@ -133,3 +132,11 @@ ATerm unparseDerivation(const Derivation & drv) ATreverse(args), ATreverse(env)); } + + +bool isDerivation(const string & fileName) +{ + return + fileName.size() >= drvExtension.size() && + string(fileName, fileName.size() - drvExtension.size()) == drvExtension; +} diff --git a/src/libstore/storeexpr.hh b/src/libstore/storeexpr.hh index 8eb80a19a8..c7b35f8ebe 100644 --- a/src/libstore/storeexpr.hh +++ b/src/libstore/storeexpr.hh @@ -5,23 +5,11 @@ #include "store.hh" -/* Abstract syntax of store expressions. */ +/* Extension of derivations in the Nix store. */ +const string drvExtension = ".drv"; -struct ClosureElem -{ - PathSet refs; -}; - -typedef map ClosureElems; - -/* -struct Closure -{ - PathSet roots; - ClosureElems elems; -}; -*/ +/* Abstract syntax of derivations. */ struct DerivationOutput { @@ -57,14 +45,18 @@ struct Derivation /* Hash an aterm. */ Hash hashTerm(ATerm t); -/* Write an aterm to the Nix store directory, and return its path. */ -Path writeTerm(ATerm t, const string & suffix); +/* Write a derivation to the Nix store, and return its path. */ +Path writeDerivation(const Derivation & drv, const string & name); -/* Parse a store expression. */ +/* Parse a derivation. */ Derivation parseDerivation(ATerm t); -/* Parse a store expression. */ +/* Parse a derivation. */ ATerm unparseDerivation(const Derivation & drv); +/* Check whether a file name ends with the extensions for + derivations. */ +bool isDerivation(const string & fileName); + #endif /* !__STOREEXPR_H */ diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc index c9498907d5..4d2ad0c897 100644 --- a/src/nix-env/main.cc +++ b/src/nix-env/main.cc @@ -205,7 +205,7 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs, /* Also write a copy of the list of inputs to the store; we need it for future modifications of the environment. */ - Path inputsFile = writeTerm(inputs2, "env-inputs"); + Path inputsFile = addTextToStore("env-inputs", atPrint(inputs2)); Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3( makeBind(toATerm("system"), diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt index cbded730e8..1bd752fc11 100644 --- a/src/nix-store/help.txt +++ b/src/nix-store/help.txt @@ -4,14 +4,12 @@ nix-store [OPTIONS...] [ARGUMENTS...] Operations: - --realise / -r: realise a Nix expression - --delete / -d: delete paths from the Nix store + --build / -b: build a Nix derivation --add / -A: copy a path to the Nix store --query / -q: query information - --successor: register a successor expression (dangerous!) --substitute: register a substitute expression (dangerous!) - --clear-substitute: clear all substitutes + --clear-substitutes: clear all substitutes --validpath: register path validity (dangerous!) --isvalid: check path validity @@ -26,9 +24,10 @@ Operations: 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 + --outputs: query the output paths of a Nix derivation (default) + --requisites / -R: print all paths necessary to realise a path + --references: print all paths referenced by the given path + --referers: print all paths refering to the given path --graph: print a dot graph rooted at given ids Options: diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index 5a67a6af64..12b61c76f7 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -18,6 +18,15 @@ void printHelp() } +static Path findOutput(const Derivation & drv, string id) +{ + for (DerivationOutputs::const_iterator i = drv.outputs.begin(); + i != drv.outputs.end(); ++i) + if (i->first == id) return i->second.path; + throw Error(format("derivation has no output `%1%'") % id); +} + + /* Build the given derivations. */ static void opBuild(Strings opFlags, Strings opArgs) { @@ -25,7 +34,11 @@ static void opBuild(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++) + { buildDerivation(*i); + Derivation drv = derivationFromPath(*i); + cout << format("%1%\n") % findOutput(drv, "out"); + } } @@ -40,70 +53,59 @@ static void opAdd(Strings opFlags, Strings opArgs) } -#if 0 -Path maybeNormalise(const Path & ne, bool normalise, bool realise) +static Path maybeUseOutput(const Path & storePath, bool useOutput) { - if (realise) { - Path ne2 = realiseStoreExpr(ne); - return normalise ? ne2 : ne; - } else - return normalise ? normaliseStoreExpr(ne) : ne; + if (useOutput && isDerivation(storePath)) { + Derivation drv = derivationFromPath(storePath); + return findOutput(drv, "out"); + } + else return storePath; } /* Perform various sorts of queries. */ static void opQuery(Strings opFlags, Strings opArgs) { - enum { qList, qRequisites, qPredecessors, qGraph - } query = qList; - bool normalise = false; - bool realise = false; - bool includeExprs = true; - bool includeSuccessors = false; + enum { qOutputs, qRequisites, qPredecessors, qGraph } query = qOutputs; + bool useOutput = false; + bool includeOutputs = false; for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); i++) - if (*i == "--list" || *i == "-l") query = qList; + if (*i == "--outputs") query = qOutputs; 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 == "--force-realise" || *i == "-f") realise = true; - else if (*i == "--exclude-exprs") includeExprs = false; - else if (*i == "--include-successors") includeSuccessors = true; + else if (*i == "--use-output" || *i == "-u") useOutput = true; + else if (*i == "--include-outputs") includeOutputs = true; else throw UsageError(format("unknown flag `%1%'") % *i); switch (query) { - case qList: { + case qOutputs: { for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++) { - StringSet paths = storeExprRoots( - maybeNormalise(*i, normalise, realise)); - for (StringSet::iterator j = paths.begin(); - j != paths.end(); j++) - cout << format("%s\n") % *j; + Derivation drv = derivationFromPath(*i); + cout << format("%1%\n") % findOutput(drv, "out"); } break; } case qRequisites: { - StringSet paths; + PathSet paths; for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++) { - StringSet paths2 = storeExprRequisites( - maybeNormalise(*i, normalise, realise), - includeExprs, includeSuccessors); - paths.insert(paths2.begin(), paths2.end()); + Path path = maybeUseOutput(*i, useOutput); + storePathRequisites(path, includeOutputs, paths); } - for (StringSet::iterator i = paths.begin(); + for (PathSet::iterator i = paths.begin(); i != paths.end(); i++) cout << format("%s\n") % *i; break; } +#if 0 case qPredecessors: { for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++) @@ -124,12 +126,12 @@ static void opQuery(Strings opFlags, Strings opArgs) printDotGraph(roots); break; } +#endif default: abort(); } } -#endif static void opSubstitute(Strings opFlags, Strings opArgs) @@ -340,8 +342,8 @@ void run(Strings args) op = opBuild; else if (arg == "--add" || arg == "-A") op = opAdd; - // else if (arg == "--query" || arg == "-q") - // op = opQuery; + else if (arg == "--query" || arg == "-q") + op = opQuery; else if (arg == "--substitute") op = opSubstitute; else if (arg == "--clear-substitutes") diff --git a/tests/dependencies.sh b/tests/dependencies.sh index 8a0ba1f2a1..a9b9cd083f 100644 --- a/tests/dependencies.sh +++ b/tests/dependencies.sh @@ -2,7 +2,7 @@ storeExpr=$($TOP/src/nix-instantiate/nix-instantiate dependencies.nix) echo "store expr is $storeExpr" -outPath=$($TOP/src/nix-store/nix-store -qnfvvvvv "$storeExpr") +outPath=$($TOP/src/nix-store/nix-store -bvv "$storeExpr") echo "output path is $outPath" diff --git a/tests/simple.sh b/tests/simple.sh index 68da000d19..4da1a7b533 100644 --- a/tests/simple.sh +++ b/tests/simple.sh @@ -2,7 +2,7 @@ storeExpr=$($TOP/src/nix-instantiate/nix-instantiate simple.nix) echo "store expr is $storeExpr" -outPath=$($TOP/src/nix-store/nix-store -qnfvvvvv "$storeExpr") +outPath=$($TOP/src/nix-store/nix-store -bvv "$storeExpr") echo "output path is $outPath"