Skip to content

Commit

Permalink
Simplify ContentAddress
Browse files Browse the repository at this point in the history
Whereas `ContentAddressWithReferences` is a sum type complex because different
varieties support different notions of reference, and
`ContentAddressMethod` is a nested enum to support that,
`ContentAddress` can be a simple pair of a method and hash.

`ContentAddress` does not need to be a sum type on the outside because
the choice of method doesn't effect what type of hashes we can use.

Co-Authored-By: Cale Gibbard <cgibbard@gmail.com>
  • Loading branch information
Ericson2314 and cgibbard committed Jul 7, 2023
1 parent 6db66eb commit 903700c
Show file tree
Hide file tree
Showing 20 changed files with 182 additions and 293 deletions.
6 changes: 2 additions & 4 deletions perl/lib/Nix/Store.xs
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,8 @@ SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
auto h = Hash::parseAny(hash, parseHashType(algo));
auto method = recursive ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;
auto path = store()->makeFixedOutputPath(name, FixedOutputInfo {
.hash = {
.method = method,
.hash = h,
},
.method = method,
.hash = h,
.references = {},
});
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(path).c_str(), 0)));
Expand Down
13 changes: 6 additions & 7 deletions src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1300,9 +1300,10 @@ drvName, Bindings * attrs, Value & v)
auto method = ingestionMethod.value_or(FileIngestionMethod::Flat);

DerivationOutput::CAFixed dof {
.ca = ContentAddress::fromParts(
std::move(method),
std::move(h)),
.ca = ContentAddress {
.method = std::move(method),
.hash = std::move(h),
},
};

