1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 08:31:16 +02:00

* Unify the treatment of sources copied to the store, and recursive

SHA-256 outputs of fixed-output derivations.  I.e. they now produce
  the same store path:

  $ nix-store --add x
  /nix/store/j2fq9qxvvxgqymvpszhs773ncci45xsj-x

  $ nix-store --add-fixed --recursive sha256 x
  /nix/store/j2fq9qxvvxgqymvpszhs773ncci45xsj-x

  the latter being the same as the path that a derivation

    derivation {
      name = "x";
      outputHashAlgo = "sha256";
      outputHashMode = "recursive";
      outputHash = "...";
      ...
    };

  produces.

  This does change the output path for such fixed-output derivations.
  Fortunately they are quite rare.  The most common use is fetchsvn
  calls with SHA-256 hashes.  (There are a handful of those is
  Nixpkgs, mostly unstable development packages.)
  
* Documented the computation of store paths (in store-api.cc).
This commit is contained in:
Eelco Dolstra 2008-12-03 15:06:30 +00:00
parent 09bc0c502c
commit 64519cfd65
12 changed files with 191 additions and 79 deletions

View file

@ -99,55 +99,112 @@ void checkStoreName(const string & name)
}
/* Store paths have the following form:
<store>/<h>-<name>
where
<store> = the location of the Nix store, usually /nix/store
<name> = a human readable name for the path, typically obtained
from the name attribute of the derivation, or the name of the
source file from which the store path is created
<h> = base-32 representation of the first 160 bits of a SHA-256
hash of <s>; the hash part of the store name
<s> = the string "<type>:sha256:<h2>:<store>:<name>";
note that it includes the location of the store as well as the
name to make sure that changes to either of those are reflected
in the hash (e.g. you won't get /nix/store/<h>-name1 and
/nix/store/<h>-name2 with equal hash parts).
<type> = one of:
"text:<r1>:<r2>:...<rN>"
for plain text files written to the store using
addTextToStore(); <r1> ... <rN> are the references of the
path.
"source"
for paths copied to the store using addToStore() when recursive
= true and hashAlgo = "sha256"
"output:out"
for either the outputs created by derivations, OR paths copied
to the store using addToStore() with recursive != true or
hashAlgo != "sha256" (in that case "source" is used; it's
silly, but it's done that way for compatibility).
<h2> = base-16 representation of a SHA-256 hash of:
if <type> = "text:...":
the string written to the resulting store path
if <type> = "source":
the serialisation of the path from which this store path is
copied, as returned by hashPath()
if <type> = "output:out":
for non-fixed derivation outputs:
the derivation (see hashDerivationModulo() in
primops.cc)
for paths copied by addToStore() or produced by fixed-output
derivations:
the string "fixed:out:<rec><algo>:<hash>:", where
<rec> = "r:" for recursive (path) hashes, or "" or flat
(file) hashes
<algo> = "md5", "sha1" or "sha256"
<hash> = base-16 representation of the path or flat hash of
the contents of the path (or expected contents of the
path for fixed-output derivations)
It would have been nicer to handle fixed-output derivations under
"source", e.g. have something like "source:<rec><algo>", but we're
stuck with this for now...
The main reason for this way of computing names is to prevent name
collisions (for security). For instance, it shouldn't be feasible
to come up with a derivation whose output path collides with the
path for a copied source. The former would have a <s> starting with
"output:out:", while the latter would have a <2> starting with
"source:".
*/
Path makeStorePath(const string & type,
const Hash & hash, const string & suffix)
const Hash & hash, const string & name)
{
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
string s = type + ":sha256:" + printHash(hash) + ":"
+ nixStore + ":" + suffix;
+ nixStore + ":" + name;
checkStoreName(suffix);
checkStoreName(name);
return nixStore + "/"
+ printHash32(compressHash(hashString(htSHA256, s), 20))
+ "-" + suffix;
+ "-" + name;
}
Path makeFixedOutputPath(bool recursive,
string hashAlgo, Hash hash, string name)
{
/* !!! copy/paste from primops.cc */
Hash h = hashString(htSHA256, "fixed:out:"
+ (recursive ? (string) "r:" : "") + hashAlgo + ":"
+ printHash(hash) + ":"
+ "");
return makeStorePath("output:out", h, name);
return hashAlgo == "sha256" && recursive
? makeStorePath("source", hash, name)
: makeStorePath("output:out", hashString(htSHA256,
"fixed:out:" + (recursive ? (string) "r:" : "") + hashAlgo + ":" + printHash(hash) + ":"),
name);
}
std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
bool fixed, bool recursive, string hashAlgo, PathFilter & filter)
bool recursive, string hashAlgo, PathFilter & filter)
{
Hash h = hashPath(htSHA256, srcPath, filter);
string baseName = baseNameOf(srcPath);
Path dstPath;
if (fixed) {
HashType ht(parseHashType(hashAlgo));
Hash h2 = recursive ? hashPath(ht, srcPath, filter) : hashFile(ht, srcPath);
dstPath = makeFixedOutputPath(recursive, hashAlgo, h2, baseName);
}
else dstPath = makeStorePath("source", h, baseName);
HashType ht(parseHashType(hashAlgo));
Hash h = recursive ? hashPath(ht, srcPath, filter) : hashFile(ht, srcPath);
string name = baseNameOf(srcPath);
Path dstPath = makeFixedOutputPath(recursive, hashAlgo, h, name);
return std::pair<Path, Hash>(dstPath, h);
}
Path computeStorePathForText(const string & suffix, const string & s,
Path computeStorePathForText(const string & name, const string & s,
const PathSet & references)
{
Hash hash = hashString(htSHA256, s);
@ -159,7 +216,7 @@ Path computeStorePathForText(const string & suffix, const string & s,
type += ":";
type += *i;
}
return makeStorePath(type, hash, suffix);
return makeStorePath(type, hash, name);
}