about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/primops.cc19
-rw-r--r--src/libmain/shared.cc8
-rw-r--r--src/libstore/normalise.cc2
-rw-r--r--src/libstore/store.cc36
-rw-r--r--src/libstore/store.hh11
-rw-r--r--src/libstore/storeexpr.cc16
-rw-r--r--src/libutil/hash.cc1
-rw-r--r--src/libutil/hash.hh2
-rw-r--r--src/nix-env/main.cc2
9 files changed, 63 insertions, 34 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index f73e60e387..59b85a6d62 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -59,7 +59,7 @@ static Path copyAtom(EvalState & state, const Path & srcPath)
     ne.closure.elems[dstPath] = elem;
 
     Hash drvHash = hashDerivation(state, ne);
-    Path drvPath = writeTerm(unparseStoreExpr(ne), "");
+    Path drvPath = writeTerm(unparseStoreExpr(ne), "c");
     state.drvHashes.insert(make_pair(drvPath, drvHash));
 
     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%'")
                 % *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
        outputs to produce a unique but deterministic path name for
        this derivation. */
     if (!outHashGiven) outHash = hashDerivation(state, ne);
-    Path outPath = canonPath(nixStore + "/" + 
-        ((string) outHash).c_str() + "-" + drvName);
+    Path outPath = makeStorePath("output:out",
+        outHash, drvName);
+
+    /* Construct the final derivation store expression. */
     ne.derivation.env["out"] = outPath;
+    ne.derivation.outputs.clear();
     ne.derivation.outputs.insert(outPath);
 
     /* Write the resulting term into the Nix store directory. */
     Hash drvHash = outHashGiven
         ? hashString((string) outHash + outPath, htMD5)
         : hashDerivation(state, ne);
-    Path drvPath = writeTerm(unparseStoreExpr(ne), "-d-" + drvName);
+    Path drvPath = writeTerm(unparseStoreExpr(ne), "d-" + drvName);
 
     printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'")
         % drvName % drvPath);
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index f608afd848..40750779c5 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -69,10 +69,10 @@ static void initAndRun(int argc, char * * argv)
     }
     
     /* Setup Nix paths. */
-    nixStore = getEnv("NIX_STORE_DIR", canonPath(NIX_STORE_DIR));
-    nixDataDir = getEnv("NIX_DATA_DIR", canonPath(NIX_DATA_DIR));
-    nixLogDir = getEnv("NIX_LOG_DIR", canonPath(NIX_LOG_DIR));
-    nixStateDir = getEnv("NIX_STATE_DIR", canonPath(NIX_STATE_DIR));
+    nixStore = canonPath(getEnv("NIX_STORE_DIR", NIX_STORE_DIR));
+    nixDataDir = canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR));
+    nixLogDir = canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR));
+    nixStateDir = canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR));
     nixDBPath = getEnv("NIX_DB_DIR", nixStateDir + "/db");
 
     /* Check that the store directory and its parent are not
diff --git a/src/libstore/normalise.cc b/src/libstore/normalise.cc
index d535fe2ee6..7907325a97 100644
--- a/src/libstore/normalise.cc
+++ b/src/libstore/normalise.cc
@@ -1137,7 +1137,7 @@ void NormalisationGoal::createClosure()
     /* Write the normal form.  This does not have to occur in the
        transaction below because writing terms is idem-potent. */
     ATerm nfTerm = unparseStoreExpr(nf);
-    Path nfPath = writeTerm(nfTerm, "-s");
+    Path nfPath = writeTerm(nfTerm, "s");
 
     /* Register each output path, and register the normal form.  This
        is wrapped in one database transaction to ensure that if we
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index b3b0dfc4f5..3a76618a5a 100644
--- a/src/libstore/store.cc
+++ b/src/libstore/store.cc
@@ -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 srcPath(absPath(_srcPath));
     debug(format("adding `%1%' to the store") % srcPath);
 
-    Hash h(htMD5);
+    Hash h(htSHA256);
     {
         SwitchToOriginalUser sw;
-        h = hashPath(srcPath, htMD5);
+        h = hashPath(srcPath, htSHA256);
     }
 
     string baseName = baseNameOf(srcPath);
-    Path dstPath = canonPath(nixStore + "/" + (string) h + "-" + baseName);
+    Path dstPath = makeStorePath("source", h, baseName);
 
     if (!readOnlyMode && !isValidPath(dstPath)) { 
 
@@ -443,6 +458,11 @@ Path addToStore(const Path & _srcPath)
             
             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);
             
             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;
         lockPaths.insert(dstPath);
@@ -482,6 +504,8 @@ void addTextToStore(const Path & dstPath, const string & s)
 
         outputLock.setDeletion(true);
     }
+
+    return dstPath;
 }
 
 
diff --git a/src/libstore/store.hh b/src/libstore/store.hh
index 6a989874bc..25a6bc8b96 100644
--- a/src/libstore/store.hh
+++ b/src/libstore/store.hh
@@ -81,14 +81,17 @@ void assertStorePath(const Path & path);
 /* Checks whether a path is valid. */ 
 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
    the resulting path.  The resulting path is returned. */
 Path addToStore(const Path & srcPath);
 
-/* Like addToStore, but the path of the output is given, and the
-   contents written to the output path is a regular file containing
-   the given string. */
-void addTextToStore(const Path & dstPath, const string & s);
+/* Like addToStore, but the contents written to the output path is a
+   regular file containing the given string. */
+Path addTextToStore(const string & suffix, const string & s);
 
 /* Delete a value from the nixStore directory. */
 void deleteFromStore(const Path & path);
diff --git a/src/libstore/storeexpr.cc b/src/libstore/storeexpr.cc
index 3308d5b06d..de29959edf 100644
--- a/src/libstore/storeexpr.cc
+++ b/src/libstore/storeexpr.cc
@@ -14,19 +14,9 @@ Hash hashTerm(ATerm t)
 
 Path writeTerm(ATerm t, const string & suffix)
 {
-    /* The id of a term is its hash. */
-    Hash h = hashTerm(t);
-
-    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;
+    char * s = ATwriteToString(t);
+    if (!s) throw Error("cannot print aterm");
+    return addTextToStore(suffix + ".store", string(s));
 }
 
 
diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc
index 599d375dca..cd7043090e 100644
--- a/src/libutil/hash.cc
+++ b/src/libutil/hash.cc
@@ -22,6 +22,7 @@ Hash::Hash(HashType type)
     else if (type == htSHA1) hashSize = sha1HashSize;
     else if (type == htSHA256) hashSize = sha256HashSize;
     else throw Error("unknown hash type");
+    assert(hashSize <= maxHashSize);
     memset(hash, 0, hashSize);
 }
 
diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh
index d82cd87a21..4490d2ff7a 100644
--- a/src/libutil/hash.hh
+++ b/src/libutil/hash.hh
@@ -18,7 +18,7 @@ const int sha256HashSize = 32;
 
 struct Hash
 {
-    static const unsigned int maxHashSize = 20;
+    static const unsigned int maxHashSize = 32;
     unsigned int hashSize;
     unsigned char hash[maxHashSize];
 
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 5321b294ab..fc65dcfc3b 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -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
        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(
         makeBind(toATerm("system"),