treewide: Rename Base to HashFormat
Co-authored-by: Yueh-Shun Li <shamrocklee@posteo.net> `base` is ambiguous, since it's not about the digital bases, but about the format of hashes. Base16, Base32 and Base64 are all character maps for binary encoding. Documentation of the format is also added. Cherry-pick of: https://github.com/NixOS/nix/pull/7708/commits/838c70f62116328ce01cb41a01886e4f1b9a727f https://github.com/NixOS/nix/pull/7708/commits/5043e6cf4ea537dfe599470797c5b310ab0e94b9 Change-Id: Ief5425f3c2056a4cca75838091e4dfa5cca88872
This commit is contained in:
@@ -69,7 +69,7 @@ static std::string makeLockFilename(const std::string & storeUri) {
|
||||
// This avoids issues with the escaped URI being very long and causing
|
||||
// path too long errors, while also avoiding any possibility of collision
|
||||
// caused by simple truncation.
|
||||
auto hash = hashString(HashType::SHA256, storeUri).to_string(Base::Base32, false);
|
||||
auto hash = hashString(HashType::SHA256, storeUri).to_string(HashFormat::Base32, false);
|
||||
return escapeUri(storeUri).substr(0, 48) + "-" + hash.substr(0, 16);
|
||||
}
|
||||
|
||||
|
||||
@@ -467,7 +467,7 @@ opQuery(std::shared_ptr<Store> store, AsyncIoRoot & aio, Strings opFlags, String
|
||||
auto info = aio.blockOn(store->queryPathInfo(j));
|
||||
if (query == qHash) {
|
||||
assert(info->narHash.type == HashType::SHA256);
|
||||
cout << fmt("%s\n", info->narHash.to_string(Base::Base32, true));
|
||||
cout << fmt("%s\n", info->narHash.to_string(HashFormat::Base32, true));
|
||||
} else if (query == qSize)
|
||||
cout << fmt("%d\n", info->narSize);
|
||||
}
|
||||
@@ -856,10 +856,12 @@ opVerifyPath(std::shared_ptr<Store> store, AsyncIoRoot & aio, Strings opFlags, S
|
||||
aio.blockOn(aio.blockOn(store->narFromPath(path))->drainInto(sink));
|
||||
auto current = sink.finish();
|
||||
if (current.first != info->narHash) {
|
||||
printError("path '%s' was modified! expected hash '%s', got '%s'",
|
||||
printError(
|
||||
"path '%s' was modified! expected hash '%s', got '%s'",
|
||||
store->printStorePath(path),
|
||||
info->narHash.to_string(Base::SRI, true),
|
||||
current.first.to_string(Base::SRI, true));
|
||||
info->narHash.to_string(HashFormat::SRI, true),
|
||||
current.first.to_string(HashFormat::SRI, true)
|
||||
);
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ struct AttrDb
|
||||
Path cacheDir = getCacheDir() + "/nix/eval-cache-v5";
|
||||
createDirs(cacheDir);
|
||||
|
||||
Path dbPath = cacheDir + "/" + fingerprint.to_string(Base::Base16, false) + ".sqlite";
|
||||
Path dbPath = cacheDir + "/" + fingerprint.to_string(HashFormat::Base16, false) + ".sqlite";
|
||||
|
||||
state->db = SQLite(dbPath);
|
||||
state->db.isCache();
|
||||
|
||||
@@ -1494,7 +1494,7 @@ static void prim_hashFile(EvalState & state, Value * * args, Value & v)
|
||||
|
||||
auto path = realisePath(state, *args[1]);
|
||||
|
||||
v.mkString(hashString(*ht, path.readFile()).to_string(Base::Base16, false));
|
||||
v.mkString(hashString(*ht, path.readFile()).to_string(HashFormat::Base16, false));
|
||||
}
|
||||
|
||||
static std::string_view fileTypeToString(InputAccessor::Type type)
|
||||
@@ -2776,7 +2776,7 @@ static void prim_hashString(EvalState & state, Value * * args, Value & v)
|
||||
NixStringContext context; // discarded
|
||||
auto s = state.forceString(*args[1], context, noPos, "while evaluating the second argument passed to builtins.hashString");
|
||||
|
||||
v.mkString(hashString(*ht, s).to_string(Base::Base16, false));
|
||||
v.mkString(hashString(*ht, s).to_string(HashFormat::Base16, false));
|
||||
}
|
||||
|
||||
struct RegexCache
|
||||
|
||||
@@ -32,7 +32,7 @@ void emitTreeAttrs(
|
||||
|
||||
auto narHash = input.getNarHash();
|
||||
assert(narHash);
|
||||
attrs.alloc("narHash").mkString(narHash->to_string(Base::SRI, true));
|
||||
attrs.alloc("narHash").mkString(narHash->to_string(HashFormat::SRI, true));
|
||||
|
||||
if (input.getType() == "git")
|
||||
attrs.alloc("submodules").mkBool(
|
||||
@@ -314,13 +314,15 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
|
||||
? state.aio.blockOn(state.ctx.store->queryPathInfo(storePath))->narHash
|
||||
: hashFile(HashType::SHA256, state.ctx.store->toRealPath(storePath));
|
||||
if (hash != *expectedHash) {
|
||||
state.ctx.errors.make<EvalError>(
|
||||
"hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s",
|
||||
*url,
|
||||
expectedHash->to_string(Base::SRI, true),
|
||||
hash.to_string(Base::SRI, true)
|
||||
).withExitStatus(102)
|
||||
.debugThrow();
|
||||
state.ctx.errors
|
||||
.make<EvalError>(
|
||||
"hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s",
|
||||
*url,
|
||||
expectedHash->to_string(HashFormat::SRI, true),
|
||||
hash.to_string(HashFormat::SRI, true)
|
||||
)
|
||||
.withExitStatus(102)
|
||||
.debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -178,12 +178,18 @@ try {
|
||||
};
|
||||
|
||||
auto narHash = TRY_AWAIT(store->queryPathInfo(tree.storePath))->narHash;
|
||||
input.attrs.insert_or_assign("narHash", narHash.to_string(Base::SRI, true));
|
||||
input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true));
|
||||
|
||||
if (auto prevNarHash = getNarHash()) {
|
||||
if (narHash != *prevNarHash)
|
||||
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'",
|
||||
to_string(), tree.actualPath, prevNarHash->to_string(Base::SRI, true), narHash.to_string(Base::SRI, true));
|
||||
throw Error(
|
||||
(unsigned int) 102,
|
||||
"NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'",
|
||||
to_string(),
|
||||
tree.actualPath,
|
||||
prevNarHash->to_string(HashFormat::SRI, true),
|
||||
narHash.to_string(HashFormat::SRI, true)
|
||||
);
|
||||
}
|
||||
|
||||
if (auto prevLastModified = getLastModified()) {
|
||||
|
||||
@@ -58,8 +58,8 @@ bool touchCacheFile(const Path & path, time_t touch_time)
|
||||
|
||||
Path getCachePath(std::string_view key)
|
||||
{
|
||||
return getCacheDir() + "/nix/gitv3/" +
|
||||
hashString(HashType::SHA256, key).to_string(Base::Base32, false);
|
||||
return getCacheDir() + "/nix/gitv3/"
|
||||
+ hashString(HashType::SHA256, key).to_string(HashFormat::Base32, false);
|
||||
}
|
||||
|
||||
// Returns the name of the HEAD branch.
|
||||
@@ -577,7 +577,10 @@ struct GitInputScheme : InputScheme
|
||||
auto checkHashType = [&](const std::optional<Hash> & hash)
|
||||
{
|
||||
if (hash.has_value() && !(hash->type == HashType::SHA1 || hash->type == HashType::SHA256))
|
||||
throw Error("Hash '%s' is not supported by Git. Supported types are sha1 and sha256.", hash->to_string(Base::Base16, true));
|
||||
throw Error(
|
||||
"Hash '%s' is not supported by Git. Supported types are sha1 and sha256.",
|
||||
hash->to_string(HashFormat::Base16, true)
|
||||
);
|
||||
};
|
||||
|
||||
auto getLockedAttrs = [&]()
|
||||
|
||||
@@ -152,7 +152,9 @@ struct GitArchiveInputScheme : InputScheme
|
||||
auto path = owner + "/" + repo;
|
||||
assert(!(ref && rev));
|
||||
if (ref) path += "/" + *ref;
|
||||
if (rev) path += "/" + rev->to_string(Base::Base16, false);
|
||||
if (rev) {
|
||||
path += "/" + rev->to_string(HashFormat::Base16, false);
|
||||
}
|
||||
return ParsedURL {
|
||||
.scheme = schemeType(),
|
||||
.path = path,
|
||||
@@ -304,8 +306,12 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
||||
? "https://%s/%s/%s/archive/%s.tar.gz"
|
||||
: "https://api.%s/repos/%s/%s/tarball/%s";
|
||||
|
||||
const auto url = fmt(urlFmt, host, getOwner(input), getRepo(input),
|
||||
input.getRev()->to_string(Base::Base16, false));
|
||||
const auto url =
|
||||
fmt(urlFmt,
|
||||
host,
|
||||
getOwner(input),
|
||||
getRepo(input),
|
||||
input.getRev()->to_string(HashFormat::Base16, false));
|
||||
|
||||
return DownloadUrl { url, headers };
|
||||
}
|
||||
@@ -388,9 +394,12 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
||||
// is 10 reqs/sec/ip-addr. See
|
||||
// https://docs.gitlab.com/ee/user/gitlab_com/index.html#gitlabcom-specific-rate-limits
|
||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
||||
auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/archive.tar.gz?sha=%s",
|
||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
||||
input.getRev()->to_string(Base::Base16, false));
|
||||
auto url =
|
||||
fmt("https://%s/api/v4/projects/%s%%2F%s/repository/archive.tar.gz?sha=%s",
|
||||
host,
|
||||
getStrAttr(input.attrs, "owner"),
|
||||
getStrAttr(input.attrs, "repo"),
|
||||
input.getRev()->to_string(HashFormat::Base16, false));
|
||||
|
||||
Headers headers = makeHeadersWithAuthTokens(host);
|
||||
return DownloadUrl { url, headers };
|
||||
@@ -487,9 +496,12 @@ struct SourceHutInputScheme : GitArchiveInputScheme
|
||||
DownloadUrl getDownloadUrl(const Input & input) const override
|
||||
{
|
||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
||||
auto url = fmt("https://%s/%s/%s/archive/%s.tar.gz",
|
||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
||||
input.getRev()->to_string(Base::Base16, false));
|
||||
auto url =
|
||||
fmt("https://%s/%s/%s/archive/%s.tar.gz",
|
||||
host,
|
||||
getStrAttr(input.attrs, "owner"),
|
||||
getStrAttr(input.attrs, "repo"),
|
||||
input.getRev()->to_string(HashFormat::Base16, false));
|
||||
|
||||
Headers headers = makeHeadersWithAuthTokens(host);
|
||||
return DownloadUrl { url, headers };
|
||||
|
||||
@@ -250,7 +250,10 @@ struct MercurialInputScheme : InputScheme
|
||||
auto checkHashType = [&](const std::optional<Hash> & hash)
|
||||
{
|
||||
if (hash.has_value() && hash->type != HashType::SHA1)
|
||||
throw Error("Hash '%s' is not supported by Mercurial. Only sha1 is supported.", hash->to_string(Base::Base16, true));
|
||||
throw Error(
|
||||
"Hash '%s' is not supported by Mercurial. Only sha1 is supported.",
|
||||
hash->to_string(HashFormat::Base16, true)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -296,7 +299,10 @@ struct MercurialInputScheme : InputScheme
|
||||
}
|
||||
}
|
||||
|
||||
Path cacheDir = fmt("%s/nix/hg/%s", getCacheDir(), hashString(HashType::SHA256, actualUrl).to_string(Base::Base32, false));
|
||||
Path cacheDir =
|
||||
fmt("%s/nix/hg/%s",
|
||||
getCacheDir(),
|
||||
hashString(HashType::SHA256, actualUrl).to_string(HashFormat::Base32, false));
|
||||
|
||||
/* If this is a commit hash that we already have, we don't
|
||||
have to pull again. */
|
||||
|
||||
@@ -293,7 +293,7 @@ struct CurlInputScheme : InputScheme
|
||||
// NAR hashes are preferred over file hashes since tar/zip
|
||||
// files don't have a canonical representation.
|
||||
if (auto narHash = input.getNarHash())
|
||||
url.query.insert_or_assign("narHash", narHash->to_string(Base::SRI, true));
|
||||
url.query.insert_or_assign("narHash", narHash->to_string(HashFormat::SRI, true));
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,14 +164,14 @@ try {
|
||||
auto [fileHash, fileSize] = fileHashSink.finish();
|
||||
narInfo->fileHash = fileHash;
|
||||
narInfo->fileSize = fileSize;
|
||||
narInfo->url = "nar/" + narInfo->fileHash->to_string(Base::Base32, false) + ".nar"
|
||||
+ (config().compression == "xz" ? ".xz" :
|
||||
config().compression == "bzip2" ? ".bz2" :
|
||||
config().compression == "zstd" ? ".zst" :
|
||||
config().compression == "lzip" ? ".lzip" :
|
||||
config().compression == "lz4" ? ".lz4" :
|
||||
config().compression == "br" ? ".br" :
|
||||
"");
|
||||
narInfo->url = "nar/" + narInfo->fileHash->to_string(HashFormat::Base32, false) + ".nar"
|
||||
+ (config().compression == "xz" ? ".xz"
|
||||
: config().compression == "bzip2" ? ".bz2"
|
||||
: config().compression == "zstd" ? ".zst"
|
||||
: config().compression == "lzip" ? ".lzip"
|
||||
: config().compression == "lz4" ? ".lz4"
|
||||
: config().compression == "br" ? ".br"
|
||||
: "");
|
||||
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
|
||||
printMsg(lvlTalkative, "copying path '%1%' (%2% bytes, compressed %3$.1f%% in %4% ms) to binary cache",
|
||||
|
||||
@@ -897,7 +897,7 @@ void LocalDerivationGoal::initTmpDir() {
|
||||
env[i.first] = i.second;
|
||||
} else {
|
||||
auto hash = hashString(HashType::SHA256, i.first);
|
||||
std::string fn = ".attr-" + hash.to_string(Base::Base32, false);
|
||||
std::string fn = ".attr-" + hash.to_string(HashFormat::Base32, false);
|
||||
Path p = tmpDir + "/" + fn;
|
||||
/* TODO(jade): we should have BorrowedFD instead of OwnedFD. */
|
||||
AutoCloseFD passAsFileFd{sys::openat(
|
||||
@@ -2105,8 +2105,8 @@ try {
|
||||
"specified: %s\n got: %s\n expected path: %s\n got path: %s",
|
||||
worker.store.printStorePath(drvPath),
|
||||
guessedUrl,
|
||||
wanted.to_string(Base::SRI, true),
|
||||
got.to_string(Base::SRI, true),
|
||||
wanted.to_string(HashFormat::SRI, true),
|
||||
got.to_string(HashFormat::SRI, true),
|
||||
worker.store.printStorePath(dof.path(worker.store, drv->name, outputName)),
|
||||
worker.store.printStorePath(newInfo0.path)
|
||||
));
|
||||
|
||||
@@ -72,8 +72,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData,
|
||||
Hash h = newHashAllowEmpty(getAttr("outputHash"), ht);
|
||||
fetch(
|
||||
aio,
|
||||
hashedMirror + printHashType(h.type) + "/"
|
||||
+ h.to_string(Base::Base16, false)
|
||||
hashedMirror + printHashType(h.type) + "/" + h.to_string(HashFormat::Base16, false)
|
||||
);
|
||||
return;
|
||||
} catch (Error & e) {
|
||||
|
||||
@@ -53,16 +53,16 @@ std::string ContentAddressMethod::render(HashType ht) const
|
||||
|
||||
std::string ContentAddress::render() const
|
||||
{
|
||||
return std::visit(overloaded {
|
||||
[](const TextIngestionMethod &) -> std::string {
|
||||
return "text:";
|
||||
},
|
||||
[](const FileIngestionMethod & method) {
|
||||
return "fixed:"
|
||||
+ makeFileIngestionPrefix(method);
|
||||
},
|
||||
}, method.raw)
|
||||
+ this->hash.to_string(Base::Base32, true);
|
||||
return std::visit(
|
||||
overloaded{
|
||||
[](const TextIngestionMethod &) -> std::string { return "text:"; },
|
||||
[](const FileIngestionMethod & method) {
|
||||
return "fixed:" + makeFileIngestionPrefix(method);
|
||||
},
|
||||
},
|
||||
method.raw
|
||||
)
|
||||
+ this->hash.to_string(HashFormat::Base32, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+18
-13
@@ -431,7 +431,8 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
|
||||
[&](const DerivationOutput::CAFixed & dof) {
|
||||
s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(dof.path(store, name, i.first)));
|
||||
s += ','; printUnquotedString(s, dof.ca.printMethodAlgo());
|
||||
s += ','; printUnquotedString(s, dof.ca.hash.to_string(Base::Base16, false));
|
||||
s += ',';
|
||||
printUnquotedString(s, dof.ca.hash.to_string(HashFormat::Base16, false));
|
||||
},
|
||||
}, i.second.raw);
|
||||
s += ')';
|
||||
@@ -590,10 +591,12 @@ try {
|
||||
std::map<std::string, Hash> outputHashes;
|
||||
for (const auto & i : drv.outputs) {
|
||||
auto & dof = std::get<DerivationOutput::CAFixed>(i.second.raw);
|
||||
auto hash = hashString(HashType::SHA256, "fixed:out:"
|
||||
+ dof.ca.printMethodAlgo() + ":"
|
||||
+ dof.ca.hash.to_string(Base::Base16, false) + ":"
|
||||
+ store.printStorePath(dof.path(store, drv.name, i.first)));
|
||||
auto hash = hashString(
|
||||
HashType::SHA256,
|
||||
"fixed:out:" + dof.ca.printMethodAlgo() + ":"
|
||||
+ dof.ca.hash.to_string(HashFormat::Base16, false) + ":"
|
||||
+ store.printStorePath(dof.path(store, drv.name, i.first))
|
||||
);
|
||||
outputHashes.insert_or_assign(i.first, std::move(hash));
|
||||
}
|
||||
co_return DrvHash {
|
||||
@@ -608,7 +611,7 @@ try {
|
||||
const auto h = get(res.hashes, outputName);
|
||||
if (!h)
|
||||
throw Error("no hash for output '%s' of derivation '%s'", outputName, drv.name);
|
||||
inputs2[h->to_string(Base::Base16, false)].insert(outputName);
|
||||
inputs2[h->to_string(HashFormat::Base16, false)].insert(outputName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,16 +714,16 @@ WireFormatGenerator serializeDerivation(const Store & store, const BasicDerivati
|
||||
co_yield i.first;
|
||||
auto [path, algo, hash] = std::visit(
|
||||
overloaded{
|
||||
[&](const DerivationOutput::InputAddressed & doi
|
||||
) -> std::tuple<std::string, std::string, std::string> {
|
||||
[&](const DerivationOutput::InputAddressed & doi)
|
||||
-> std::tuple<std::string, std::string, std::string> {
|
||||
return {store.printStorePath(doi.path), "", ""};
|
||||
},
|
||||
[&](const DerivationOutput::CAFixed & dof
|
||||
) -> std::tuple<std::string, std::string, std::string> {
|
||||
[&](const DerivationOutput::CAFixed & dof)
|
||||
-> std::tuple<std::string, std::string, std::string> {
|
||||
return {
|
||||
store.printStorePath(dof.path(store, drv.name, i.first)),
|
||||
dof.ca.printMethodAlgo(),
|
||||
dof.ca.hash.to_string(Base::Base16, false)
|
||||
dof.ca.hash.to_string(HashFormat::Base16, false)
|
||||
};
|
||||
},
|
||||
},
|
||||
@@ -750,7 +753,9 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr
|
||||
std::string hashPlaceholder(const OutputNameView outputName)
|
||||
{
|
||||
// FIXME: memoize?
|
||||
return "/" + hashString(HashType::SHA256, concatStrings("nix-output:", outputName)).to_string(Base::Base32, false);
|
||||
return "/"
|
||||
+ hashString(HashType::SHA256, concatStrings("nix-output:", outputName))
|
||||
.to_string(HashFormat::Base32, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -833,7 +838,7 @@ JSON DerivationOutput::toJSON(
|
||||
[&](const DerivationOutput::CAFixed & dof) {
|
||||
res["path"] = store.printStorePath(dof.path(store, drvName, outputName));
|
||||
res["hashAlgo"] = dof.ca.printMethodAlgo();
|
||||
res["hash"] = dof.ca.hash.to_string(Base::Base16, false);
|
||||
res["hash"] = dof.ca.hash.to_string(HashFormat::Base16, false);
|
||||
// FIXME print refs?
|
||||
},
|
||||
}, raw);
|
||||
|
||||
@@ -39,8 +39,12 @@ try {
|
||||
Don't complain if the stored hash is zero (unknown). */
|
||||
Hash hash = hashSink.currentHash().first;
|
||||
if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
|
||||
throw Error("hash of path '%s' has changed from '%s' to '%s'!",
|
||||
printStorePath(path), info->narHash.to_string(Base::SRI, true), hash.to_string(Base::SRI, true));
|
||||
throw Error(
|
||||
"hash of path '%s' has changed from '%s' to '%s'!",
|
||||
printStorePath(path),
|
||||
info->narHash.to_string(HashFormat::SRI, true),
|
||||
hash.to_string(HashFormat::SRI, true)
|
||||
);
|
||||
|
||||
teeSink
|
||||
<< exportMagic
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ static void makeSymlink(const Path & link, const Path & target)
|
||||
|
||||
kj::Promise<Result<void>> LocalStore::addIndirectRoot(const Path & path)
|
||||
try {
|
||||
std::string hash = hashString(HashType::SHA1, path).to_string(Base::Base32, false);
|
||||
std::string hash = hashString(HashType::SHA1, path).to_string(HashFormat::Base32, false);
|
||||
Path realRoot = canonPath(fmt("%1%/%2%/auto/%3%", config().stateDir, gcRootsDir, hash));
|
||||
makeSymlink(realRoot, path);
|
||||
return {result::success()};
|
||||
|
||||
@@ -315,7 +315,7 @@ struct LegacySSHStore final : public Store
|
||||
ServeProto::Command::AddToStoreNar,
|
||||
printStorePath(info.path),
|
||||
(info.deriver ? printStorePath(*info.deriver) : ""),
|
||||
info.narHash.to_string(Base::Base16, false),
|
||||
info.narHash.to_string(HashFormat::Base16, false),
|
||||
ServeProto::write(*conn, info.references),
|
||||
info.registrationTime,
|
||||
info.narSize,
|
||||
|
||||
+17
-10
@@ -655,7 +655,7 @@ try {
|
||||
|
||||
state.stmts->RegisterValidPath.use()
|
||||
(printStorePath(info.path))
|
||||
(info.narHash.to_string(Base::Base16, true))
|
||||
(info.narHash.to_string(HashFormat::Base16, true))
|
||||
(info.registrationTime == 0 ? time(0) : info.registrationTime)
|
||||
(info.deriver ? printStorePath(*info.deriver) : "", (bool) info.deriver)
|
||||
(info.narSize, info.narSize != 0)
|
||||
@@ -768,7 +768,7 @@ void LocalStore::updatePathInfo(DBState & state, const ValidPathInfo & info)
|
||||
{
|
||||
state.stmts->UpdatePathInfo.use()
|
||||
(info.narSize, info.narSize != 0)
|
||||
(info.narHash.to_string(Base::Base16, true))
|
||||
(info.narHash.to_string(HashFormat::Base16, true))
|
||||
(info.ultimate ? 1 : 0, info.ultimate)
|
||||
(concatStringsSep(" ", info.sigs), !info.sigs.empty())
|
||||
(renderContentAddress(info.ca), (bool) info.ca)
|
||||
@@ -1140,8 +1140,12 @@ try {
|
||||
auto hashResult = hashSink.finish();
|
||||
|
||||
if (hashResult.first != info.narHash)
|
||||
throw Error("hash mismatch importing path '%s';\n specified: %s\n got: %s",
|
||||
printStorePath(info.path), info.narHash.to_string(Base::SRI, true), hashResult.first.to_string(Base::SRI, true));
|
||||
throw Error(
|
||||
"hash mismatch importing path '%s';\n specified: %s\n got: %s",
|
||||
printStorePath(info.path),
|
||||
info.narHash.to_string(HashFormat::SRI, true),
|
||||
hashResult.first.to_string(HashFormat::SRI, true)
|
||||
);
|
||||
|
||||
if (hashResult.second != info.narSize)
|
||||
throw Error("size mismatch importing path '%s';\n specified: %s\n got: %s",
|
||||
@@ -1155,10 +1159,12 @@ try {
|
||||
info.path
|
||||
);
|
||||
if (specified.hash != actualHash.hash) {
|
||||
throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s",
|
||||
throw Error(
|
||||
"ca hash mismatch importing path '%s';\n specified: %s\n got: %s",
|
||||
printStorePath(info.path),
|
||||
specified.hash.to_string(Base::SRI, true),
|
||||
actualHash.hash.to_string(Base::SRI, true));
|
||||
specified.hash.to_string(HashFormat::SRI, true),
|
||||
actualHash.hash.to_string(HashFormat::SRI, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1505,7 +1511,8 @@ try {
|
||||
for (auto & link : readDirectory(linksDir)) {
|
||||
printMsg(lvlTalkative, "checking contents of '%s'", link.name);
|
||||
Path linkPath = linksDir + "/" + link.name;
|
||||
std::string hash = hashPath(HashType::SHA256, linkPath).first.to_string(Base::Base32, false);
|
||||
std::string hash =
|
||||
hashPath(HashType::SHA256, linkPath).first.to_string(HashFormat::Base32, false);
|
||||
if (hash != link.name) {
|
||||
printError("link '%s' was modified! expected hash '%s', got '%s'",
|
||||
linkPath, link.name, hash);
|
||||
@@ -1544,8 +1551,8 @@ try {
|
||||
printError(
|
||||
"path '%s' was modified! expected hash '%s', got '%s'",
|
||||
toRealPath(printStorePath(i)),
|
||||
info->narHash.to_string(Base::SRI, true),
|
||||
current.first.to_string(Base::SRI, true)
|
||||
info->narHash.to_string(HashFormat::SRI, true),
|
||||
current.first.to_string(HashFormat::SRI, true)
|
||||
);
|
||||
if (repair) TRY_AWAIT(repairPath(i)); else errors = true;
|
||||
} else {
|
||||
|
||||
@@ -288,9 +288,9 @@ public:
|
||||
(std::string(info->path.name()))
|
||||
(narInfo ? narInfo->url : "", narInfo != 0)
|
||||
(narInfo ? narInfo->compression : "", narInfo != 0)
|
||||
(narInfo && narInfo->fileHash ? narInfo->fileHash->to_string(Base::Base32, true) : "", narInfo && narInfo->fileHash)
|
||||
(narInfo && narInfo->fileHash ? narInfo->fileHash->to_string(HashFormat::Base32, true) : "", narInfo && narInfo->fileHash)
|
||||
(narInfo ? narInfo->fileSize : 0, narInfo != 0 && narInfo->fileSize)
|
||||
(info->narHash.to_string(Base::Base32, true))
|
||||
(info->narHash.to_string(HashFormat::Base32, true))
|
||||
(info->narSize)
|
||||
(concatStringsSep(" ", info->shortRefs()))
|
||||
(info->deriver ? std::string(info->deriver->to_string()) : "", (bool) info->deriver)
|
||||
|
||||
@@ -105,10 +105,10 @@ std::string NarInfo::to_string(const Store & store) const
|
||||
assert(compression != "");
|
||||
res += "Compression: " + compression + "\n";
|
||||
assert(fileHash && fileHash->type == HashType::SHA256);
|
||||
res += "FileHash: " + fileHash->to_string(Base::Base32, true) + "\n";
|
||||
res += "FileHash: " + fileHash->to_string(HashFormat::Base32, true) + "\n";
|
||||
res += "FileSize: " + std::to_string(fileSize) + "\n";
|
||||
assert(narHash.type == HashType::SHA256);
|
||||
res += "NarHash: " + narHash.to_string(Base::Base32, true) + "\n";
|
||||
res += "NarHash: " + narHash.to_string(HashFormat::Base32, true) + "\n";
|
||||
res += "NarSize: " + std::to_string(narSize) + "\n";
|
||||
|
||||
res += "References: " + concatStringsSep(" ", shortRefs()) + "\n";
|
||||
|
||||
@@ -156,10 +156,10 @@ std::optional<struct ::stat> LocalStore::optimisePath_(
|
||||
contents of the symlink (i.e. the result of readlink()), not
|
||||
the contents of the target (which may not even exist). */
|
||||
Hash hash = hashPath(HashType::SHA256, path).first;
|
||||
debug("'%1%' has hash '%2%'", path, hash.to_string(Base::Base32, true));
|
||||
debug("'%1%' has hash '%2%'", path, hash.to_string(HashFormat::Base32, true));
|
||||
|
||||
/* Check if this is a known hash. */
|
||||
Path linkPath = linksDir + "/" + hash.to_string(Base::Base32, false);
|
||||
Path linkPath = linksDir + "/" + hash.to_string(HashFormat::Base32, false);
|
||||
auto stLinkOpt = maybeLstat(linkPath);
|
||||
|
||||
/* Maybe delete the link, if it has been corrupted. */
|
||||
|
||||
@@ -28,11 +28,8 @@ std::string ValidPathInfo::fingerprint(const Store & store) const
|
||||
if (narSize == 0)
|
||||
throw Error("cannot calculate fingerprint of path '%s' because its size is not known",
|
||||
store.printStorePath(path));
|
||||
return
|
||||
"1;" + store.printStorePath(path) + ";"
|
||||
+ narHash.to_string(Base::Base32, true) + ";"
|
||||
+ std::to_string(narSize) + ";"
|
||||
+ concatStringsSep(",", store.printStorePathSet(references));
|
||||
return "1;" + store.printStorePath(path) + ";" + narHash.to_string(HashFormat::Base32, true) + ";"
|
||||
+ std::to_string(narSize) + ";" + concatStringsSep(",", store.printStorePathSet(references));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ StorePath::StorePath(std::string_view _baseName)
|
||||
}
|
||||
|
||||
StorePath::StorePath(const Hash & hash, std::string_view _name)
|
||||
: baseName((hash.to_string(Base::Base32, false) + "-").append(std::string(_name)))
|
||||
: baseName((hash.to_string(HashFormat::Base32, false) + "-").append(std::string(_name)))
|
||||
{
|
||||
assert(hash.base32Len() == HASH_PART_LEN);
|
||||
checkName(baseName, name());
|
||||
|
||||
@@ -39,7 +39,9 @@ struct DrvOutput {
|
||||
std::string to_string() const;
|
||||
|
||||
std::string strHash() const
|
||||
{ return drvHash.to_string(Base::Base16, true); }
|
||||
{
|
||||
return drvHash.to_string(HashFormat::Base16, true);
|
||||
}
|
||||
|
||||
static DrvOutput parse(const std::string &);
|
||||
|
||||
|
||||
@@ -421,7 +421,7 @@ try {
|
||||
WorkerProto::Op::AddToStoreNar,
|
||||
printStorePath(info.path),
|
||||
(info.deriver ? printStorePath(*info.deriver) : ""),
|
||||
info.narHash.to_string(Base::Base16, false),
|
||||
info.narHash.to_string(HashFormat::Base16, false),
|
||||
WorkerProto::write(*conn, info.references),
|
||||
info.registrationTime,
|
||||
info.narSize,
|
||||
|
||||
@@ -87,7 +87,7 @@ WireFormatGenerator ServeProto::Serialise<UnkeyedValidPathInfo>::write(WriteConn
|
||||
co_yield info.narSize; // downloadSize, lie a little
|
||||
co_yield info.narSize;
|
||||
if (GET_PROTOCOL_MINOR(conn.version) >= 4) {
|
||||
co_yield info.narHash.to_string(Base::Base32, true);
|
||||
co_yield info.narHash.to_string(HashFormat::Base32, true);
|
||||
co_yield renderContentAddress(info.ca);
|
||||
co_yield info.sigs;
|
||||
}
|
||||
|
||||
+20
-14
@@ -178,7 +178,7 @@ StorePath Store::makeStorePath(std::string_view type,
|
||||
StorePath Store::makeStorePath(std::string_view type,
|
||||
const Hash & hash, std::string_view name) const
|
||||
{
|
||||
return makeStorePath(type, hash.to_string(Base::Base16, true), name);
|
||||
return makeStorePath(type, hash.to_string(HashFormat::Base16, true), name);
|
||||
}
|
||||
|
||||
|
||||
@@ -215,12 +215,15 @@ StorePath Store::makeFixedOutputPath(std::string_view name, const FixedOutputInf
|
||||
throw Error("fixed output derivation '%s' is not allowed to refer to other store paths.\nYou may need to use the 'unsafeDiscardReferences' derivation attribute, see the manual for more details.",
|
||||
name);
|
||||
}
|
||||
return makeStorePath("output:out",
|
||||
hashString(HashType::SHA256,
|
||||
"fixed:out:"
|
||||
+ makeFileIngestionPrefix(info.method)
|
||||
+ info.hash.to_string(Base::Base16, true) + ":"),
|
||||
name);
|
||||
return makeStorePath(
|
||||
"output:out",
|
||||
hashString(
|
||||
HashType::SHA256,
|
||||
"fixed:out:" + makeFileIngestionPrefix(info.method)
|
||||
+ info.hash.to_string(HashFormat::Base16, true) + ":"
|
||||
),
|
||||
name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,7 +804,7 @@ try {
|
||||
auto info = TRY_AWAIT(queryPathInfo(i));
|
||||
|
||||
if (showHash) {
|
||||
s += info->narHash.to_string(Base::Base16, false) + "\n";
|
||||
s += info->narHash.to_string(HashFormat::Base16, false) + "\n";
|
||||
s += fmt("%1%\n", info->narSize);
|
||||
}
|
||||
|
||||
@@ -852,10 +855,13 @@ try {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
kj::Promise<Result<JSON>> Store::pathInfoToJSON(const StorePathSet & storePaths,
|
||||
bool includeImpureInfo, bool showClosureSize,
|
||||
Base hashBase,
|
||||
AllowInvalidFlag allowInvalid)
|
||||
kj::Promise<Result<JSON>> Store::pathInfoToJSON(
|
||||
const StorePathSet & storePaths,
|
||||
bool includeImpureInfo,
|
||||
bool showClosureSize,
|
||||
HashFormat hashFormat,
|
||||
AllowInvalidFlag allowInvalid
|
||||
)
|
||||
try {
|
||||
JSON::array_t jsonList = JSON::array();
|
||||
|
||||
@@ -867,7 +873,7 @@ try {
|
||||
|
||||
jsonPath["path"] = printStorePath(info->path);
|
||||
jsonPath["valid"] = true;
|
||||
jsonPath["narHash"] = info->narHash.to_string(hashBase, true);
|
||||
jsonPath["narHash"] = info->narHash.to_string(hashFormat, true);
|
||||
jsonPath["narSize"] = info->narSize;
|
||||
|
||||
{
|
||||
@@ -909,7 +915,7 @@ try {
|
||||
if (!narInfo->url.empty())
|
||||
jsonPath["url"] = narInfo->url;
|
||||
if (narInfo->fileHash)
|
||||
jsonPath["downloadHash"] = narInfo->fileHash->to_string(hashBase, true);
|
||||
jsonPath["downloadHash"] = narInfo->fileHash->to_string(hashFormat, true);
|
||||
if (narInfo->fileSize)
|
||||
jsonPath["downloadSize"] = narInfo->fileSize;
|
||||
if (showClosureSize)
|
||||
|
||||
@@ -714,10 +714,13 @@ public:
|
||||
* @param showClosureSize If true, the closure size of each path is
|
||||
* included.
|
||||
*/
|
||||
kj::Promise<Result<JSON>> pathInfoToJSON(const StorePathSet & storePaths,
|
||||
bool includeImpureInfo, bool showClosureSize,
|
||||
Base hashBase = Base::Base32,
|
||||
AllowInvalidFlag allowInvalid = DisallowInvalid);
|
||||
kj::Promise<Result<JSON>> pathInfoToJSON(
|
||||
const StorePathSet & storePaths,
|
||||
bool includeImpureInfo,
|
||||
bool showClosureSize,
|
||||
HashFormat hashFormat = HashFormat::Base32,
|
||||
AllowInvalidFlag allowInvalid = DisallowInvalid
|
||||
);
|
||||
|
||||
/**
|
||||
* @return the size of the closure of the specified path, that is,
|
||||
|
||||
@@ -145,7 +145,7 @@ UnkeyedValidPathInfo WorkerProto::Serialise<UnkeyedValidPathInfo>::read(ReadConn
|
||||
WireFormatGenerator WorkerProto::Serialise<UnkeyedValidPathInfo>::write(WriteConn conn, const UnkeyedValidPathInfo & pathInfo)
|
||||
{
|
||||
co_yield (pathInfo.deriver ? conn.store.printStorePath(*pathInfo.deriver) : "");
|
||||
co_yield pathInfo.narHash.to_string(Base::Base16, false);
|
||||
co_yield pathInfo.narHash.to_string(HashFormat::Base16, false);
|
||||
co_yield WorkerProto::write(conn, pathInfo.references);
|
||||
co_yield pathInfo.registrationTime;
|
||||
co_yield pathInfo.narSize;
|
||||
|
||||
+10
-11
@@ -82,26 +82,25 @@ static std::string printHash16(const Hash & hash)
|
||||
|
||||
std::string printHash16or32(const Hash & hash)
|
||||
{
|
||||
return hash.to_string(hash.type == HashType::MD5 ? Base::Base16 : Base::Base32, false);
|
||||
return hash.to_string(hash.type == HashType::MD5 ? HashFormat::Base16 : HashFormat::Base32, false);
|
||||
}
|
||||
|
||||
|
||||
std::string Hash::to_string(Base base, bool includeType) const
|
||||
std::string Hash::to_string(HashFormat format, bool includeType) const
|
||||
{
|
||||
std::string s;
|
||||
if (base == Base::SRI || includeType) {
|
||||
if (format == HashFormat::SRI || includeType) {
|
||||
s += printHashType(type);
|
||||
s += base == Base::SRI ? '-' : ':';
|
||||
s += format == HashFormat::SRI ? '-' : ':';
|
||||
}
|
||||
switch (base) {
|
||||
case Base::Base16:
|
||||
switch (format) {
|
||||
case HashFormat::Base16:
|
||||
s += printHash16(*this);
|
||||
break;
|
||||
case Base::Base32:
|
||||
case HashFormat::Base32:
|
||||
s += base32EncodeStr(std::string_view(charptr_cast<const char *>(hash), hashSize));
|
||||
break;
|
||||
case Base::Base64:
|
||||
case Base::SRI:
|
||||
case HashFormat::Base64:
|
||||
case HashFormat::SRI:
|
||||
s += base64Encode(std::string_view(charptr_cast<const char *>(hash), hashSize));
|
||||
break;
|
||||
}
|
||||
@@ -219,7 +218,7 @@ Hash newHashAllowEmpty(std::string_view hashStr, std::optional<HashType> ht)
|
||||
if (!ht)
|
||||
throw BadHash("empty hash requires explicit hash type");
|
||||
Hash h(*ht);
|
||||
printTaggedWarning("found empty hash, assuming '%s'", h.to_string(Base::SRI, true));
|
||||
printTaggedWarning("found empty hash, assuming '%s'", h.to_string(HashFormat::SRI, true));
|
||||
return h;
|
||||
} else
|
||||
return Hash::parseAny(hashStr, ht);
|
||||
|
||||
+18
-5
@@ -32,8 +32,21 @@ const int sha512HashSize = 64;
|
||||
|
||||
extern std::set<std::string> hashTypes;
|
||||
|
||||
enum class Base : int { Base64, Base32, Base16, SRI };
|
||||
|
||||
/**
|
||||
* @brief Enumeration representing the hash formats.
|
||||
*/
|
||||
enum class HashFormat : int {
|
||||
/// @brief Base 64 encoding.
|
||||
/// @see [IETF RFC 4648, section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4).
|
||||
Base64,
|
||||
/// @brief Nix-specific base-32 encoding. @see base32Chars
|
||||
Base32,
|
||||
/// @brief Lowercase hexadecimal encoding. @see base16Chars
|
||||
Base16,
|
||||
/// @brief "<hash algo>:<Base 64 hash>", format of the SRI integrity attribute.
|
||||
/// @see W3C recommendation [Subresource Intergrity](https://www.w3.org/TR/SRI/).
|
||||
SRI
|
||||
};
|
||||
|
||||
struct Hash
|
||||
{
|
||||
@@ -123,16 +136,16 @@ public:
|
||||
* or base-64. By default, this is prefixed by the hash type
|
||||
* (e.g. "sha256:").
|
||||
*/
|
||||
std::string to_string(Base base, bool includeType) const;
|
||||
std::string to_string(HashFormat format, bool includeType) const;
|
||||
|
||||
std::string gitRev() const
|
||||
{
|
||||
return to_string(Base::Base16, false);
|
||||
return to_string(HashFormat::Base16, false);
|
||||
}
|
||||
|
||||
std::string gitShortRev() const
|
||||
{
|
||||
return std::string(to_string(Base::Base16, false), 0, 7);
|
||||
return std::string(to_string(HashFormat::Base16, false), 0, 7);
|
||||
}
|
||||
|
||||
static Hash dummy;
|
||||
|
||||
+8
-6
@@ -238,7 +238,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
|
||||
j["url"] = flake.lockedRef.to_string(); // FIXME: rename to lockedUrl
|
||||
j["locked"] = fetchers::attrsToJSON(flake.lockedRef.toAttrs());
|
||||
if (auto rev = flake.lockedRef.input.getRev())
|
||||
j["revision"] = rev->to_string(Base::Base16, false);
|
||||
j["revision"] = rev->to_string(HashFormat::Base16, false);
|
||||
if (auto dirtyRev = fetchers::maybeGetStrAttr(flake.lockedRef.toAttrs(), "dirtyRev"))
|
||||
j["dirtyRevision"] = *dirtyRev;
|
||||
if (auto revCount = flake.lockedRef.input.getRevCount())
|
||||
@@ -264,8 +264,8 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
|
||||
store->printStorePath(flake.sourceInfo->storePath));
|
||||
if (auto rev = flake.lockedRef.input.getRev())
|
||||
logger->cout(
|
||||
ANSI_BOLD "Revision:" ANSI_NORMAL " %s",
|
||||
rev->to_string(Base::Base16, false));
|
||||
ANSI_BOLD "Revision:" ANSI_NORMAL " %s", rev->to_string(HashFormat::Base16, false)
|
||||
);
|
||||
if (auto dirtyRev = fetchers::maybeGetStrAttr(flake.lockedRef.toAttrs(), "dirtyRev"))
|
||||
logger->cout(
|
||||
ANSI_BOLD "Revision:" ANSI_NORMAL " %s",
|
||||
@@ -1532,13 +1532,15 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON
|
||||
if (json) {
|
||||
auto res = JSON::object();
|
||||
res["storePath"] = store->printStorePath(tree.storePath);
|
||||
res["hash"] = hash.to_string(Base::SRI, true);
|
||||
res["hash"] = hash.to_string(HashFormat::SRI, true);
|
||||
logger->cout(res.dump());
|
||||
} else {
|
||||
notice("Downloaded '%s' to '%s' (hash '%s').",
|
||||
notice(
|
||||
"Downloaded '%s' to '%s' (hash '%s').",
|
||||
lockedRef.to_string(),
|
||||
store->printStorePath(tree.storePath),
|
||||
hash.to_string(Base::SRI, true));
|
||||
hash.to_string(HashFormat::SRI, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+62
-59
@@ -9,39 +9,39 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct CmdHashBase : Command
|
||||
struct CmdHashFormat : Command
|
||||
{
|
||||
FileIngestionMethod mode;
|
||||
Base base = Base::SRI;
|
||||
HashFormat format = HashFormat::SRI;
|
||||
bool truncate = false;
|
||||
HashType ht = HashType::SHA256;
|
||||
std::vector<std::string> paths;
|
||||
std::optional<std::string> modulus;
|
||||
|
||||
CmdHashBase(FileIngestionMethod mode) : mode(mode)
|
||||
CmdHashFormat(FileIngestionMethod mode) : mode(mode)
|
||||
{
|
||||
addFlag({
|
||||
.longName = "sri",
|
||||
.description = "Print the hash in SRI format.",
|
||||
.handler = {&base, Base::SRI},
|
||||
.handler = {&format, HashFormat::SRI},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "base64",
|
||||
.description = "Print the hash in base-64 format.",
|
||||
.handler = {&base, Base::Base64},
|
||||
.handler = {&format, HashFormat::Base64},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "base32",
|
||||
.description = "Print the hash in base-32 (Nix-specific) format.",
|
||||
.handler = {&base, Base::Base32},
|
||||
.handler = {&format, HashFormat::Base32},
|
||||
});
|
||||
|
||||
addFlag({
|
||||
.longName = "base16",
|
||||
.description = "Print the hash in base-16 format.",
|
||||
.handler = {&base, Base::Base16},
|
||||
.handler = {&format, HashFormat::Base16},
|
||||
});
|
||||
|
||||
addFlag(Flag::mkHashTypeFlag("type", &ht));
|
||||
@@ -91,18 +91,18 @@ struct CmdHashBase : Command
|
||||
? computeHashModulo(ht, *modulus, source).first
|
||||
: hashSource(ht, source).first;
|
||||
if (truncate && h.hashSize > 20) h = compressHash(h, 20);
|
||||
logger->cout(h.to_string(base, base == Base::SRI));
|
||||
logger->cout(h.to_string(format, format == HashFormat::SRI));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct CmdToBase : Command
|
||||
struct CmdToHashFormat : Command
|
||||
{
|
||||
Base base;
|
||||
HashFormat format;
|
||||
std::optional<HashType> ht;
|
||||
std::vector<std::string> args;
|
||||
|
||||
CmdToBase(Base base) : base(base)
|
||||
CmdToHashFormat(HashFormat format) : format(format)
|
||||
{
|
||||
addFlag(Flag::mkHashTypeOptFlag("type", &ht));
|
||||
expectArgs("strings", &args);
|
||||
@@ -110,17 +110,19 @@ struct CmdToBase : Command
|
||||
|
||||
std::string description() override
|
||||
{
|
||||
return fmt("convert a hash to %s representation",
|
||||
base == Base::Base16 ? "base-16" :
|
||||
base == Base::Base32 ? "base-32" :
|
||||
base == Base::Base64 ? "base-64" :
|
||||
"SRI");
|
||||
return fmt(
|
||||
"convert a hash to %s representation",
|
||||
format == HashFormat::Base16 ? "base-16"
|
||||
: format == HashFormat::Base32 ? "base-32"
|
||||
: format == HashFormat::Base64 ? "base-64"
|
||||
: "SRI"
|
||||
);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
for (auto s : args)
|
||||
logger->cout(Hash::parseAny(s, ht).to_string(base, base == Base::SRI));
|
||||
logger->cout(Hash::parseAny(s, ht).to_string(format, format == HashFormat::SRI));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,23 +130,23 @@ struct CmdHash : MultiCommand
|
||||
{
|
||||
CmdHash()
|
||||
: MultiCommand({
|
||||
{"file",
|
||||
[](auto & aio) {
|
||||
return make_ref<MixAio<CmdHashBase>>(aio, FileIngestionMethod::Flat);
|
||||
;
|
||||
}},
|
||||
{"path",
|
||||
[](auto & aio) {
|
||||
return make_ref<MixAio<CmdHashBase>>(aio, FileIngestionMethod::Recursive);
|
||||
}},
|
||||
{"to-base16",
|
||||
[](auto & aio) { return make_ref<MixAio<CmdToBase>>(aio, Base::Base16); }},
|
||||
{"to-base32",
|
||||
[](auto & aio) { return make_ref<MixAio<CmdToBase>>(aio, Base::Base32); }},
|
||||
{"to-base64",
|
||||
[](auto & aio) { return make_ref<MixAio<CmdToBase>>(aio, Base::Base64); }},
|
||||
{"to-sri", [](auto & aio) { return make_ref<MixAio<CmdToBase>>(aio, Base::SRI); }},
|
||||
})
|
||||
{"file",
|
||||
[](auto & aio) {
|
||||
return make_ref<MixAio<CmdHashFormat>>(aio, FileIngestionMethod::Flat);
|
||||
;
|
||||
}},
|
||||
{"path",
|
||||
[](auto & aio) {
|
||||
return make_ref<MixAio<CmdHashFormat>>(aio, FileIngestionMethod::Recursive);
|
||||
}},
|
||||
{"to-base16",
|
||||
[](auto & aio) { return make_ref<MixAio<CmdToHashFormat>>(aio, HashFormat::Base16); }},
|
||||
{"to-base32",
|
||||
[](auto & aio) { return make_ref<MixAio<CmdToHashFormat>>(aio, HashFormat::Base32); }},
|
||||
{"to-base64",
|
||||
[](auto & aio) { return make_ref<MixAio<CmdToHashFormat>>(aio, HashFormat::Base64); }},
|
||||
{"to-sri", [](auto & aio) { return make_ref<MixAio<CmdToHashFormat>>(aio, HashFormat::SRI); }},
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
@@ -173,7 +175,7 @@ static int compatNixHash(AsyncIoRoot & aio, std::string programName, Strings arg
|
||||
{
|
||||
std::optional<HashType> ht;
|
||||
bool flat = false;
|
||||
Base base = Base::Base16;
|
||||
HashFormat format = HashFormat::Base16;
|
||||
bool truncate = false;
|
||||
enum { opHash, opTo } op = opHash;
|
||||
std::vector<std::string> ss;
|
||||
@@ -184,50 +186,51 @@ static int compatNixHash(AsyncIoRoot & aio, std::string programName, Strings arg
|
||||
else if (*arg == "--version")
|
||||
printVersion("nix-hash");
|
||||
else if (*arg == "--flat") flat = true;
|
||||
else if (*arg == "--base16") base = Base::Base16;
|
||||
else if (*arg == "--base32") base = Base::Base32;
|
||||
else if (*arg == "--base64") base = Base::Base64;
|
||||
else if (*arg == "--sri") base = Base::SRI;
|
||||
else if (*arg == "--truncate") truncate = true;
|
||||
else if (*arg == "--type") {
|
||||
else if (*arg == "--base16") {
|
||||
format = HashFormat::Base16;
|
||||
} else if (*arg == "--base32") {
|
||||
format = HashFormat::Base32;
|
||||
} else if (*arg == "--base64") {
|
||||
format = HashFormat::Base64;
|
||||
} else if (*arg == "--sri") {
|
||||
format = HashFormat::SRI;
|
||||
} else if (*arg == "--truncate") {
|
||||
truncate = true;
|
||||
} else if (*arg == "--type") {
|
||||
std::string s = getArg(*arg, arg, end);
|
||||
ht = parseHashType(s);
|
||||
}
|
||||
else if (*arg == "--to-base16") {
|
||||
} else if (*arg == "--to-base16") {
|
||||
op = opTo;
|
||||
base = Base::Base16;
|
||||
}
|
||||
else if (*arg == "--to-base32") {
|
||||
format = HashFormat::Base16;
|
||||
} else if (*arg == "--to-base32") {
|
||||
op = opTo;
|
||||
base = Base::Base32;
|
||||
}
|
||||
else if (*arg == "--to-base64") {
|
||||
format = HashFormat::Base32;
|
||||
} else if (*arg == "--to-base64") {
|
||||
op = opTo;
|
||||
base = Base::Base64;
|
||||
}
|
||||
else if (*arg == "--to-sri") {
|
||||
format = HashFormat::Base64;
|
||||
} else if (*arg == "--to-sri") {
|
||||
op = opTo;
|
||||
base = Base::SRI;
|
||||
}
|
||||
else if (*arg != "" && arg->at(0) == '-')
|
||||
format = HashFormat::SRI;
|
||||
} else if (*arg != "" && arg->at(0) == '-') {
|
||||
return false;
|
||||
else
|
||||
} else {
|
||||
ss.push_back(*arg);
|
||||
}
|
||||
return true;
|
||||
}).parseCmdline(argv);
|
||||
|
||||
if (op == opHash) {
|
||||
MixAio<CmdHashBase> cmd(aio, flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive);
|
||||
MixAio<CmdHashFormat> cmd(aio, flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive);
|
||||
if (!ht.has_value()) ht = HashType::MD5;
|
||||
cmd.ht = ht.value();
|
||||
cmd.base = base;
|
||||
cmd.format = format;
|
||||
cmd.truncate = truncate;
|
||||
cmd.paths = ss;
|
||||
cmd.run();
|
||||
}
|
||||
|
||||
else {
|
||||
MixAio<CmdToBase> cmd(aio, base);
|
||||
MixAio<CmdToHashFormat> cmd(aio, format);
|
||||
cmd.args = ss;
|
||||
if (ht.has_value()) cmd.ht = ht;
|
||||
cmd.run();
|
||||
|
||||
+10
-4
@@ -91,10 +91,16 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
|
||||
pathLen = std::max(pathLen, store->printStorePath(storePath).size());
|
||||
|
||||
if (json) {
|
||||
std::cout << aio().blockOn(store->pathInfoToJSON(
|
||||
// FIXME: preserve order?
|
||||
StorePathSet(storePaths.begin(), storePaths.end()),
|
||||
true, showClosureSize, Base::SRI, AllowInvalid)).dump();
|
||||
std::cout << aio()
|
||||
.blockOn(store->pathInfoToJSON(
|
||||
// FIXME: preserve order?
|
||||
StorePathSet(storePaths.begin(), storePaths.end()),
|
||||
true,
|
||||
showClosureSize,
|
||||
HashFormat::SRI,
|
||||
AllowInvalid
|
||||
))
|
||||
.dump();
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
+5
-3
@@ -341,13 +341,15 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
|
||||
if (json) {
|
||||
auto res = JSON::object();
|
||||
res["storePath"] = store->printStorePath(storePath);
|
||||
res["hash"] = hash.to_string(Base::SRI, true);
|
||||
res["hash"] = hash.to_string(HashFormat::SRI, true);
|
||||
logger->cout(res.dump());
|
||||
} else {
|
||||
notice("Downloaded '%s' to '%s' (hash '%s').",
|
||||
notice(
|
||||
"Downloaded '%s' to '%s' (hash '%s').",
|
||||
url,
|
||||
store->printStorePath(storePath),
|
||||
hash.to_string(Base::SRI, true));
|
||||
hash.to_string(HashFormat::SRI, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+5
-3
@@ -114,10 +114,12 @@ struct CmdVerify : StorePathsCommand
|
||||
ACTIVITY_RESULT_SYNC(
|
||||
aio, act2, resCorruptedPath, store->printStorePath(info->path)
|
||||
);
|
||||
printError("path '%s' was modified! expected hash '%s', got '%s'",
|
||||
printError(
|
||||
"path '%s' was modified! expected hash '%s', got '%s'",
|
||||
store->printStorePath(info->path),
|
||||
info->narHash.to_string(Base::SRI, true),
|
||||
hash.first.to_string(Base::SRI, true));
|
||||
info->narHash.to_string(HashFormat::SRI, true),
|
||||
hash.first.to_string(HashFormat::SRI, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ SV * queryReferences(char * path)
|
||||
SV * queryPathHash(char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
auto s = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)))->narHash.to_string(Base::Base32, true);
|
||||
auto s = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)))->narHash.to_string(HashFormat::Base32, true);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
@@ -118,7 +118,7 @@ SV * queryPathInfo(char * path, int base32)
|
||||
XPUSHs(&PL_sv_undef);
|
||||
else
|
||||
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0)));
|
||||
auto s = info->narHash.to_string(base32 ? Base::Base32 : Base::Base16, true);
|
||||
auto s = info->narHash.to_string(base32 ? HashFormat::Base32 : HashFormat::Base16, true);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
mXPUSHi(info->registrationTime);
|
||||
mXPUSHi(info->narSize);
|
||||
@@ -210,7 +210,7 @@ SV * hashPath(char * algo, int base32, char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = hashPath(parseHashType(algo), path).first;
|
||||
auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
|
||||
auto s = h.to_string(base32 ? HashFormat::Base32 : HashFormat::Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
@@ -221,7 +221,7 @@ SV * hashFile(char * algo, int base32, char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = hashFile(parseHashType(algo), path);
|
||||
auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
|
||||
auto s = h.to_string(base32 ? HashFormat::Base32 : HashFormat::Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
@@ -232,7 +232,7 @@ SV * hashString(char * algo, int base32, char * s)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = hashString(parseHashType(algo), s);
|
||||
auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
|
||||
auto s = h.to_string(base32 ? HashFormat::Base32 : HashFormat::Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
@@ -243,7 +243,7 @@ SV * convertHash(char * algo, char * s, int toBase32)
|
||||
PPCODE:
|
||||
try {
|
||||
auto h = Hash::parseAny(s, parseHashType(algo));
|
||||
auto s = h.to_string(toBase32 ? Base::Base32 : Base::Base16, false);
|
||||
auto s = h.to_string(toBase32 ? HashFormat::Base32 : HashFormat::Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
|
||||
+24
-16
@@ -14,28 +14,28 @@ namespace nix {
|
||||
// values taken from: https://tools.ietf.org/html/rfc1321
|
||||
auto s1 = "";
|
||||
auto hash = hashString(HashType::MD5, s1);
|
||||
ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e");
|
||||
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e");
|
||||
}
|
||||
|
||||
TEST(hashString, testKnownMD5Hashes2) {
|
||||
// values taken from: https://tools.ietf.org/html/rfc1321
|
||||
auto s2 = "abc";
|
||||
auto hash = hashString(HashType::MD5, s2);
|
||||
ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72");
|
||||
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72");
|
||||
}
|
||||
|
||||
TEST(hashString, testKnownSHA1Hashes1) {
|
||||
// values taken from: https://tools.ietf.org/html/rfc3174
|
||||
auto s = "abc";
|
||||
auto hash = hashString(HashType::SHA1, s);
|
||||
ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
|
||||
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
|
||||
}
|
||||
|
||||
TEST(hashString, testKnownSHA1Hashes2) {
|
||||
// values taken from: https://tools.ietf.org/html/rfc3174
|
||||
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
||||
auto hash = hashString(HashType::SHA1, s);
|
||||
ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
|
||||
ASSERT_EQ(hash.to_string(HashFormat::Base16, true), "sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
|
||||
}
|
||||
|
||||
TEST(hashString, testKnownSHA256Hashes1) {
|
||||
@@ -43,35 +43,43 @@ namespace nix {
|
||||
auto s = "abc";
|
||||
|
||||
auto hash = hashString(HashType::SHA256, s);
|
||||
ASSERT_EQ(hash.to_string(Base::Base16, true),
|
||||
"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
|
||||
ASSERT_EQ(
|
||||
hash.to_string(HashFormat::Base16, true),
|
||||
"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(hashString, testKnownSHA256Hashes2) {
|
||||
// values taken from: https://tools.ietf.org/html/rfc4634
|
||||
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
||||
auto hash = hashString(HashType::SHA256, s);
|
||||
ASSERT_EQ(hash.to_string(Base::Base16, true),
|
||||
"sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
|
||||
ASSERT_EQ(
|
||||
hash.to_string(HashFormat::Base16, true),
|
||||
"sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(hashString, testKnownSHA512Hashes1) {
|
||||
// values taken from: https://tools.ietf.org/html/rfc4634
|
||||
auto s = "abc";
|
||||
auto hash = hashString(HashType::SHA512, s);
|
||||
ASSERT_EQ(hash.to_string(Base::Base16, true),
|
||||
"sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9"
|
||||
"7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd"
|
||||
"454d4423643ce80e2a9ac94fa54ca49f");
|
||||
ASSERT_EQ(
|
||||
hash.to_string(HashFormat::Base16, true),
|
||||
"sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9"
|
||||
"7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd"
|
||||
"454d4423643ce80e2a9ac94fa54ca49f"
|
||||
);
|
||||
}
|
||||
TEST(hashString, testKnownSHA512Hashes2) {
|
||||
// values taken from: https://tools.ietf.org/html/rfc4634
|
||||
auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
|
||||
|
||||
auto hash = hashString(HashType::SHA512, s);
|
||||
ASSERT_EQ(hash.to_string(Base::Base16, true),
|
||||
"sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1"
|
||||
"7299aeadb6889018501d289e4900f7e4331b99dec4b5433a"
|
||||
"c7d329eeb6dd26545e96e55b874be909");
|
||||
ASSERT_EQ(
|
||||
hash.to_string(HashFormat::Base16, true),
|
||||
"sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1"
|
||||
"7299aeadb6889018501d289e4900f7e4331b99dec4b5433a"
|
||||
"c7d329eeb6dd26545e96e55b874be909"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user