* Start move towards SHA-256 hashes instead of MD5.
* Start cleaning up unique store path generation (they weren't always unique; in particular the suffix ("-aterm-2.2", "-builder.sh") was not part of the hash, therefore changes to the suffix would cause multiple store objects with the same hash).
This commit is contained in:
parent
a7b94e87d7
commit
9530cc3170
9 changed files with 63 additions and 34 deletions
|
@ -59,7 +59,7 @@ static Path copyAtom(EvalState & state, const Path & srcPath)
|
||||||
ne.closure.elems[dstPath] = elem;
|
ne.closure.elems[dstPath] = elem;
|
||||||
|
|
||||||
Hash drvHash = hashDerivation(state, ne);
|
Hash drvHash = hashDerivation(state, ne);
|
||||||
Path drvPath = writeTerm(unparseStoreExpr(ne), "");
|
Path drvPath = writeTerm(unparseStoreExpr(ne), "c");
|
||||||
state.drvHashes.insert(make_pair(drvPath, drvHash));
|
state.drvHashes.insert(make_pair(drvPath, drvHash));
|
||||||
|
|
||||||
state.drvRoots[drvPath] = ne.closure.roots;
|
state.drvRoots[drvPath] = ne.closure.roots;
|
||||||
|
@ -250,21 +250,32 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
|
||||||
throw Error(format("invalid character `%1%' in derivation name `%2%'")
|
throw Error(format("invalid character `%1%' in derivation name `%2%'")
|
||||||
% *i % drvName);
|
% *i % drvName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Construct the "masked" derivation store expression, which is
|
||||||
|
the final one except that the list of output paths is set to
|
||||||
|
the set of output names, and the corresponding environment
|
||||||
|
variables have an empty value. This ensures that changes in
|
||||||
|
the set of output names do get reflected in the hash. */
|
||||||
|
ne.derivation.env["out"] = "";
|
||||||
|
ne.derivation.outputs.insert("out");
|
||||||
|
|
||||||
/* Determine the output path by hashing the Nix expression with no
|
/* Determine the output path by hashing the Nix expression with no
|
||||||
outputs to produce a unique but deterministic path name for
|
outputs to produce a unique but deterministic path name for
|
||||||
this derivation. */
|
this derivation. */
|
||||||
if (!outHashGiven) outHash = hashDerivation(state, ne);
|
if (!outHashGiven) outHash = hashDerivation(state, ne);
|
||||||
Path outPath = canonPath(nixStore + "/" +
|
Path outPath = makeStorePath("output:out",
|
||||||
((string) outHash).c_str() + "-" + drvName);
|
outHash, drvName);
|
||||||
|
|
||||||
|
/* Construct the final derivation store expression. */
|
||||||
ne.derivation.env["out"] = outPath;
|
ne.derivation.env["out"] = outPath;
|
||||||
|
ne.derivation.outputs.clear();
|
||||||
ne.derivation.outputs.insert(outPath);
|
ne.derivation.outputs.insert(outPath);
|
||||||
|
|
||||||
/* Write the resulting term into the Nix store directory. */
|
/* Write the resulting term into the Nix store directory. */
|
||||||
Hash drvHash = outHashGiven
|
Hash drvHash = outHashGiven
|
||||||
? hashString((string) outHash + outPath, htMD5)
|
? hashString((string) outHash + outPath, htMD5)
|
||||||
: hashDerivation(state, ne);
|
: hashDerivation(state, ne);
|
||||||
Path drvPath = writeTerm(unparseStoreExpr(ne), "-d-" + drvName);
|
Path drvPath = writeTerm(unparseStoreExpr(ne), "d-" + drvName);
|
||||||
|
|
||||||
printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'")
|
printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'")
|
||||||
% drvName % drvPath);
|
% drvName % drvPath);
|
||||||
|
|
|
@ -69,10 +69,10 @@ static void initAndRun(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup Nix paths. */
|
/* Setup Nix paths. */
|
||||||
nixStore = getEnv("NIX_STORE_DIR", canonPath(NIX_STORE_DIR));
|
nixStore = canonPath(getEnv("NIX_STORE_DIR", NIX_STORE_DIR));
|
||||||
nixDataDir = getEnv("NIX_DATA_DIR", canonPath(NIX_DATA_DIR));
|
nixDataDir = canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR));
|
||||||
nixLogDir = getEnv("NIX_LOG_DIR", canonPath(NIX_LOG_DIR));
|
nixLogDir = canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR));
|
||||||
nixStateDir = getEnv("NIX_STATE_DIR", canonPath(NIX_STATE_DIR));
|
nixStateDir = canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR));
|
||||||
nixDBPath = getEnv("NIX_DB_DIR", nixStateDir + "/db");
|
nixDBPath = getEnv("NIX_DB_DIR", nixStateDir + "/db");
|
||||||
|
|
||||||
/* Check that the store directory and its parent are not
|
/* Check that the store directory and its parent are not
|
||||||
|
|
|
@ -1137,7 +1137,7 @@ void NormalisationGoal::createClosure()
|
||||||
/* Write the normal form. This does not have to occur in the
|
/* Write the normal form. This does not have to occur in the
|
||||||
transaction below because writing terms is idem-potent. */
|
transaction below because writing terms is idem-potent. */
|
||||||
ATerm nfTerm = unparseStoreExpr(nf);
|
ATerm nfTerm = unparseStoreExpr(nf);
|
||||||
Path nfPath = writeTerm(nfTerm, "-s");
|
Path nfPath = writeTerm(nfTerm, "s");
|
||||||
|
|
||||||
/* Register each output path, and register the normal form. This
|
/* Register each output path, and register the normal form. This
|
||||||
is wrapped in one database transaction to ensure that if we
|
is wrapped in one database transaction to ensure that if we
|
||||||
|
|
|
@ -411,19 +411,34 @@ static void invalidatePath(const Path & path, Transaction & txn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Path makeStorePath(const string & type,
|
||||||
|
Hash & hash, const string & suffix)
|
||||||
|
{
|
||||||
|
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
|
||||||
|
string s = type + ":sha256:" + (string) hash + ":"
|
||||||
|
+ nixStore + ":" + suffix;
|
||||||
|
|
||||||
|
Hash nameHash = hashString(s, htSHA256);
|
||||||
|
|
||||||
|
printMsg(lvlError, format("name input: %1% -> %2%") % s % (string) nameHash);
|
||||||
|
|
||||||
|
return nixStore + "/" + (string) nameHash + "-" + suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Path addToStore(const Path & _srcPath)
|
Path addToStore(const Path & _srcPath)
|
||||||
{
|
{
|
||||||
Path srcPath(absPath(_srcPath));
|
Path srcPath(absPath(_srcPath));
|
||||||
debug(format("adding `%1%' to the store") % srcPath);
|
debug(format("adding `%1%' to the store") % srcPath);
|
||||||
|
|
||||||
Hash h(htMD5);
|
Hash h(htSHA256);
|
||||||
{
|
{
|
||||||
SwitchToOriginalUser sw;
|
SwitchToOriginalUser sw;
|
||||||
h = hashPath(srcPath, htMD5);
|
h = hashPath(srcPath, htSHA256);
|
||||||
}
|
}
|
||||||
|
|
||||||
string baseName = baseNameOf(srcPath);
|
string baseName = baseNameOf(srcPath);
|
||||||
Path dstPath = canonPath(nixStore + "/" + (string) h + "-" + baseName);
|
Path dstPath = makeStorePath("source", h, baseName);
|
||||||
|
|
||||||
if (!readOnlyMode && !isValidPath(dstPath)) {
|
if (!readOnlyMode && !isValidPath(dstPath)) {
|
||||||
|
|
||||||
|
@ -443,6 +458,11 @@ Path addToStore(const Path & _srcPath)
|
||||||
|
|
||||||
copyPath(srcPath, dstPath);
|
copyPath(srcPath, dstPath);
|
||||||
|
|
||||||
|
Hash h2 = hashPath(dstPath, htSHA256);
|
||||||
|
if (h != h2)
|
||||||
|
throw Error(format("contents of `%1%' changed while copying it to `%2%' (%3% -> %4%)")
|
||||||
|
% srcPath % dstPath % (string) h % (string) h2);
|
||||||
|
|
||||||
makePathReadOnly(dstPath);
|
makePathReadOnly(dstPath);
|
||||||
|
|
||||||
Transaction txn(nixDB);
|
Transaction txn(nixDB);
|
||||||
|
@ -457,11 +477,13 @@ Path addToStore(const Path & _srcPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void addTextToStore(const Path & dstPath, const string & s)
|
Path addTextToStore(const string & suffix, const string & s)
|
||||||
{
|
{
|
||||||
assertStorePath(dstPath);
|
Hash hash = hashString(s, htSHA256);
|
||||||
|
|
||||||
|
Path dstPath = makeStorePath("text", hash, suffix);
|
||||||
|
|
||||||
if (!isValidPath(dstPath)) {
|
if (!readOnlyMode && !isValidPath(dstPath)) {
|
||||||
|
|
||||||
PathSet lockPaths;
|
PathSet lockPaths;
|
||||||
lockPaths.insert(dstPath);
|
lockPaths.insert(dstPath);
|
||||||
|
@ -482,6 +504,8 @@ void addTextToStore(const Path & dstPath, const string & s)
|
||||||
|
|
||||||
outputLock.setDeletion(true);
|
outputLock.setDeletion(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return dstPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,14 +81,17 @@ void assertStorePath(const Path & path);
|
||||||
/* Checks whether a path is valid. */
|
/* Checks whether a path is valid. */
|
||||||
bool isValidPath(const Path & path);
|
bool isValidPath(const Path & path);
|
||||||
|
|
||||||
|
/* Constructs a unique store path name. */
|
||||||
|
Path makeStorePath(const string & type,
|
||||||
|
Hash & hash, const string & suffix);
|
||||||
|
|
||||||
/* Copy the contents of a path to the store and register the validity
|
/* Copy the contents of a path to the store and register the validity
|
||||||
the resulting path. The resulting path is returned. */
|
the resulting path. The resulting path is returned. */
|
||||||
Path addToStore(const Path & srcPath);
|
Path addToStore(const Path & srcPath);
|
||||||
|
|
||||||
/* Like addToStore, but the path of the output is given, and the
|
/* Like addToStore, but the contents written to the output path is a
|
||||||
contents written to the output path is a regular file containing
|
regular file containing the given string. */
|
||||||
the given string. */
|
Path addTextToStore(const string & suffix, const string & s);
|
||||||
void addTextToStore(const Path & dstPath, const string & s);
|
|
||||||
|
|
||||||
/* Delete a value from the nixStore directory. */
|
/* Delete a value from the nixStore directory. */
|
||||||
void deleteFromStore(const Path & path);
|
void deleteFromStore(const Path & path);
|
||||||
|
|
|
@ -14,19 +14,9 @@ Hash hashTerm(ATerm t)
|
||||||
|
|
||||||
Path writeTerm(ATerm t, const string & suffix)
|
Path writeTerm(ATerm t, const string & suffix)
|
||||||
{
|
{
|
||||||
/* The id of a term is its hash. */
|
char * s = ATwriteToString(t);
|
||||||
Hash h = hashTerm(t);
|
if (!s) throw Error("cannot print aterm");
|
||||||
|
return addTextToStore(suffix + ".store", string(s));
|
||||||
Path path = canonPath(nixStore + "/" +
|
|
||||||
(string) h + suffix + ".store");
|
|
||||||
|
|
||||||
if (!readOnlyMode && !isValidPath(path)) {
|
|
||||||
char * s = ATwriteToString(t);
|
|
||||||
if (!s) throw Error(format("cannot write aterm to `%1%'") % path);
|
|
||||||
addTextToStore(path, string(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ Hash::Hash(HashType type)
|
||||||
else if (type == htSHA1) hashSize = sha1HashSize;
|
else if (type == htSHA1) hashSize = sha1HashSize;
|
||||||
else if (type == htSHA256) hashSize = sha256HashSize;
|
else if (type == htSHA256) hashSize = sha256HashSize;
|
||||||
else throw Error("unknown hash type");
|
else throw Error("unknown hash type");
|
||||||
|
assert(hashSize <= maxHashSize);
|
||||||
memset(hash, 0, hashSize);
|
memset(hash, 0, hashSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ const int sha256HashSize = 32;
|
||||||
|
|
||||||
struct Hash
|
struct Hash
|
||||||
{
|
{
|
||||||
static const unsigned int maxHashSize = 20;
|
static const unsigned int maxHashSize = 32;
|
||||||
unsigned int hashSize;
|
unsigned int hashSize;
|
||||||
unsigned char hash[maxHashSize];
|
unsigned char hash[maxHashSize];
|
||||||
|
|
||||||
|
|
|
@ -216,7 +216,7 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
|
||||||
|
|
||||||
/* Also write a copy of the list of inputs to the store; we need
|
/* Also write a copy of the list of inputs to the store; we need
|
||||||
it for future modifications of the environment. */
|
it for future modifications of the environment. */
|
||||||
Path inputsFile = writeTerm(inputs2, "-env-inputs");
|
Path inputsFile = writeTerm(inputs2, "env-inputs");
|
||||||
|
|
||||||
Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3(
|
Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3(
|
||||||
makeBind(toATerm("system"),
|
makeBind(toATerm("system"),
|
||||||
|
|
Loading…
Reference in a new issue