drv.env["out"] = state.store->printStorePath(dof.path(*state.store, drvName, "out"));
Expand Down Expand Up @@ -2162,10 +2163,8 @@ static void addPath(
std::optional<StorePath> expectedStorePath;
if (expectedHash)
expectedStorePath = state.store->makeFixedOutputPath(name, FixedOutputInfo {
.hash = {
.method = method,
.hash = *expectedHash,
},
.method = method,
.hash = *expectedHash,
.references = {},
});

Expand Down
6 changes: 2 additions & 4 deletions src/libexpr/primops/fetchTree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,8 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
auto expectedPath = state.store->makeFixedOutputPath(
name,
FixedOutputInfo {
.hash = {
.method = unpack ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat,
.hash = *expectedHash,
},
.method = unpack ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat,
.hash = *expectedHash,
.references = {}
});

Expand Down
6 changes: 2 additions & 4 deletions src/libfetchers/fetchers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,8 @@ StorePath Input::computeStorePath(Store & store) const
if (!narHash)
throw Error("cannot compute store path for unlocked input '%s'", to_string());
return store.makeFixedOutputPath(getName(), FixedOutputInfo {
.hash = {
.method = FileIngestionMethod::Recursive,
.hash = *narHash,
},
.method = FileIngestionMethod::Recursive,
.hash = *narHash,
.references = {},
});
}
Expand Down
6 changes: 2 additions & 4 deletions src/libfetchers/tarball.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,8 @@ DownloadFileResult downloadFile(
*store,
name,
FixedOutputInfo {
.hash = {
.method = FileIngestionMethod::Flat,
.hash = hash,
},
.method = FileIngestionMethod::Flat,
.hash = hash,
.references = {},
},
hashString(htSHA256, sink.s),
Expand Down
16 changes: 6 additions & 10 deletions src/libstore/binary-cache-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,8 @@ StorePath BinaryCacheStore::addToStoreFromDump(Source & dump, std::string_view n
*this,
name,
FixedOutputInfo {
.hash = {
.method = method,
.hash = nar.first,
},
.method = method,
.hash = nar.first,
.references = {
.others = references,
// caller is not capable of creating a self-reference, because this is content-addressed without modulus
Expand Down Expand Up @@ -428,10 +426,8 @@ StorePath BinaryCacheStore::addToStore(
*this,
name,
FixedOutputInfo {
.hash = {
.method = method,
.hash = h,
},
.method = method,
.hash = h,
.references = {
.others = references,
// caller is not capable of creating a self-reference, because this is content-addressed without modulus
Expand Down Expand Up @@ -465,8 +461,8 @@ StorePath BinaryCacheStore::addTextToStore(
*this,
std::string { name },
TextInfo {
{ .hash = textHash },
references,
.hash = textHash,
.references = references,
},
nar.first,
};
Expand Down
6 changes: 3 additions & 3 deletions src/libstore/build/local-derivation-goal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2538,16 +2538,16 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
},

[&](const DerivationOutput::CAFixed & dof) {
auto wanted = dof.ca.getHash();
auto & wanted = dof.ca.hash;

auto newInfo0 = newInfoFromCA(DerivationOutput::CAFloating {
.method = dof.ca.getMethod(),
.method = dof.ca.method,
.hashType = wanted.type,
});

/* Check wanted hash */
assert(newInfo0.ca);
auto got = newInfo0.ca->getHash();
auto & got = newInfo0.ca->hash;
if (wanted != got) {
/* Throw an error after registering the path as
valid. */
Expand Down
125 changes: 33 additions & 92 deletions src/libstore/content-address.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@

namespace nix {

std::string FixedOutputHash::printMethodAlgo() const
{
return makeFileIngestionPrefix(method) + printHashType(hash.type);
}

std::string makeFileIngestionPrefix(FileIngestionMethod m)
{
switch (m) {
Expand Down Expand Up @@ -42,21 +37,6 @@ ContentAddressMethod ContentAddressMethod::parsePrefix(std::string_view & m)
return method;
}

std::string ContentAddress::render() const
{
return std::visit(overloaded {
[](const TextHash & th) {
return "text:"
+ th.hash.to_string(Base32, true);
},
[](const FixedOutputHash & fsh) {
return "fixed:"
+ makeFileIngestionPrefix(fsh.method)
+ fsh.hash.to_string(Base32, true);
}
}, raw);
}

std::string ContentAddressMethod::render(HashType ht) const
{
return std::visit(overloaded {
Expand All @@ -69,6 +49,20 @@ std::string ContentAddressMethod::render(HashType ht) const
}, raw);
}

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(Base32, true);
}

/**
* Parses content address strings up to the hash.
*/
Expand Down Expand Up @@ -118,22 +112,12 @@ ContentAddress ContentAddress::parse(std::string_view rawCa)
{
auto rest = rawCa;

auto [caMethod, hashType_] = parseContentAddressMethodPrefix(rest);
auto hashType = hashType_; // work around clang bug
auto [caMethod, hashType] = parseContentAddressMethodPrefix(rest);

return std::visit(overloaded {
[&](TextIngestionMethod &) {
return ContentAddress(TextHash {
.hash = Hash::parseNonSRIUnprefixed(rest, hashType)
});
},
[&](FileIngestionMethod & fim) {
return ContentAddress(FixedOutputHash {
.method = fim,
.hash = Hash::parseNonSRIUnprefixed(rest, hashType),
});
},
}, caMethod.raw);
return ContentAddress {
.method = std::move(caMethod).raw,
.hash = Hash::parseNonSRIUnprefixed(rest, hashType),
};
}

std::pair<ContentAddressMethod, HashType> ContentAddressMethod::parse(std::string_view caMethod)
Expand All @@ -156,52 +140,10 @@ std::string renderContentAddress(std::optional<ContentAddress> ca)
return ca ? ca->render() : "";
}

ContentAddress ContentAddress::fromParts(
ContentAddressMethod method, Hash hash) noexcept
{
return std::visit(overloaded {
[&](TextIngestionMethod _) -> ContentAddress {
return TextHash {
.hash = std::move(hash),
};
},
[&](FileIngestionMethod m2) -> ContentAddress {
return FixedOutputHash {
.method = std::move(m2),
.hash = std::move(hash),
};
},
}, method.raw);
}

ContentAddressMethod ContentAddress::getMethod() const
{
return std::visit(overloaded {
[](const TextHash & th) -> ContentAddressMethod {
return TextIngestionMethod {};
},
[](const FixedOutputHash & fsh) -> ContentAddressMethod {
return fsh.method;
},
}, raw);
}

const Hash & ContentAddress::getHash() const
{
return std::visit(overloaded {
[](const TextHash & th) -> auto & {
return th.hash;
},
[](const FixedOutputHash & fsh) -> auto & {
return fsh.hash;
},
}, raw);
}

std::string ContentAddress::printMethodAlgo() const
{
return getMethod().renderPrefix()
+ printHashType(getHash().type);
return method.renderPrefix()
+ printHashType(hash.type);
}

bool StoreReferences::empty() const
Expand All @@ -217,19 +159,20 @@ size_t StoreReferences::size() const
ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const ContentAddress & ca) noexcept
{
return std::visit(overloaded {
[&](const TextHash & h) -> ContentAddressWithReferences {
[&](const TextIngestionMethod &) -> ContentAddressWithReferences {
return TextInfo {
.hash = h,
.hash = ca.hash,
.references = {},
};
},
[&](const FixedOutputHash & h) -> ContentAddressWithReferences {
[&](const FileIngestionMethod & method) -> ContentAddressWithReferences {
return FixedOutputInfo {
.hash = h,
.method = method,
.hash = ca.hash,
.references = {},
};
},
}, ca.raw);
}, ca.method.raw);
}

std::optional<ContentAddressWithReferences> ContentAddressWithReferences::fromPartsOpt(
Expand All @@ -241,18 +184,16 @@ std::optional<ContentAddressWithReferences> ContentAddressWithReferences::fromPa
return std::nullopt;
return ContentAddressWithReferences {
TextInfo {
.hash = { .hash = std::move(hash) },
.hash = std::move(hash),
.references = std::move(refs.others),
}
};
},
[&](FileIngestionMethod m2) -> std::optional<ContentAddressWithReferences> {
return ContentAddressWithReferences {
FixedOutputInfo {
.hash = {
.method = m2,
.hash = std::move(hash),
},
.method = m2,
.hash = std::move(hash),
.references = std::move(refs),
}
};
Expand All @@ -267,7 +208,7 @@ ContentAddressMethod ContentAddressWithReferences::getMethod() const
return TextIngestionMethod {};
},
[](const FixedOutputInfo & fsh) -> ContentAddressMethod {
return fsh.hash.method;
return fsh.method;
},
}, raw);
}
Expand All @@ -276,10 +217,10 @@ Hash ContentAddressWithReferences::getHash() const
{
return std::visit(overloaded {
[](const TextInfo & th) {
return th.hash.hash;
return th.hash;
},
[](const FixedOutputInfo & fsh) {
return fsh.hash.hash;
return fsh.hash;
},
}, raw);
}
Expand Down
Loading

0 comments on commit 903700c

Please sign in to comment.