aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/misc.cc5
-rw-r--r--src/libstore/normalise.cc59
-rw-r--r--src/libstore/store.cc10
-rw-r--r--src/libstore/store.hh2
-rw-r--r--src/libstore/storeexpr-ast.def1
-rw-r--r--src/libstore/storeexpr.cc37
-rw-r--r--src/libstore/storeexpr.hh22
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;