Permalink
Browse files

Support base-64 hashes

Also simplify the Hash API.

Fixes #1437.
  • Loading branch information...
edolstra committed Jul 4, 2017
1 parent fe97c69 commit c0015e87af70f539f24d2aa2bc224a9d8b84276b
@@ -81,8 +81,7 @@ SV * queryReferences(char * path)
SV * queryPathHash(char * path)
PPCODE:
try {
auto hash = store()->queryPathInfo(path)->narHash;
string s = "sha256:" + printHash32(hash);
auto s = store()->queryPathInfo(path)->narHash.to_string();
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -108,7 +107,7 @@ SV * queryPathInfo(char * path, int base32)
XPUSHs(&PL_sv_undef);
else
XPUSHs(sv_2mortal(newSVpv(info->deriver.c_str(), 0)));
string s = "sha256:" + (base32 ? printHash32(info->narHash) : printHash(info->narHash));
auto s = info->narHash.to_string(base32 ? Base32 : Base16);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
mXPUSHi(info->registrationTime);
mXPUSHi(info->narSize);
@@ -184,7 +183,7 @@ void importPaths(int fd, int dontCheckSigs)
PPCODE:
try {
FdSource source(fd);
store()->importPaths(source, 0, dontCheckSigs);
store()->importPaths(source, nullptr, dontCheckSigs ? NoCheckSigs : CheckSigs);
} catch (Error & e) {
croak("%s", e.what());
}
@@ -194,7 +193,7 @@ SV * hashPath(char * algo, int base32, char * path)
PPCODE:
try {
Hash h = hashPath(parseHashType(algo), path).first;
string s = base32 ? printHash32(h) : printHash(h);
auto s = h.to_string(base32 ? Base32 : Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -205,7 +204,7 @@ SV * hashFile(char * algo, int base32, char * path)
PPCODE:
try {
Hash h = hashFile(parseHashType(algo), path);
string s = base32 ? printHash32(h) : printHash(h);
auto s = h.to_string(base32 ? Base32 : Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -216,7 +215,7 @@ SV * hashString(char * algo, int base32, char * s)
PPCODE:
try {
Hash h = hashString(parseHashType(algo), s);
string s = base32 ? printHash32(h) : printHash(h);
auto s = h.to_string(base32 ? Base32 : Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -226,8 +225,8 @@ SV * hashString(char * algo, int base32, char * s)
SV * convertHash(char * algo, char * s, int toBase32)
PPCODE:
try {
Hash h = parseHash16or32(parseHashType(algo), s);
string s = toBase32 ? printHash32(h) : printHash(h);
Hash h(s, parseHashType(algo));
string s = h.to_string(toBase32 ? Base32 : Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -286,8 +285,7 @@ SV * addToStore(char * srcPath, int recursive, char * algo)
SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
PPCODE:
try {
HashType ht = parseHashType(algo);
Hash h = parseHash16or32(ht, hash);
Hash h(hash, parseHashType(algo));
Path path = store()->makeFixedOutputPath(recursive, h, name);
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
} catch (Error & e) {
@@ -708,8 +708,8 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
HashType ht = parseHashType(outputHashAlgo);
if (ht == htUnknown)
throw EvalError(format("unknown hash algorithm ‘%1%’, at %2%") % outputHashAlgo % posDrvName);
Hash h = parseHash16or32(ht, *outputHash);
outputHash = printHash(h);
Hash h(*outputHash, ht);
outputHash = h.to_string(Base16, false);
if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
Path outPath = state.store->makeFixedOutputPath(outputHashRecursive, h, drvName);
@@ -1701,7 +1701,7 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
PathSet context; // discarded
string s = state.forceString(*args[1], context, pos);
mkString(v, printHash(hashString(ht, s)), context);
mkString(v, hashString(ht, s).to_string(Base16, false), context);
}
@@ -1852,7 +1852,7 @@ void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
if (n == "url")
url = state.forceStringNoCtx(*attr.value, *attr.pos);
else if (n == "sha256")
expectedHash = parseHash16or32(htSHA256, state.forceStringNoCtx(*attr.value, *attr.pos));
expectedHash = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
else if (n == "name")
name = state.forceStringNoCtx(*attr.value, *attr.pos);
else
@@ -239,7 +239,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
% duration);
/* Atomically write the NAR file. */
narInfo->url = "nar/" + printHash32(narInfo->fileHash) + ".nar"
narInfo->url = "nar/" + narInfo->fileHash.to_string(Base32, false) + ".nar"
+ (compression == "xz" ? ".xz" :
compression == "bzip2" ? ".bz2" :
compression == "br" ? ".br" :
@@ -3236,7 +3236,7 @@ PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash)
Path DerivationGoal::addHashRewrite(const Path & path)
{
string h1 = string(path, worker.store.storeDir.size() + 1, 32);
string h2 = string(printHash32(hashString(htSHA256, "rewrite:" + drvPath + ":" + path)), 0, 32);
string h2 = string(hashString(htSHA256, "rewrite:" + drvPath + ":" + path).to_string(Base32, false), 0, 32);
Path p = worker.store.storeDir + "/" + h2 + string(path, worker.store.storeDir.size() + 33);
deletePath(p);
assert(path.size() == p.size());
@@ -23,7 +23,7 @@ void DerivationOutput::parseHashInfo(bool & recursive, Hash & hash) const
if (hashType == htUnknown)
throw Error(format("unknown hash algorithm ‘%1%’") % algo);
hash = parseHash(hashType, this->hash);
hash = Hash(this->hash, hashType);
}
@@ -354,7 +354,7 @@ Hash hashDerivationModulo(Store & store, Derivation drv)
h = hashDerivationModulo(store, drv2);
drvHashes[i.first] = h;
}
inputs2[printHash(h)] = i.second;
inputs2[h.to_string(Base16, false)] = i.second;
}
drv.inputDrvs = inputs2;
@@ -437,7 +437,7 @@ Sink & operator << (Sink & out, const BasicDerivation & drv)
std::string hashPlaceholder(const std::string & outputName)
{
// FIXME: memoize?
return "/" + printHash32(hashString(htSHA256, "nix-output:" + outputName));
return "/" + hashString(htSHA256, "nix-output:" + outputName).to_string(Base32, false);
}
@@ -581,7 +581,7 @@ Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpa
Path cacheDir = getCacheDir() + "/nix/tarballs";
createDirs(cacheDir);
string urlHash = printHash32(hashString(htSHA256, url));
string urlHash = hashString(htSHA256, url).to_string(Base32, false);
Path dataFile = cacheDir + "/" + urlHash + ".info";
Path fileLink = cacheDir + "/" + urlHash + "-file";
@@ -56,7 +56,7 @@ void Store::exportPath(const Path & path, Sink & sink)
Hash hash = hashAndWriteSink.currentHash();
if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
throw Error(format("hash of path ‘%1%’ has changed from ‘%2%’ to ‘%3%’!") % path
% printHash(info->narHash) % printHash(hash));
% info->narHash.to_string() % hash.to_string());
hashAndWriteSink << exportMagic << path << info->references << info->deriver << 0;
}
@@ -76,7 +76,7 @@ void LocalStore::syncWithGC()
void LocalStore::addIndirectRoot(const Path & path)
{
string hash = printHash32(hashString(htSHA1, path));
string hash = hashString(htSHA1, path).to_string(Base32, false);
Path realRoot = canonPath((format("%1%/%2%/auto/%3%")
% stateDir % gcRootsDir % hash).str());
makeSymlink(realRoot, path);
@@ -572,7 +572,7 @@ uint64_t LocalStore::addValidPath(State & state,
state.stmtRegisterValidPath.use()
(info.path)
("sha256:" + printHash(info.narHash))
(info.narHash.to_string(Base16))
(info.registrationTime == 0 ? time(0) : info.registrationTime)
(info.deriver, info.deriver != "")
(info.narSize, info.narSize != 0)
@@ -614,20 +614,6 @@ uint64_t LocalStore::addValidPath(State & state,
}
Hash parseHashField(const Path & path, const string & s)
{
string::size_type colon = s.find(':');
if (colon == string::npos)
throw Error(format("corrupt hash ‘%1%’ in valid-path entry for ‘%2%’")
% s % path);
HashType ht = parseHashType(string(s, 0, colon));
if (ht == htUnknown)
throw Error(format("unknown hash type ‘%1%’ in valid-path entry for ‘%2%’")
% string(s, 0, colon) % path);
return parseHash(ht, string(s, colon + 1));
}
void LocalStore::queryPathInfoUncached(const Path & path,
std::function<void(std::shared_ptr<ValidPathInfo>)> success,
std::function<void(std::exception_ptr exc)> failure)
@@ -650,7 +636,11 @@ void LocalStore::queryPathInfoUncached(const Path & path,
info->id = useQueryPathInfo.getInt(0);
info->narHash = parseHashField(path, useQueryPathInfo.getStr(1));
try {
info->narHash = Hash(useQueryPathInfo.getStr(1));
} catch (BadHash & e) {
throw Error("in valid-path entry for ‘%s’: %s", path, e.what());
}
info->registrationTime = useQueryPathInfo.getInt(2);
@@ -685,7 +675,7 @@ void LocalStore::updatePathInfo(State & state, const ValidPathInfo & info)
{
state.stmtUpdatePathInfo.use()
(info.narSize, info.narSize != 0)
("sha256:" + printHash(info.narHash))
(info.narHash.to_string(Base16))
(info.ultimate ? 1 : 0, info.ultimate)
(concatStringsSep(" ", info.sigs), !info.sigs.empty())
(info.ca, !info.ca.empty())
@@ -1211,7 +1201,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
if (info->narHash != nullHash && info->narHash != current.first) {
printError(format("path ‘%1%’ was modified! "
"expected hash ‘%2%’, got ‘%3%’")
% i % printHash(info->narHash) % printHash(current.first));
% i % info->narHash.to_string() % current.first.to_string());
if (repair) repairPath(i); else errors = true;
} else {
@@ -203,9 +203,9 @@ class NarInfoDiskCacheImpl : public NarInfoDiskCache
narInfo->url = queryNAR.getStr(3);
narInfo->compression = queryNAR.getStr(4);
if (!queryNAR.isNull(5))
narInfo->fileHash = parseHash(queryNAR.getStr(5));
narInfo->fileHash = Hash(queryNAR.getStr(5));
narInfo->fileSize = queryNAR.getInt(6);
narInfo->narHash = parseHash(queryNAR.getStr(7));
narInfo->narHash = Hash(queryNAR.getStr(7));
narInfo->narSize = queryNAR.getInt(8);
for (auto & r : tokenizeString<Strings>(queryNAR.getStr(9), " "))
narInfo->references.insert(cache.storeDir + "/" + r);
@@ -11,7 +11,7 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
auto parseHashField = [&](const string & s) {
try {
return parseHash(s);
return Hash(s);
} catch (BadHash &) {
corrupt();
return Hash(); // never reached
@@ -90,10 +90,10 @@ std::string NarInfo::to_string() const
assert(compression != "");
res += "Compression: " + compression + "\n";
assert(fileHash.type == htSHA256);
res += "FileHash: sha256:" + printHash32(fileHash) + "\n";
res += "FileHash: " + fileHash.to_string(Base32) + "\n";
res += "FileSize: " + std::to_string(fileSize) + "\n";
assert(narHash.type == htSHA256);
res += "NarHash: sha256:" + printHash32(narHash) + "\n";
res += "NarHash: " + narHash.to_string(Base32) + "\n";
res += "NarSize: " + std::to_string(narSize) + "\n";
res += "References: " + concatStringsSep(" ", shortRefs()) + "\n";
@@ -135,10 +135,10 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
contents of the symlink (i.e. the result of readlink()), not
the contents of the target (which may not even exist). */
Hash hash = hashPath(htSHA256, path).first;
debug(format("‘%1%’ has hash ‘%2%’") % path % printHash(hash));
debug(format("‘%1%’ has hash ‘%2%’") % path % hash.to_string());
/* Check if this is a known hash. */
Path linkPath = linksDir + "/" + printHash32(hash);
Path linkPath = linksDir + "/" + hash.to_string(Base32, false);
retry:
if (!pathExists(linkPath)) {
@@ -294,7 +294,7 @@ void RemoteStore::queryPathInfoUncached(const Path & path,
info->path = path;
info->deriver = readString(conn->from);
if (info->deriver != "") assertStorePath(info->deriver);
info->narHash = parseHash(htSHA256, readString(conn->from));
info->narHash = Hash(readString(conn->from), htSHA256);
info->references = readStorePaths<PathSet>(*this, conn->from);
conn->from >> info->registrationTime >> info->narSize;
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 16) {
@@ -387,7 +387,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, const ref<std::string>
else {
conn->to << wopAddToStoreNar
<< info.path << info.deriver << printHash(info.narHash)
<< info.path << info.deriver << info.narHash.to_string(Base16, false)
<< info.references << info.registrationTime << info.narSize
<< info.ultimate << info.sigs << info.ca
<< repair << !checkSigs;
@@ -176,13 +176,12 @@ Path Store::makeStorePath(const string & type,
const Hash & hash, const string & name) const
{
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
string s = type + ":sha256:" + printHash(hash) + ":"
+ storeDir + ":" + name;
string s = type + ":" + hash.to_string(Base16) + ":" + storeDir + ":" + name;
checkStoreName(name);
return storeDir + "/"
+ printHash32(compressHash(hashString(htSHA256, s), 20))
+ compressHash(hashString(htSHA256, s), 20).to_string(Base32, false)
+ "-" + name;
}
@@ -202,7 +201,7 @@ Path Store::makeFixedOutputPath(bool recursive,
? makeStorePath("source", hash, name)
: makeStorePath("output:out", hashString(htSHA256,
"fixed:out:" + (recursive ? (string) "r:" : "") +
printHashType(hash.type) + ":" + printHash(hash) + ":"),
hash.to_string(Base16) + ":"),
name);
}
@@ -438,7 +437,7 @@ string Store::makeValidityRegistration(const PathSet & paths,
auto info = queryPathInfo(i);
if (showHash) {
s += printHash(info->narHash) + "\n";
s += info->narHash.to_string(Base16, false) + "\n";
s += (format("%1%\n") % info->narSize).str();
}
@@ -613,7 +612,7 @@ ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven)
if (hashGiven) {
string s;
getline(str, s);
info.narHash = parseHash(htSHA256, s);
info.narHash = Hash(s, htSHA256);
getline(str, s);
if (!string2Int(s, info.narSize)) throw Error("number expected");
}
@@ -648,7 +647,7 @@ std::string ValidPathInfo::fingerprint() const
% path);
return
"1;" + path + ";"
+ printHashType(narHash.type) + ":" + printHash32(narHash) + ";"
+ narHash.to_string(Base32) + ";"
+ std::to_string(narSize) + ";"
+ concatStringsSep(",", references);
}
@@ -667,7 +666,7 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const
};
if (hasPrefix(ca, "text:")) {
auto hash = parseHash(std::string(ca, 5));
Hash hash(std::string(ca, 5));
if (store.makeTextPath(storePathToName(path), hash, references) == path)
return true;
else
@@ -676,7 +675,7 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const
else if (hasPrefix(ca, "fixed:")) {
bool recursive = ca.compare(6, 2, "r:") == 0;
auto hash = parseHash(std::string(ca, recursive ? 8 : 6));
Hash hash(std::string(ca, recursive ? 8 : 6));
if (store.makeFixedOutputPath(recursive, hash, storePathToName(path)) == path)
return true;
else
Oops, something went wrong.

0 comments on commit c0015e8

Please sign in to comment.