diff options
Diffstat (limited to 'src/libstore')
-rw-r--r-- | src/libstore/misc.cc | 5 | ||||
-rw-r--r-- | src/libstore/normalise.cc | 59 | ||||
-rw-r--r-- | src/libstore/store.cc | 10 | ||||
-rw-r--r-- | src/libstore/store.hh | 2 | ||||
-rw-r--r-- | src/libstore/storeexpr-ast.def | 1 | ||||
-rw-r--r-- | src/libstore/storeexpr.cc | 37 | ||||
-rw-r--r-- | src/libstore/storeexpr.hh | 22 |
7 files changed, 103 insertions, 33 deletions
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index d7c32336e..6dc054fb4 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -20,8 +20,9 @@ PathSet storeExprRoots(const Path & nePath) if (ne.type == StoreExpr::neClosure) paths.insert(ne.closure.roots.begin(), ne.closure.roots.end()); else if (ne.type == StoreExpr::neDerivation) - paths.insert(ne.derivation.outputs.begin(), - ne.derivation.outputs.end()); + for (DerivationOutputs::iterator i = ne.derivation.outputs.begin(); + i != ne.derivation.outputs.end(); ++i) + paths.insert(i->second.path); else abort(); return paths; diff --git a/src/libstore/normalise.cc b/src/libstore/normalise.cc index 7907325a9..b016d8d35 100644 --- a/src/libstore/normalise.cc +++ b/src/libstore/normalise.cc @@ -702,6 +702,29 @@ static void drain(int fd) } +PathSet outputPaths(const DerivationOutputs & outputs) +{ + PathSet paths; + for (DerivationOutputs::const_iterator i = outputs.begin(); + i != outputs.end(); ++i) + paths.insert(i->second.path); + return paths; +} + + +string showPaths(const PathSet & paths) +{ + string s; + for (PathSet::const_iterator i = paths.begin(); + i != paths.end(); ++i) + { + if (s.size() != 0) s += ", "; + s += *i; + } + return s; +} + + NormalisationGoal::HookReply NormalisationGoal::tryBuildHook() { Path buildHook = getEnv("NIX_BUILD_HOOK"); @@ -786,7 +809,7 @@ NormalisationGoal::HookReply NormalisationGoal::tryBuildHook() } printMsg(lvlInfo, format("running hook to build path `%1%'") - % *expr.derivation.outputs.begin()); + % showPaths(outputPaths(expr.derivation.outputs))); /* Write the information that the hook needs to perform the build, i.e., the set of input paths (including closure @@ -807,9 +830,9 @@ NormalisationGoal::HookReply NormalisationGoal::tryBuildHook() writeStringToFile(inputListFN, s); s = ""; - for (PathSet::iterator i = expr.derivation.outputs.begin(); + for (DerivationOutputs::iterator i = expr.derivation.outputs.begin(); i != expr.derivation.outputs.end(); ++i) - s += *i + "\n"; + s += i->second.path + "\n"; writeStringToFile(outputListFN, s); s = ""; @@ -848,7 +871,7 @@ bool NormalisationGoal::prepareBuild() /* Obtain locks on all output paths. The locks are automatically released when we exit this function or Nix crashes. */ /* !!! BUG: this could block, which is not allowed. */ - outputLocks.lockPaths(expr.derivation.outputs); + outputLocks.lockPaths(outputPaths(expr.derivation.outputs)); /* Now check again whether there is a successor. This is because another process may have started building in parallel. After @@ -870,11 +893,11 @@ bool NormalisationGoal::prepareBuild() running the build hook. */ /* The outputs are referenceable paths. */ - for (PathSet::iterator i = expr.derivation.outputs.begin(); + for (DerivationOutputs::iterator i = expr.derivation.outputs.begin(); i != expr.derivation.outputs.end(); ++i) { - debug(format("building path `%1%'") % *i); - allPaths.insert(*i); + debug(format("building path `%1%'") % i->second.path); + allPaths.insert(i->second.path); } /* Get information about the inputs (these all exist now). */ @@ -901,9 +924,9 @@ bool NormalisationGoal::prepareBuild() /* We can skip running the builder if all output paths are already valid. */ bool fastBuild = true; - for (PathSet::iterator i = expr.derivation.outputs.begin(); + for (DerivationOutputs::iterator i = expr.derivation.outputs.begin(); i != expr.derivation.outputs.end(); ++i) - if (!isValidPath(*i)) { + if (!isValidPath(i->second.path)) { fastBuild = false; break; } @@ -921,7 +944,7 @@ bool NormalisationGoal::prepareBuild() void NormalisationGoal::startBuilder() { startNest(nest, lvlInfo, - format("building path `%1%'") % *expr.derivation.outputs.begin()); + format("building path `%1%'") % showPaths(outputPaths(expr.derivation.outputs))) /* Right platform? */ if (expr.derivation.platform != thisSystem) @@ -931,10 +954,10 @@ void NormalisationGoal::startBuilder() /* If any of the outputs already exist but are not registered, delete them. */ - for (PathSet::iterator i = expr.derivation.outputs.begin(); + for (DerivationOutputs::iterator i = expr.derivation.outputs.begin(); i != expr.derivation.outputs.end(); ++i) { - Path path = *i; + Path path = i->second.path; if (isValidPath(path)) throw Error(format("obstructed build: path `%1%' exists") % path); if (pathExists(path)) { @@ -1054,10 +1077,10 @@ void NormalisationGoal::createClosure() output path to determine what other paths it references. Also make all output paths read-only. */ PathSet usedPaths; - for (PathSet::iterator i = expr.derivation.outputs.begin(); + for (DerivationOutputs::iterator i = expr.derivation.outputs.begin(); i != expr.derivation.outputs.end(); ++i) { - Path path = *i; + Path path = i->second.path; if (!pathExists(path)) { throw BuildError( format("builder for `%1%' failed to produce output path `%2%'") @@ -1084,6 +1107,7 @@ void NormalisationGoal::createClosure() /* For each path referenced by this output path, add its id to the closure element and add the id to the `usedPaths' set (so that the elements referenced by *its* closure are added below). */ + PathSet outputPaths = ::outputPaths(expr.derivation.outputs); for (Paths::iterator j = refPaths.begin(); j != refPaths.end(); ++j) { @@ -1092,8 +1116,7 @@ void NormalisationGoal::createClosure() elem.refs.insert(path); if (inClosures.find(path) != inClosures.end()) usedPaths.insert(path); - else if (expr.derivation.outputs.find(path) == - expr.derivation.outputs.end()) + else if (outputPaths.find(path) == outputPaths.end()) abort(); } @@ -1147,9 +1170,9 @@ void NormalisationGoal::createClosure() by running the garbage collector. */ Transaction txn; createStoreTransaction(txn); - for (PathSet::iterator i = expr.derivation.outputs.begin(); + for (DerivationOutputs::iterator i = expr.derivation.outputs.begin(); i != expr.derivation.outputs.end(); ++i) - registerValidPath(txn, *i); + registerValidPath(txn, i->second.path); registerSuccessor(txn, nePath, nfPath); txn.commit(); diff --git a/src/libstore/store.cc b/src/libstore/store.cc index e490bf258..0d89f7a5d 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -412,14 +412,14 @@ static void invalidatePath(const Path & path, Transaction & txn) Path makeStorePath(const string & type, - Hash & hash, const string & suffix) + const Hash & hash, const string & suffix) { /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ string s = type + ":sha256:" + printHash(hash) + ":" + nixStore + ":" + suffix; return nixStore + "/" - + printHash32(compressHash(hashString(s, htSHA256), 20)) + + printHash32(compressHash(hashString(htSHA256, s), 20)) + "-" + suffix; } @@ -432,7 +432,7 @@ Path addToStore(const Path & _srcPath) Hash h(htSHA256); { SwitchToOriginalUser sw; - h = hashPath(srcPath, htSHA256); + h = hashPath(htSHA256, srcPath); } string baseName = baseNameOf(srcPath); @@ -456,7 +456,7 @@ Path addToStore(const Path & _srcPath) copyPath(srcPath, dstPath); - Hash h2 = hashPath(dstPath, htSHA256); + Hash h2 = hashPath(htSHA256, dstPath); if (h != h2) throw Error(format("contents of `%1%' changed while copying it to `%2%' (%3% -> %4%)") % srcPath % dstPath % printHash(h) % printHash(h2)); @@ -477,7 +477,7 @@ Path addToStore(const Path & _srcPath) Path addTextToStore(const string & suffix, const string & s) { - Hash hash = hashString(s, htSHA256); + Hash hash = hashString(htSHA256, s); Path dstPath = makeStorePath("text", hash, suffix); diff --git a/src/libstore/store.hh b/src/libstore/store.hh index 25a6bc8b9..c27918cbb 100644 --- a/src/libstore/store.hh +++ b/src/libstore/store.hh @@ -83,7 +83,7 @@ bool isValidPath(const Path & path); /* Constructs a unique store path name. */ Path makeStorePath(const string & type, - Hash & hash, const string & suffix); + const Hash & hash, const string & suffix); /* Copy the contents of a path to the store and register the validity the resulting path. The resulting path is returned. */ diff --git a/src/libstore/storeexpr-ast.def b/src/libstore/storeexpr-ast.def index 9d2433dbe..0c70948d4 100644 --- a/src/libstore/storeexpr-ast.def +++ b/src/libstore/storeexpr-ast.def @@ -5,3 +5,4 @@ Derive | ATermList ATermList string string ATermList ATermList | ATerm | | string string | ATerm | EnvBinding | | string ATermList | ATerm | ClosureElem | +| string string string string | ATerm | DerivationOutput | diff --git a/src/libstore/storeexpr.cc b/src/libstore/storeexpr.cc index de29959ed..d8300a066 100644 --- a/src/libstore/storeexpr.cc +++ b/src/libstore/storeexpr.cc @@ -8,7 +8,7 @@ Hash hashTerm(ATerm t) { - return hashString(atPrint(t), htMD5); + return hashString(htSHA256, atPrint(t)); } @@ -20,14 +20,20 @@ Path writeTerm(ATerm t, const string & suffix) } +void checkPath(const string & s) +{ + if (s.size() == 0 || s[0] != '/') + throw Error(format("bad path `%1%' in store expression") % s); +} + + static void parsePaths(ATermList paths, PathSet & out) { for (ATermIterator i(paths); i; ++i) { if (ATgetType(*i) != AT_APPL) throw badTerm("not a path", *i); string s = aterm2String(*i); - if (s.size() == 0 || s[0] != '/') - throw badTerm("not a path", *i); + checkPath(s); out.insert(s); } } @@ -92,7 +98,18 @@ static bool parseDerivation(ATerm t, Derivation & derivation) if (!matchDerive(t, outs, ins, platform, builder, args, bnds)) return false; - parsePaths(outs, derivation.outputs); + for (ATermIterator i(outs); i; ++i) { + ATerm id, path, hashAlgo, hash; + if (!matchDerivationOutput(*i, id, path, hashAlgo, hash)) + return false; + DerivationOutput out; + out.path = aterm2String(path); + checkPath(out.path); + out.hashAlgo = aterm2String(hashAlgo); + out.hash = aterm2String(hash); + derivation.outputs[aterm2String(id)] = out; + } + parsePaths(ins, derivation.inputs); derivation.builder = aterm2String(builder); @@ -155,6 +172,16 @@ static ATerm unparseClosure(const Closure & closure) static ATerm unparseDerivation(const Derivation & derivation) { + ATermList outputs = ATempty; + for (DerivationOutputs::const_iterator i = derivation.outputs.begin(); + i != derivation.outputs.end(); i++) + outputs = ATinsert(outputs, + makeDerivationOutput( + toATerm(i->first), + toATerm(i->second.path), + toATerm(i->second.hashAlgo), + toATerm(i->second.hash))); + ATermList args = ATempty; for (Strings::const_iterator i = derivation.args.begin(); i != derivation.args.end(); i++) @@ -169,7 +196,7 @@ static ATerm unparseDerivation(const Derivation & derivation) toATerm(i->second))); return makeDerive( - unparsePaths(derivation.outputs), + ATreverse(outputs), unparsePaths(derivation.inputs), toATerm(derivation.platform), toATerm(derivation.builder), diff --git a/src/libstore/storeexpr.hh b/src/libstore/storeexpr.hh index 07676c3cc..d8b8b2a96 100644 --- a/src/libstore/storeexpr.hh +++ b/src/libstore/storeexpr.hh @@ -20,12 +20,30 @@ struct Closure ClosureElems elems; }; + +struct DerivationOutput +{ + Path path; + string hashAlgo; /* hash used for expected hash computation */ + string hash; /* expected hash, may be null */ + DerivationOutput() + { + } + DerivationOutput(Path path, string hashAlgo, string hash) + { + this->path = path; + this->hashAlgo = hashAlgo; + this->hash = hash; + } +}; + +typedef map<string, DerivationOutput> DerivationOutputs; typedef map<string, string> StringPairs; struct Derivation { - PathSet outputs; - PathSet inputs; /* Store expressions, not actual inputs */ + DerivationOutputs outputs; /* keyed on symbolic IDs */ + PathSet inputs; /* store expressions, not actual inputs */ string platform; Path builder; Strings args; |