mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-22 05:56:15 +02:00
Cleanup ContentAddressMethod
to match docs
The old `std::variant` is bad because we aren't adding a new case to `FileIngestionMethod` so much as we are defining a separate concept --- store object content addressing rather than file system object content addressing. As such, it is more correct to just create a fresh enumeration. Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
This commit is contained in:
parent
64e599ebe1
commit
b51e161af5
25 changed files with 275 additions and 203 deletions
|
@ -2303,7 +2303,7 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat
|
||||||
path.resolveSymlinks(),
|
path.resolveSymlinks(),
|
||||||
settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy,
|
settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy,
|
||||||
path.baseName(),
|
path.baseName(),
|
||||||
FileIngestionMethod::NixArchive,
|
ContentAddressMethod::Raw::NixArchive,
|
||||||
nullptr,
|
nullptr,
|
||||||
repair);
|
repair);
|
||||||
allowPath(dstPath);
|
allowPath(dstPath);
|
||||||
|
|
|
@ -1209,7 +1209,7 @@ static void derivationStrictInternal(
|
||||||
auto handleHashMode = [&](const std::string_view s) {
|
auto handleHashMode = [&](const std::string_view s) {
|
||||||
if (s == "recursive") {
|
if (s == "recursive") {
|
||||||
// back compat, new name is "nar"
|
// back compat, new name is "nar"
|
||||||
ingestionMethod = FileIngestionMethod::NixArchive;
|
ingestionMethod = ContentAddressMethod::Raw::NixArchive;
|
||||||
} else try {
|
} else try {
|
||||||
ingestionMethod = ContentAddressMethod::parse(s);
|
ingestionMethod = ContentAddressMethod::parse(s);
|
||||||
} catch (UsageError &) {
|
} catch (UsageError &) {
|
||||||
|
@ -1217,9 +1217,9 @@ static void derivationStrictInternal(
|
||||||
"invalid value '%s' for 'outputHashMode' attribute", s
|
"invalid value '%s' for 'outputHashMode' attribute", s
|
||||||
).atPos(v).debugThrow();
|
).atPos(v).debugThrow();
|
||||||
}
|
}
|
||||||
if (ingestionMethod == TextIngestionMethod {})
|
if (ingestionMethod == ContentAddressMethod::Raw::Text)
|
||||||
experimentalFeatureSettings.require(Xp::DynamicDerivations);
|
experimentalFeatureSettings.require(Xp::DynamicDerivations);
|
||||||
if (ingestionMethod == FileIngestionMethod::Git)
|
if (ingestionMethod == ContentAddressMethod::Raw::Git)
|
||||||
experimentalFeatureSettings.require(Xp::GitHashing);
|
experimentalFeatureSettings.require(Xp::GitHashing);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1391,7 +1391,7 @@ static void derivationStrictInternal(
|
||||||
|
|
||||||
/* Check whether the derivation name is valid. */
|
/* Check whether the derivation name is valid. */
|
||||||
if (isDerivation(drvName) &&
|
if (isDerivation(drvName) &&
|
||||||
!(ingestionMethod == ContentAddressMethod { TextIngestionMethod { } } &&
|
!(ingestionMethod == ContentAddressMethod::Raw::Text &&
|
||||||
outputs.size() == 1 &&
|
outputs.size() == 1 &&
|
||||||
*(outputs.begin()) == "out"))
|
*(outputs.begin()) == "out"))
|
||||||
{
|
{
|
||||||
|
@ -1413,7 +1413,7 @@ static void derivationStrictInternal(
|
||||||
|
|
||||||
auto h = newHashAllowEmpty(*outputHash, outputHashAlgo);
|
auto h = newHashAllowEmpty(*outputHash, outputHashAlgo);
|
||||||
|
|
||||||
auto method = ingestionMethod.value_or(FileIngestionMethod::Flat);
|
auto method = ingestionMethod.value_or(ContentAddressMethod::Raw::Flat);
|
||||||
|
|
||||||
DerivationOutput::CAFixed dof {
|
DerivationOutput::CAFixed dof {
|
||||||
.ca = ContentAddress {
|
.ca = ContentAddress {
|
||||||
|
@ -1432,7 +1432,7 @@ static void derivationStrictInternal(
|
||||||
.atPos(v).debugThrow();
|
.atPos(v).debugThrow();
|
||||||
|
|
||||||
auto ha = outputHashAlgo.value_or(HashAlgorithm::SHA256);
|
auto ha = outputHashAlgo.value_or(HashAlgorithm::SHA256);
|
||||||
auto method = ingestionMethod.value_or(FileIngestionMethod::NixArchive);
|
auto method = ingestionMethod.value_or(ContentAddressMethod::Raw::NixArchive);
|
||||||
|
|
||||||
for (auto & i : outputs) {
|
for (auto & i : outputs) {
|
||||||
drv.env[i] = hashPlaceholder(i);
|
drv.env[i] = hashPlaceholder(i);
|
||||||
|
@ -2208,7 +2208,7 @@ static void prim_toFile(EvalState & state, const PosIdx pos, Value * * args, Val
|
||||||
})
|
})
|
||||||
: ({
|
: ({
|
||||||
StringSource s { contents };
|
StringSource s { contents };
|
||||||
state.store->addToStoreFromDump(s, name, FileSerialisationMethod::Flat, TextIngestionMethod {}, HashAlgorithm::SHA256, refs, state.repair);
|
state.store->addToStoreFromDump(s, name, FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, refs, state.repair);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Note: we don't need to add `context' to the context of the
|
/* Note: we don't need to add `context' to the context of the
|
||||||
|
@ -2391,7 +2391,7 @@ static void prim_filterSource(EvalState & state, const PosIdx pos, Value * * arg
|
||||||
"while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'");
|
"while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'");
|
||||||
state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.filterSource");
|
state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.filterSource");
|
||||||
|
|
||||||
addPath(state, pos, path.baseName(), path, args[0], FileIngestionMethod::NixArchive, std::nullopt, v, context);
|
addPath(state, pos, path.baseName(), path, args[0], ContentAddressMethod::Raw::NixArchive, std::nullopt, v, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_filterSource({
|
static RegisterPrimOp primop_filterSource({
|
||||||
|
@ -2454,7 +2454,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
|
||||||
std::optional<SourcePath> path;
|
std::optional<SourcePath> path;
|
||||||
std::string name;
|
std::string name;
|
||||||
Value * filterFun = nullptr;
|
Value * filterFun = nullptr;
|
||||||
ContentAddressMethod method = FileIngestionMethod::NixArchive;
|
auto method = ContentAddressMethod::Raw::NixArchive;
|
||||||
std::optional<Hash> expectedHash;
|
std::optional<Hash> expectedHash;
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
|
|
||||||
|
@ -2470,8 +2470,8 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
|
||||||
state.forceFunction(*(filterFun = attr.value), attr.pos, "while evaluating the `filter` parameter passed to builtins.path");
|
state.forceFunction(*(filterFun = attr.value), attr.pos, "while evaluating the `filter` parameter passed to builtins.path");
|
||||||
else if (n == "recursive")
|
else if (n == "recursive")
|
||||||
method = state.forceBool(*attr.value, attr.pos, "while evaluating the `recursive` attribute passed to builtins.path")
|
method = state.forceBool(*attr.value, attr.pos, "while evaluating the `recursive` attribute passed to builtins.path")
|
||||||
? FileIngestionMethod::NixArchive
|
? ContentAddressMethod::Raw::NixArchive
|
||||||
: FileIngestionMethod::Flat;
|
: ContentAddressMethod::Raw::Flat;
|
||||||
else if (n == "sha256")
|
else if (n == "sha256")
|
||||||
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `sha256` attribute passed to builtins.path"), HashAlgorithm::SHA256);
|
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `sha256` attribute passed to builtins.path"), HashAlgorithm::SHA256);
|
||||||
else
|
else
|
||||||
|
|
|
@ -18,7 +18,7 @@ StorePath fetchToStore(
|
||||||
const SourcePath & path,
|
const SourcePath & path,
|
||||||
FetchMode mode,
|
FetchMode mode,
|
||||||
std::string_view name = "source",
|
std::string_view name = "source",
|
||||||
ContentAddressMethod method = FileIngestionMethod::NixArchive,
|
ContentAddressMethod method = ContentAddressMethod::Raw::NixArchive,
|
||||||
PathFilter * filter = nullptr,
|
PathFilter * filter = nullptr,
|
||||||
RepairFlag repair = NoRepair);
|
RepairFlag repair = NoRepair);
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ struct MercurialInputScheme : InputScheme
|
||||||
auto storePath = store->addToStore(
|
auto storePath = store->addToStore(
|
||||||
input.getName(),
|
input.getName(),
|
||||||
{getFSSourceAccessor(), CanonPath(actualPath)},
|
{getFSSourceAccessor(), CanonPath(actualPath)},
|
||||||
FileIngestionMethod::NixArchive, HashAlgorithm::SHA256, {},
|
ContentAddressMethod::Raw::NixArchive, HashAlgorithm::SHA256, {},
|
||||||
filter);
|
filter);
|
||||||
|
|
||||||
return storePath;
|
return storePath;
|
||||||
|
|
|
@ -8,6 +8,7 @@ std::string_view makeFileIngestionPrefix(FileIngestionMethod m)
|
||||||
{
|
{
|
||||||
switch (m) {
|
switch (m) {
|
||||||
case FileIngestionMethod::Flat:
|
case FileIngestionMethod::Flat:
|
||||||
|
// Not prefixed for back compat
|
||||||
return "";
|
return "";
|
||||||
case FileIngestionMethod::NixArchive:
|
case FileIngestionMethod::NixArchive:
|
||||||
return "r:";
|
return "r:";
|
||||||
|
@ -15,91 +16,128 @@ std::string_view makeFileIngestionPrefix(FileIngestionMethod m)
|
||||||
experimentalFeatureSettings.require(Xp::GitHashing);
|
experimentalFeatureSettings.require(Xp::GitHashing);
|
||||||
return "git:";
|
return "git:";
|
||||||
default:
|
default:
|
||||||
throw Error("impossible, caught both cases");
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view ContentAddressMethod::render() const
|
std::string_view ContentAddressMethod::render() const
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
switch (raw) {
|
||||||
[](TextIngestionMethod) -> std::string_view { return "text"; },
|
case ContentAddressMethod::Raw::Text:
|
||||||
[](FileIngestionMethod m2) {
|
return "text";
|
||||||
/* Not prefixed for back compat with things that couldn't produce text before. */
|
case ContentAddressMethod::Raw::Flat:
|
||||||
return renderFileIngestionMethod(m2);
|
case ContentAddressMethod::Raw::NixArchive:
|
||||||
},
|
case ContentAddressMethod::Raw::Git:
|
||||||
}, raw);
|
return renderFileIngestionMethod(getFileIngestionMethod());
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Not surjective**
|
||||||
|
*
|
||||||
|
* This is not exposed because `FileIngestionMethod::Flat` maps to
|
||||||
|
* `ContentAddressMethod::Raw::Flat` and
|
||||||
|
* `ContentAddressMethod::Raw::Text` alike. We can thus only safely use
|
||||||
|
* this when the latter is ruled out (e.g. because it is already
|
||||||
|
* handled).
|
||||||
|
*/
|
||||||
|
static ContentAddressMethod fileIngestionMethodToContentAddressMethod(FileIngestionMethod m)
|
||||||
|
{
|
||||||
|
switch (m) {
|
||||||
|
case FileIngestionMethod::Flat:
|
||||||
|
return ContentAddressMethod::Raw::Flat;
|
||||||
|
case FileIngestionMethod::NixArchive:
|
||||||
|
return ContentAddressMethod::Raw::NixArchive;
|
||||||
|
case FileIngestionMethod::Git:
|
||||||
|
return ContentAddressMethod::Raw::Git;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentAddressMethod ContentAddressMethod::parse(std::string_view m)
|
ContentAddressMethod ContentAddressMethod::parse(std::string_view m)
|
||||||
{
|
{
|
||||||
if (m == "text")
|
if (m == "text")
|
||||||
return TextIngestionMethod {};
|
return ContentAddressMethod::Raw::Text;
|
||||||
else
|
else
|
||||||
return parseFileIngestionMethod(m);
|
return fileIngestionMethodToContentAddressMethod(
|
||||||
|
parseFileIngestionMethod(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view ContentAddressMethod::renderPrefix() const
|
std::string_view ContentAddressMethod::renderPrefix() const
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
switch (raw) {
|
||||||
[](TextIngestionMethod) -> std::string_view { return "text:"; },
|
case ContentAddressMethod::Raw::Text:
|
||||||
[](FileIngestionMethod m2) {
|
return "text:";
|
||||||
/* Not prefixed for back compat with things that couldn't produce text before. */
|
case ContentAddressMethod::Raw::Flat:
|
||||||
return makeFileIngestionPrefix(m2);
|
case ContentAddressMethod::Raw::NixArchive:
|
||||||
},
|
case ContentAddressMethod::Raw::Git:
|
||||||
}, raw);
|
return makeFileIngestionPrefix(getFileIngestionMethod());
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentAddressMethod ContentAddressMethod::parsePrefix(std::string_view & m)
|
ContentAddressMethod ContentAddressMethod::parsePrefix(std::string_view & m)
|
||||||
{
|
{
|
||||||
if (splitPrefix(m, "r:")) {
|
if (splitPrefix(m, "r:")) {
|
||||||
return FileIngestionMethod::NixArchive;
|
return ContentAddressMethod::Raw::NixArchive;
|
||||||
}
|
}
|
||||||
else if (splitPrefix(m, "git:")) {
|
else if (splitPrefix(m, "git:")) {
|
||||||
experimentalFeatureSettings.require(Xp::GitHashing);
|
experimentalFeatureSettings.require(Xp::GitHashing);
|
||||||
return FileIngestionMethod::Git;
|
return ContentAddressMethod::Raw::Git;
|
||||||
}
|
}
|
||||||
else if (splitPrefix(m, "text:")) {
|
else if (splitPrefix(m, "text:")) {
|
||||||
return TextIngestionMethod {};
|
return ContentAddressMethod::Raw::Text;
|
||||||
|
}
|
||||||
|
return ContentAddressMethod::Raw::Flat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is slightly more mindful of forward compat in that it uses `fixed:`
|
||||||
|
* rather than just doing a raw empty prefix or `r:`, which doesn't "save room"
|
||||||
|
* for future changes very well.
|
||||||
|
*/
|
||||||
|
static std::string renderPrefixModern(const ContentAddressMethod & ca)
|
||||||
|
{
|
||||||
|
switch (ca.raw) {
|
||||||
|
case ContentAddressMethod::Raw::Text:
|
||||||
|
return "text:";
|
||||||
|
case ContentAddressMethod::Raw::Flat:
|
||||||
|
case ContentAddressMethod::Raw::NixArchive:
|
||||||
|
case ContentAddressMethod::Raw::Git:
|
||||||
|
return "fixed:" + makeFileIngestionPrefix(ca.getFileIngestionMethod());
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
return FileIngestionMethod::Flat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ContentAddressMethod::renderWithAlgo(HashAlgorithm ha) const
|
std::string ContentAddressMethod::renderWithAlgo(HashAlgorithm ha) const
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
return renderPrefixModern(*this) + printHashAlgo(ha);
|
||||||
[&](const TextIngestionMethod & th) {
|
|
||||||
return std::string{"text:"} + printHashAlgo(ha);
|
|
||||||
},
|
|
||||||
[&](const FileIngestionMethod & fim) {
|
|
||||||
return "fixed:" + makeFileIngestionPrefix(fim) + printHashAlgo(ha);
|
|
||||||
}
|
|
||||||
}, raw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileIngestionMethod ContentAddressMethod::getFileIngestionMethod() const
|
FileIngestionMethod ContentAddressMethod::getFileIngestionMethod() const
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
switch (raw) {
|
||||||
[&](const TextIngestionMethod & th) {
|
case ContentAddressMethod::Raw::Flat:
|
||||||
return FileIngestionMethod::Flat;
|
return FileIngestionMethod::Flat;
|
||||||
},
|
case ContentAddressMethod::Raw::NixArchive:
|
||||||
[&](const FileIngestionMethod & fim) {
|
return FileIngestionMethod::NixArchive;
|
||||||
return fim;
|
case ContentAddressMethod::Raw::Git:
|
||||||
}
|
return FileIngestionMethod::Git;
|
||||||
}, raw);
|
case ContentAddressMethod::Raw::Text:
|
||||||
|
return FileIngestionMethod::Flat;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ContentAddress::render() const
|
std::string ContentAddress::render() const
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
return renderPrefixModern(method) + this->hash.to_string(HashFormat::Nix32, true);
|
||||||
[](const TextIngestionMethod &) -> std::string {
|
|
||||||
return "text:";
|
|
||||||
},
|
|
||||||
[](const FileIngestionMethod & method) {
|
|
||||||
return "fixed:"
|
|
||||||
+ makeFileIngestionPrefix(method);
|
|
||||||
},
|
|
||||||
}, method.raw)
|
|
||||||
+ this->hash.to_string(HashFormat::Nix32, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,17 +168,17 @@ static std::pair<ContentAddressMethod, HashAlgorithm> parseContentAddressMethodP
|
||||||
// No parsing of the ingestion method, "text" only support flat.
|
// No parsing of the ingestion method, "text" only support flat.
|
||||||
HashAlgorithm hashAlgo = parseHashAlgorithm_();
|
HashAlgorithm hashAlgo = parseHashAlgorithm_();
|
||||||
return {
|
return {
|
||||||
TextIngestionMethod {},
|
ContentAddressMethod::Raw::Text,
|
||||||
std::move(hashAlgo),
|
std::move(hashAlgo),
|
||||||
};
|
};
|
||||||
} else if (prefix == "fixed") {
|
} else if (prefix == "fixed") {
|
||||||
// Parse method
|
// Parse method
|
||||||
auto method = FileIngestionMethod::Flat;
|
auto method = ContentAddressMethod::Raw::Flat;
|
||||||
if (splitPrefix(rest, "r:"))
|
if (splitPrefix(rest, "r:"))
|
||||||
method = FileIngestionMethod::NixArchive;
|
method = ContentAddressMethod::Raw::NixArchive;
|
||||||
else if (splitPrefix(rest, "git:")) {
|
else if (splitPrefix(rest, "git:")) {
|
||||||
experimentalFeatureSettings.require(Xp::GitHashing);
|
experimentalFeatureSettings.require(Xp::GitHashing);
|
||||||
method = FileIngestionMethod::Git;
|
method = ContentAddressMethod::Raw::Git;
|
||||||
}
|
}
|
||||||
HashAlgorithm hashAlgo = parseHashAlgorithm_();
|
HashAlgorithm hashAlgo = parseHashAlgorithm_();
|
||||||
return {
|
return {
|
||||||
|
@ -201,57 +239,58 @@ size_t StoreReferences::size() const
|
||||||
|
|
||||||
ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const ContentAddress & ca) noexcept
|
ContentAddressWithReferences ContentAddressWithReferences::withoutRefs(const ContentAddress & ca) noexcept
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
switch (ca.method.raw) {
|
||||||
[&](const TextIngestionMethod &) -> ContentAddressWithReferences {
|
case ContentAddressMethod::Raw::Text:
|
||||||
return TextInfo {
|
return TextInfo {
|
||||||
.hash = ca.hash,
|
.hash = ca.hash,
|
||||||
.references = {},
|
.references = {},
|
||||||
};
|
};
|
||||||
},
|
case ContentAddressMethod::Raw::Flat:
|
||||||
[&](const FileIngestionMethod & method) -> ContentAddressWithReferences {
|
case ContentAddressMethod::Raw::NixArchive:
|
||||||
return FixedOutputInfo {
|
case ContentAddressMethod::Raw::Git:
|
||||||
.method = method,
|
return FixedOutputInfo {
|
||||||
.hash = ca.hash,
|
.method = ca.method.getFileIngestionMethod(),
|
||||||
.references = {},
|
.hash = ca.hash,
|
||||||
};
|
.references = {},
|
||||||
},
|
};
|
||||||
}, ca.method.raw);
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentAddressWithReferences ContentAddressWithReferences::fromParts(
|
ContentAddressWithReferences ContentAddressWithReferences::fromParts(
|
||||||
ContentAddressMethod method, Hash hash, StoreReferences refs)
|
ContentAddressMethod method, Hash hash, StoreReferences refs)
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
switch (method.raw) {
|
||||||
[&](TextIngestionMethod _) -> ContentAddressWithReferences {
|
case ContentAddressMethod::Raw::Text:
|
||||||
if (refs.self)
|
if (refs.self)
|
||||||
throw Error("self-reference not allowed with text hashing");
|
throw Error("self-reference not allowed with text hashing");
|
||||||
return ContentAddressWithReferences {
|
return TextInfo {
|
||||||
TextInfo {
|
.hash = std::move(hash),
|
||||||
.hash = std::move(hash),
|
.references = std::move(refs.others),
|
||||||
.references = std::move(refs.others),
|
};
|
||||||
}
|
case ContentAddressMethod::Raw::Flat:
|
||||||
};
|
case ContentAddressMethod::Raw::NixArchive:
|
||||||
},
|
case ContentAddressMethod::Raw::Git:
|
||||||
[&](FileIngestionMethod m2) -> ContentAddressWithReferences {
|
return FixedOutputInfo {
|
||||||
return ContentAddressWithReferences {
|
.method = method.getFileIngestionMethod(),
|
||||||
FixedOutputInfo {
|
.hash = std::move(hash),
|
||||||
.method = m2,
|
.references = std::move(refs),
|
||||||
.hash = std::move(hash),
|
};
|
||||||
.references = std::move(refs),
|
default:
|
||||||
}
|
assert(false);
|
||||||
};
|
}
|
||||||
},
|
|
||||||
}, method.raw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentAddressMethod ContentAddressWithReferences::getMethod() const
|
ContentAddressMethod ContentAddressWithReferences::getMethod() const
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
return std::visit(overloaded {
|
||||||
[](const TextInfo & th) -> ContentAddressMethod {
|
[](const TextInfo & th) -> ContentAddressMethod {
|
||||||
return TextIngestionMethod {};
|
return ContentAddressMethod::Raw::Text;
|
||||||
},
|
},
|
||||||
[](const FixedOutputInfo & fsh) -> ContentAddressMethod {
|
[](const FixedOutputInfo & fsh) -> ContentAddressMethod {
|
||||||
return fsh.method;
|
return fileIngestionMethodToContentAddressMethod(
|
||||||
|
fsh.method);
|
||||||
},
|
},
|
||||||
}, raw);
|
}, raw);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "hash.hh"
|
#include "hash.hh"
|
||||||
#include "path.hh"
|
#include "path.hh"
|
||||||
#include "file-content-address.hh"
|
#include "file-content-address.hh"
|
||||||
#include "comparator.hh"
|
|
||||||
#include "variant-wrapper.hh"
|
#include "variant-wrapper.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
@ -14,24 +13,6 @@ namespace nix {
|
||||||
* Content addressing method
|
* Content addressing method
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* We only have one way to hash text with references, so this is a single-value
|
|
||||||
type, mainly useful with std::variant.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The single way we can serialize "text" file system objects.
|
|
||||||
*
|
|
||||||
* Somewhat obscure, used by \ref Derivation derivations and
|
|
||||||
* `builtins.toFile` currently.
|
|
||||||
*
|
|
||||||
* TextIngestionMethod is identical to FileIngestionMethod::Fixed except that
|
|
||||||
* the former may not have self-references and is tagged `text:${algo}:${hash}`
|
|
||||||
* rather than `fixed:${algo}:${hash}`. The contents of the store path are
|
|
||||||
* ingested and hashed identically, aside from the slightly different tag and
|
|
||||||
* restriction on self-references.
|
|
||||||
*/
|
|
||||||
struct TextIngestionMethod : std::monostate { };
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the prefix to the hash algorithm which indicates how the
|
* Compute the prefix to the hash algorithm which indicates how the
|
||||||
* files were ingested.
|
* files were ingested.
|
||||||
|
@ -48,14 +29,51 @@ std::string_view makeFileIngestionPrefix(FileIngestionMethod m);
|
||||||
*/
|
*/
|
||||||
struct ContentAddressMethod
|
struct ContentAddressMethod
|
||||||
{
|
{
|
||||||
typedef std::variant<
|
enum struct Raw {
|
||||||
TextIngestionMethod,
|
/**
|
||||||
FileIngestionMethod
|
* Calculate a store path using the `FileIngestionMethod::Flat`
|
||||||
> Raw;
|
* hash of the file system objects, and references.
|
||||||
|
*
|
||||||
|
* See `store-object/content-address.md#method-flat` in the
|
||||||
|
* manual.
|
||||||
|
*/
|
||||||
|
Flat,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a store path using the
|
||||||
|
* `FileIngestionMethod::NixArchive` hash of the file system
|
||||||
|
* objects, and references.
|
||||||
|
*
|
||||||
|
* See `store-object/content-address.md#method-flat` in the
|
||||||
|
* manual.
|
||||||
|
*/
|
||||||
|
NixArchive,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a store path using the `FileIngestionMethod::Git`
|
||||||
|
* hash of the file system objects, and references.
|
||||||
|
*
|
||||||
|
* Part of `ExperimentalFeature::GitHashing`.
|
||||||
|
*
|
||||||
|
* See `store-object/content-address.md#method-git` in the
|
||||||
|
* manual.
|
||||||
|
*/
|
||||||
|
Git,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a store path using the `FileIngestionMethod::Flat`
|
||||||
|
* hash of the file system objects, and references, but in a
|
||||||
|
* different way than `ContentAddressMethod::Raw::Flat`.
|
||||||
|
*
|
||||||
|
* See `store-object/content-address.md#method-text` in the
|
||||||
|
* manual.
|
||||||
|
*/
|
||||||
|
Text,
|
||||||
|
};
|
||||||
|
|
||||||
Raw raw;
|
Raw raw;
|
||||||
|
|
||||||
GENERATE_CMP(ContentAddressMethod, me->raw);
|
auto operator <=>(const ContentAddressMethod &) const = default;
|
||||||
|
|
||||||
MAKE_WRAPPER_CONSTRUCTOR(ContentAddressMethod);
|
MAKE_WRAPPER_CONSTRUCTOR(ContentAddressMethod);
|
||||||
|
|
||||||
|
@ -141,7 +159,7 @@ struct ContentAddress
|
||||||
*/
|
*/
|
||||||
Hash hash;
|
Hash hash;
|
||||||
|
|
||||||
GENERATE_CMP(ContentAddress, me->method, me->hash);
|
auto operator <=>(const ContentAddress &) const = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the content-addressability assertion
|
* Compute the content-addressability assertion
|
||||||
|
@ -200,7 +218,7 @@ struct StoreReferences
|
||||||
*/
|
*/
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
|
|
||||||
GENERATE_CMP(StoreReferences, me->self, me->others);
|
auto operator <=>(const StoreReferences &) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This matches the additional info that we need for makeTextPath
|
// This matches the additional info that we need for makeTextPath
|
||||||
|
@ -217,7 +235,7 @@ struct TextInfo
|
||||||
*/
|
*/
|
||||||
StorePathSet references;
|
StorePathSet references;
|
||||||
|
|
||||||
GENERATE_CMP(TextInfo, me->hash, me->references);
|
auto operator <=>(const TextInfo &) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FixedOutputInfo
|
struct FixedOutputInfo
|
||||||
|
@ -237,7 +255,7 @@ struct FixedOutputInfo
|
||||||
*/
|
*/
|
||||||
StoreReferences references;
|
StoreReferences references;
|
||||||
|
|
||||||
GENERATE_CMP(FixedOutputInfo, me->hash, me->references);
|
auto operator <=>(const FixedOutputInfo &) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,7 +272,7 @@ struct ContentAddressWithReferences
|
||||||
|
|
||||||
Raw raw;
|
Raw raw;
|
||||||
|
|
||||||
GENERATE_CMP(ContentAddressWithReferences, me->raw);
|
auto operator <=>(const ContentAddressWithReferences &) const = default;
|
||||||
|
|
||||||
MAKE_WRAPPER_CONSTRUCTOR(ContentAddressWithReferences);
|
MAKE_WRAPPER_CONSTRUCTOR(ContentAddressWithReferences);
|
||||||
|
|
||||||
|
|
|
@ -435,19 +435,21 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
|
||||||
} else {
|
} else {
|
||||||
HashAlgorithm hashAlgo;
|
HashAlgorithm hashAlgo;
|
||||||
std::string baseName;
|
std::string baseName;
|
||||||
FileIngestionMethod method;
|
ContentAddressMethod method;
|
||||||
{
|
{
|
||||||
bool fixed;
|
bool fixed;
|
||||||
uint8_t recursive;
|
uint8_t recursive;
|
||||||
std::string hashAlgoRaw;
|
std::string hashAlgoRaw;
|
||||||
from >> baseName >> fixed /* obsolete */ >> recursive >> hashAlgoRaw;
|
from >> baseName >> fixed /* obsolete */ >> recursive >> hashAlgoRaw;
|
||||||
if (recursive > (uint8_t) FileIngestionMethod::NixArchive)
|
if (recursive > true)
|
||||||
throw Error("unsupported FileIngestionMethod with value of %i; you may need to upgrade nix-daemon", recursive);
|
throw Error("unsupported FileIngestionMethod with value of %i; you may need to upgrade nix-daemon", recursive);
|
||||||
method = FileIngestionMethod { recursive };
|
method = recursive
|
||||||
|
? ContentAddressMethod::Raw::NixArchive
|
||||||
|
: ContentAddressMethod::Raw::Flat;
|
||||||
/* Compatibility hack. */
|
/* Compatibility hack. */
|
||||||
if (!fixed) {
|
if (!fixed) {
|
||||||
hashAlgoRaw = "sha256";
|
hashAlgoRaw = "sha256";
|
||||||
method = FileIngestionMethod::NixArchive;
|
method = ContentAddressMethod::Raw::NixArchive;
|
||||||
}
|
}
|
||||||
hashAlgo = parseHashAlgo(hashAlgoRaw);
|
hashAlgo = parseHashAlgo(hashAlgoRaw);
|
||||||
}
|
}
|
||||||
|
@ -500,7 +502,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
|
||||||
logger->startWork();
|
logger->startWork();
|
||||||
auto path = ({
|
auto path = ({
|
||||||
StringSource source { s };
|
StringSource source { s };
|
||||||
store->addToStoreFromDump(source, suffix, FileSerialisationMethod::Flat, TextIngestionMethod {}, HashAlgorithm::SHA256, refs, NoRepair);
|
store->addToStoreFromDump(source, suffix, FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, refs, NoRepair);
|
||||||
});
|
});
|
||||||
logger->stopWork();
|
logger->stopWork();
|
||||||
to << store->printStorePath(path);
|
to << store->printStorePath(path);
|
||||||
|
|
|
@ -150,7 +150,7 @@ StorePath writeDerivation(Store & store,
|
||||||
})
|
})
|
||||||
: ({
|
: ({
|
||||||
StringSource s { contents };
|
StringSource s { contents };
|
||||||
store.addToStoreFromDump(s, suffix, FileSerialisationMethod::Flat, TextIngestionMethod {}, HashAlgorithm::SHA256, references, repair);
|
store.addToStoreFromDump(s, suffix, FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, references, repair);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ static DerivationOutput parseDerivationOutput(
|
||||||
{
|
{
|
||||||
if (hashAlgoStr != "") {
|
if (hashAlgoStr != "") {
|
||||||
ContentAddressMethod method = ContentAddressMethod::parsePrefix(hashAlgoStr);
|
ContentAddressMethod method = ContentAddressMethod::parsePrefix(hashAlgoStr);
|
||||||
if (method == TextIngestionMethod {})
|
if (method == ContentAddressMethod::Raw::Text)
|
||||||
xpSettings.require(Xp::DynamicDerivations);
|
xpSettings.require(Xp::DynamicDerivations);
|
||||||
const auto hashAlgo = parseHashAlgo(hashAlgoStr);
|
const auto hashAlgo = parseHashAlgo(hashAlgoStr);
|
||||||
if (hashS == "impure") {
|
if (hashS == "impure") {
|
||||||
|
@ -1249,7 +1249,7 @@ DerivationOutput DerivationOutput::fromJSON(
|
||||||
auto methodAlgo = [&]() -> std::pair<ContentAddressMethod, HashAlgorithm> {
|
auto methodAlgo = [&]() -> std::pair<ContentAddressMethod, HashAlgorithm> {
|
||||||
auto & method_ = getString(valueAt(json, "method"));
|
auto & method_ = getString(valueAt(json, "method"));
|
||||||
ContentAddressMethod method = ContentAddressMethod::parse(method_);
|
ContentAddressMethod method = ContentAddressMethod::parse(method_);
|
||||||
if (method == TextIngestionMethod {})
|
if (method == ContentAddressMethod::Raw::Text)
|
||||||
xpSettings.require(Xp::DynamicDerivations);
|
xpSettings.require(Xp::DynamicDerivations);
|
||||||
|
|
||||||
auto & hashAlgo_ = getString(valueAt(json, "hashAlgo"));
|
auto & hashAlgo_ = getString(valueAt(json, "hashAlgo"));
|
||||||
|
|
|
@ -1253,7 +1253,7 @@ StorePath LocalStore::addToStoreFromDump(
|
||||||
std::filesystem::path tempDir;
|
std::filesystem::path tempDir;
|
||||||
AutoCloseFD tempDirFd;
|
AutoCloseFD tempDirFd;
|
||||||
|
|
||||||
bool methodsMatch = ContentAddressMethod(FileIngestionMethod(dumpMethod)) == hashMethod;
|
bool methodsMatch = static_cast<FileIngestionMethod>(dumpMethod) == hashMethod.getFileIngestionMethod();
|
||||||
|
|
||||||
/* If the methods don't match, our streaming hash of the dump is the
|
/* If the methods don't match, our streaming hash of the dump is the
|
||||||
wrong sort, and we need to rehash. */
|
wrong sort, and we need to rehash. */
|
||||||
|
|
|
@ -48,15 +48,21 @@ std::optional<ContentAddressWithReferences> ValidPathInfo::contentAddressWithRef
|
||||||
if (! ca)
|
if (! ca)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
return std::visit(overloaded {
|
switch (ca->method.raw) {
|
||||||
[&](const TextIngestionMethod &) -> ContentAddressWithReferences {
|
case ContentAddressMethod::Raw::Text:
|
||||||
|
{
|
||||||
assert(references.count(path) == 0);
|
assert(references.count(path) == 0);
|
||||||
return TextInfo {
|
return TextInfo {
|
||||||
.hash = ca->hash,
|
.hash = ca->hash,
|
||||||
.references = references,
|
.references = references,
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
[&](const FileIngestionMethod & m2) -> ContentAddressWithReferences {
|
|
||||||
|
case ContentAddressMethod::Raw::Flat:
|
||||||
|
case ContentAddressMethod::Raw::NixArchive:
|
||||||
|
case ContentAddressMethod::Raw::Git:
|
||||||
|
default:
|
||||||
|
{
|
||||||
auto refs = references;
|
auto refs = references;
|
||||||
bool hasSelfReference = false;
|
bool hasSelfReference = false;
|
||||||
if (refs.count(path)) {
|
if (refs.count(path)) {
|
||||||
|
@ -64,15 +70,15 @@ std::optional<ContentAddressWithReferences> ValidPathInfo::contentAddressWithRef
|
||||||
refs.erase(path);
|
refs.erase(path);
|
||||||
}
|
}
|
||||||
return FixedOutputInfo {
|
return FixedOutputInfo {
|
||||||
.method = m2,
|
.method = ca->method.getFileIngestionMethod(),
|
||||||
.hash = ca->hash,
|
.hash = ca->hash,
|
||||||
.references = {
|
.references = {
|
||||||
.others = std::move(refs),
|
.others = std::move(refs),
|
||||||
.self = hasSelfReference,
|
.self = hasSelfReference,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
}, ca->method.raw);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValidPathInfo::isContentAddressed(const Store & store) const
|
bool ValidPathInfo::isContentAddressed(const Store & store) const
|
||||||
|
@ -127,22 +133,18 @@ ValidPathInfo::ValidPathInfo(
|
||||||
: UnkeyedValidPathInfo(narHash)
|
: UnkeyedValidPathInfo(narHash)
|
||||||
, path(store.makeFixedOutputPathFromCA(name, ca))
|
, path(store.makeFixedOutputPathFromCA(name, ca))
|
||||||
{
|
{
|
||||||
|
this->ca = ContentAddress {
|
||||||
|
.method = ca.getMethod(),
|
||||||
|
.hash = ca.getHash(),
|
||||||
|
};
|
||||||
std::visit(overloaded {
|
std::visit(overloaded {
|
||||||
[this](TextInfo && ti) {
|
[this](TextInfo && ti) {
|
||||||
this->references = std::move(ti.references);
|
this->references = std::move(ti.references);
|
||||||
this->ca = ContentAddress {
|
|
||||||
.method = TextIngestionMethod {},
|
|
||||||
.hash = std::move(ti.hash),
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
[this](FixedOutputInfo && foi) {
|
[this](FixedOutputInfo && foi) {
|
||||||
this->references = std::move(foi.references.others);
|
this->references = std::move(foi.references.others);
|
||||||
if (foi.references.self)
|
if (foi.references.self)
|
||||||
this->references.insert(path);
|
this->references.insert(path);
|
||||||
this->ca = ContentAddress {
|
|
||||||
.method = std::move(foi.method),
|
|
||||||
.hash = std::move(foi.hash),
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
}, std::move(ca).raw);
|
}, std::move(ca).raw);
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,8 +392,9 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
|
||||||
else {
|
else {
|
||||||
if (repair) throw Error("repairing is not supported when building through the Nix daemon protocol < 1.25");
|
if (repair) throw Error("repairing is not supported when building through the Nix daemon protocol < 1.25");
|
||||||
|
|
||||||
std::visit(overloaded {
|
switch (caMethod.raw) {
|
||||||
[&](const TextIngestionMethod & thm) -> void {
|
case ContentAddressMethod::Raw::Text:
|
||||||
|
{
|
||||||
if (hashAlgo != HashAlgorithm::SHA256)
|
if (hashAlgo != HashAlgorithm::SHA256)
|
||||||
throw UnimplementedError("When adding text-hashed data called '%s', only SHA-256 is supported but '%s' was given",
|
throw UnimplementedError("When adding text-hashed data called '%s', only SHA-256 is supported but '%s' was given",
|
||||||
name, printHashAlgo(hashAlgo));
|
name, printHashAlgo(hashAlgo));
|
||||||
|
@ -401,8 +402,14 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
|
||||||
conn->to << WorkerProto::Op::AddTextToStore << name << s;
|
conn->to << WorkerProto::Op::AddTextToStore << name << s;
|
||||||
WorkerProto::write(*this, *conn, references);
|
WorkerProto::write(*this, *conn, references);
|
||||||
conn.processStderr();
|
conn.processStderr();
|
||||||
},
|
break;
|
||||||
[&](const FileIngestionMethod & fim) -> void {
|
}
|
||||||
|
case ContentAddressMethod::Raw::Flat:
|
||||||
|
case ContentAddressMethod::Raw::NixArchive:
|
||||||
|
case ContentAddressMethod::Raw::Git:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
auto fim = caMethod.getFileIngestionMethod();
|
||||||
conn->to
|
conn->to
|
||||||
<< WorkerProto::Op::AddToStore
|
<< WorkerProto::Op::AddToStore
|
||||||
<< name
|
<< name
|
||||||
|
@ -432,9 +439,9 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
|
||||||
} catch (EndOfFile & e) { }
|
} catch (EndOfFile & e) { }
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}, caMethod.raw);
|
}
|
||||||
auto path = parseStorePath(readString(conn->from));
|
auto path = parseStorePath(readString(conn->from));
|
||||||
// Release our connection to prevent a deadlock in queryPathInfo().
|
// Release our connection to prevent a deadlock in queryPathInfo().
|
||||||
conn_.reset();
|
conn_.reset();
|
||||||
|
|
|
@ -356,7 +356,7 @@ ValidPathInfo Store::addToStoreSlow(
|
||||||
RegularFileSink fileSink { caHashSink };
|
RegularFileSink fileSink { caHashSink };
|
||||||
TeeSink unusualHashTee { narHashSink, caHashSink };
|
TeeSink unusualHashTee { narHashSink, caHashSink };
|
||||||
|
|
||||||
auto & narSink = method == FileIngestionMethod::NixArchive && hashAlgo != HashAlgorithm::SHA256
|
auto & narSink = method == ContentAddressMethod::Raw::NixArchive && hashAlgo != HashAlgorithm::SHA256
|
||||||
? static_cast<Sink &>(unusualHashTee)
|
? static_cast<Sink &>(unusualHashTee)
|
||||||
: narHashSink;
|
: narHashSink;
|
||||||
|
|
||||||
|
@ -384,9 +384,9 @@ ValidPathInfo Store::addToStoreSlow(
|
||||||
finish. */
|
finish. */
|
||||||
auto [narHash, narSize] = narHashSink.finish();
|
auto [narHash, narSize] = narHashSink.finish();
|
||||||
|
|
||||||
auto hash = method == FileIngestionMethod::NixArchive && hashAlgo == HashAlgorithm::SHA256
|
auto hash = method == ContentAddressMethod::Raw::NixArchive && hashAlgo == HashAlgorithm::SHA256
|
||||||
? narHash
|
? narHash
|
||||||
: method == FileIngestionMethod::Git
|
: method == ContentAddressMethod::Raw::Git
|
||||||
? git::dumpHash(hashAlgo, srcPath).hash
|
? git::dumpHash(hashAlgo, srcPath).hash
|
||||||
: caHashSink.finish().first;
|
: caHashSink.finish().first;
|
||||||
|
|
||||||
|
|
|
@ -441,7 +441,7 @@ public:
|
||||||
virtual StorePath addToStore(
|
virtual StorePath addToStore(
|
||||||
std::string_view name,
|
std::string_view name,
|
||||||
const SourcePath & path,
|
const SourcePath & path,
|
||||||
ContentAddressMethod method = FileIngestionMethod::NixArchive,
|
ContentAddressMethod method = ContentAddressMethod::Raw::NixArchive,
|
||||||
HashAlgorithm hashAlgo = HashAlgorithm::SHA256,
|
HashAlgorithm hashAlgo = HashAlgorithm::SHA256,
|
||||||
const StorePathSet & references = StorePathSet(),
|
const StorePathSet & references = StorePathSet(),
|
||||||
PathFilter & filter = defaultPathFilter,
|
PathFilter & filter = defaultPathFilter,
|
||||||
|
@ -455,7 +455,7 @@ public:
|
||||||
ValidPathInfo addToStoreSlow(
|
ValidPathInfo addToStoreSlow(
|
||||||
std::string_view name,
|
std::string_view name,
|
||||||
const SourcePath & path,
|
const SourcePath & path,
|
||||||
ContentAddressMethod method = FileIngestionMethod::NixArchive,
|
ContentAddressMethod method = ContentAddressMethod::Raw::NixArchive,
|
||||||
HashAlgorithm hashAlgo = HashAlgorithm::SHA256,
|
HashAlgorithm hashAlgo = HashAlgorithm::SHA256,
|
||||||
const StorePathSet & references = StorePathSet(),
|
const StorePathSet & references = StorePathSet(),
|
||||||
std::optional<Hash> expectedCAHash = {});
|
std::optional<Hash> expectedCAHash = {});
|
||||||
|
@ -481,7 +481,7 @@ public:
|
||||||
Source & dump,
|
Source & dump,
|
||||||
std::string_view name,
|
std::string_view name,
|
||||||
FileSerialisationMethod dumpMethod = FileSerialisationMethod::NixArchive,
|
FileSerialisationMethod dumpMethod = FileSerialisationMethod::NixArchive,
|
||||||
ContentAddressMethod hashMethod = FileIngestionMethod::NixArchive,
|
ContentAddressMethod hashMethod = ContentAddressMethod::Raw::NixArchive,
|
||||||
HashAlgorithm hashAlgo = HashAlgorithm::SHA256,
|
HashAlgorithm hashAlgo = HashAlgorithm::SHA256,
|
||||||
const StorePathSet & references = StorePathSet(),
|
const StorePathSet & references = StorePathSet(),
|
||||||
RepairFlag repair = NoRepair) = 0;
|
RepairFlag repair = NoRepair) = 0;
|
||||||
|
|
|
@ -117,6 +117,8 @@ enum struct FileIngestionMethod : uint8_t {
|
||||||
/**
|
/**
|
||||||
* Git hashing.
|
* Git hashing.
|
||||||
*
|
*
|
||||||
|
* Part of `ExperimentalFeature::GitHashing`.
|
||||||
|
*
|
||||||
* See `file-system-object/content-address.md#serial-git` in the
|
* See `file-system-object/content-address.md#serial-git` in the
|
||||||
* manual.
|
* manual.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -115,7 +115,7 @@ bool createUserEnv(EvalState & state, PackageInfos & elems,
|
||||||
std::string str2 = str.str();
|
std::string str2 = str.str();
|
||||||
StringSource source { str2 };
|
StringSource source { str2 };
|
||||||
state.store->addToStoreFromDump(
|
state.store->addToStoreFromDump(
|
||||||
source, "env-manifest.nix", FileSerialisationMethod::Flat, TextIngestionMethod {}, HashAlgorithm::SHA256, references);
|
source, "env-manifest.nix", FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, references);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Get the environment builder expression. */
|
/* Get the environment builder expression. */
|
||||||
|
|
|
@ -194,10 +194,10 @@ static void opAdd(Strings opFlags, Strings opArgs)
|
||||||
store. */
|
store. */
|
||||||
static void opAddFixed(Strings opFlags, Strings opArgs)
|
static void opAddFixed(Strings opFlags, Strings opArgs)
|
||||||
{
|
{
|
||||||
auto method = FileIngestionMethod::Flat;
|
ContentAddressMethod method = ContentAddressMethod::Raw::Flat;
|
||||||
|
|
||||||
for (auto & i : opFlags)
|
for (auto & i : opFlags)
|
||||||
if (i == "--recursive") method = FileIngestionMethod::NixArchive;
|
if (i == "--recursive") method = ContentAddressMethod::Raw::NixArchive;
|
||||||
else throw UsageError("unknown flag '%1%'", i);
|
else throw UsageError("unknown flag '%1%'", i);
|
||||||
|
|
||||||
if (opArgs.empty())
|
if (opArgs.empty())
|
||||||
|
|
|
@ -12,7 +12,7 @@ struct CmdAddToStore : MixDryRun, StoreCommand
|
||||||
{
|
{
|
||||||
Path path;
|
Path path;
|
||||||
std::optional<std::string> namePart;
|
std::optional<std::string> namePart;
|
||||||
ContentAddressMethod caMethod = FileIngestionMethod::NixArchive;
|
ContentAddressMethod caMethod = ContentAddressMethod::Raw::NixArchive;
|
||||||
HashAlgorithm hashAlgo = HashAlgorithm::SHA256;
|
HashAlgorithm hashAlgo = HashAlgorithm::SHA256;
|
||||||
|
|
||||||
CmdAddToStore()
|
CmdAddToStore()
|
||||||
|
@ -68,7 +68,7 @@ struct CmdAddFile : CmdAddToStore
|
||||||
{
|
{
|
||||||
CmdAddFile()
|
CmdAddFile()
|
||||||
{
|
{
|
||||||
caMethod = FileIngestionMethod::Flat;
|
caMethod = ContentAddressMethod::Raw::Flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string description() override
|
std::string description() override
|
||||||
|
|
|
@ -238,7 +238,7 @@ static StorePath getDerivationEnvironment(ref<Store> store, ref<Store> evalStore
|
||||||
auto getEnvShPath = ({
|
auto getEnvShPath = ({
|
||||||
StringSource source { getEnvSh };
|
StringSource source { getEnvSh };
|
||||||
evalStore->addToStoreFromDump(
|
evalStore->addToStoreFromDump(
|
||||||
source, "get-env.sh", FileSerialisationMethod::Flat, TextIngestionMethod {}, HashAlgorithm::SHA256, {});
|
source, "get-env.sh", FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, {});
|
||||||
});
|
});
|
||||||
|
|
||||||
drv.args = {store->printStorePath(getEnvShPath)};
|
drv.args = {store->printStorePath(getEnvShPath)};
|
||||||
|
|
|
@ -57,7 +57,9 @@ std::tuple<StorePath, Hash> prefetchFile(
|
||||||
bool unpack,
|
bool unpack,
|
||||||
bool executable)
|
bool executable)
|
||||||
{
|
{
|
||||||
auto ingestionMethod = unpack || executable ? FileIngestionMethod::NixArchive : FileIngestionMethod::Flat;
|
ContentAddressMethod method = unpack || executable
|
||||||
|
? ContentAddressMethod::Raw::NixArchive
|
||||||
|
: ContentAddressMethod::Raw::Flat;
|
||||||
|
|
||||||
/* Figure out a name in the Nix store. */
|
/* Figure out a name in the Nix store. */
|
||||||
if (!name) {
|
if (!name) {
|
||||||
|
@ -73,11 +75,10 @@ std::tuple<StorePath, Hash> prefetchFile(
|
||||||
the store. */
|
the store. */
|
||||||
if (expectedHash) {
|
if (expectedHash) {
|
||||||
hashAlgo = expectedHash->algo;
|
hashAlgo = expectedHash->algo;
|
||||||
storePath = store->makeFixedOutputPath(*name, FixedOutputInfo {
|
storePath = store->makeFixedOutputPathFromCA(*name, ContentAddressWithReferences::fromParts(
|
||||||
.method = ingestionMethod,
|
method,
|
||||||
.hash = *expectedHash,
|
*expectedHash,
|
||||||
.references = {},
|
{}));
|
||||||
});
|
|
||||||
if (store->isValidPath(*storePath))
|
if (store->isValidPath(*storePath))
|
||||||
hash = expectedHash;
|
hash = expectedHash;
|
||||||
else
|
else
|
||||||
|
@ -128,7 +129,7 @@ std::tuple<StorePath, Hash> prefetchFile(
|
||||||
|
|
||||||
auto info = store->addToStoreSlow(
|
auto info = store->addToStoreSlow(
|
||||||
*name, PosixSourceAccessor::createAtRoot(tmpFile),
|
*name, PosixSourceAccessor::createAtRoot(tmpFile),
|
||||||
ingestionMethod, hashAlgo, {}, expectedHash);
|
method, hashAlgo, {}, expectedHash);
|
||||||
storePath = info.path;
|
storePath = info.path;
|
||||||
assert(info.ca);
|
assert(info.ca);
|
||||||
hash = info.ca->hash;
|
hash = info.ca->hash;
|
||||||
|
|
|
@ -335,7 +335,7 @@ SV *
|
||||||
StoreWrapper::addToStore(char * srcPath, int recursive, char * algo)
|
StoreWrapper::addToStore(char * srcPath, int recursive, char * algo)
|
||||||
PPCODE:
|
PPCODE:
|
||||||
try {
|
try {
|
||||||
auto method = recursive ? FileIngestionMethod::NixArchive : FileIngestionMethod::Flat;
|
auto method = recursive ? ContentAddressMethod::Raw::NixArchive : ContentAddressMethod::Raw::Flat;
|
||||||
auto path = THIS->store->addToStore(
|
auto path = THIS->store->addToStore(
|
||||||
std::string(baseNameOf(srcPath)),
|
std::string(baseNameOf(srcPath)),
|
||||||
PosixSourceAccessor::createAtRoot(srcPath),
|
PosixSourceAccessor::createAtRoot(srcPath),
|
||||||
|
|
|
@ -83,15 +83,15 @@ CHARACTERIZATION_TEST(
|
||||||
"content-address",
|
"content-address",
|
||||||
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
|
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = TextIngestionMethod {},
|
.method = ContentAddressMethod::Raw::Text,
|
||||||
.hash = hashString(HashAlgorithm::SHA256, "Derive(...)"),
|
.hash = hashString(HashAlgorithm::SHA256, "Derive(...)"),
|
||||||
},
|
},
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = FileIngestionMethod::Flat,
|
.method = ContentAddressMethod::Raw::Flat,
|
||||||
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
||||||
},
|
},
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = FileIngestionMethod::NixArchive,
|
.method = ContentAddressMethod::Raw::NixArchive,
|
||||||
.hash = hashString(HashAlgorithm::SHA256, "(...)"),
|
.hash = hashString(HashAlgorithm::SHA256, "(...)"),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
@ -178,7 +178,7 @@ CHARACTERIZATION_TEST(
|
||||||
std::nullopt,
|
std::nullopt,
|
||||||
std::optional {
|
std::optional {
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = FileIngestionMethod::Flat,
|
.method = ContentAddressMethod::Raw::Flat,
|
||||||
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,11 +9,11 @@ namespace nix {
|
||||||
* --------------------------------------------------------------------------*/
|
* --------------------------------------------------------------------------*/
|
||||||
|
|
||||||
TEST(ContentAddressMethod, testRoundTripPrintParse_1) {
|
TEST(ContentAddressMethod, testRoundTripPrintParse_1) {
|
||||||
for (const ContentAddressMethod & cam : {
|
for (ContentAddressMethod cam : {
|
||||||
ContentAddressMethod { TextIngestionMethod {} },
|
ContentAddressMethod::Raw::Text,
|
||||||
ContentAddressMethod { FileIngestionMethod::Flat },
|
ContentAddressMethod::Raw::Flat,
|
||||||
ContentAddressMethod { FileIngestionMethod::NixArchive },
|
ContentAddressMethod::Raw::NixArchive,
|
||||||
ContentAddressMethod { FileIngestionMethod::Git },
|
ContentAddressMethod::Raw::Git,
|
||||||
}) {
|
}) {
|
||||||
EXPECT_EQ(ContentAddressMethod::parse(cam.render()), cam);
|
EXPECT_EQ(ContentAddressMethod::parse(cam.render()), cam);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ TEST_JSON(DerivationTest, inputAddressed,
|
||||||
TEST_JSON(DerivationTest, caFixedFlat,
|
TEST_JSON(DerivationTest, caFixedFlat,
|
||||||
(DerivationOutput::CAFixed {
|
(DerivationOutput::CAFixed {
|
||||||
.ca = {
|
.ca = {
|
||||||
.method = FileIngestionMethod::Flat,
|
.method = ContentAddressMethod::Raw::Flat,
|
||||||
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -117,7 +117,7 @@ TEST_JSON(DerivationTest, caFixedFlat,
|
||||||
TEST_JSON(DerivationTest, caFixedNAR,
|
TEST_JSON(DerivationTest, caFixedNAR,
|
||||||
(DerivationOutput::CAFixed {
|
(DerivationOutput::CAFixed {
|
||||||
.ca = {
|
.ca = {
|
||||||
.method = FileIngestionMethod::NixArchive,
|
.method = ContentAddressMethod::Raw::NixArchive,
|
||||||
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -126,6 +126,7 @@ TEST_JSON(DerivationTest, caFixedNAR,
|
||||||
TEST_JSON(DynDerivationTest, caFixedText,
|
TEST_JSON(DynDerivationTest, caFixedText,
|
||||||
(DerivationOutput::CAFixed {
|
(DerivationOutput::CAFixed {
|
||||||
.ca = {
|
.ca = {
|
||||||
|
.method = ContentAddressMethod::Raw::Text,
|
||||||
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -133,7 +134,7 @@ TEST_JSON(DynDerivationTest, caFixedText,
|
||||||
|
|
||||||
TEST_JSON(CaDerivationTest, caFloating,
|
TEST_JSON(CaDerivationTest, caFloating,
|
||||||
(DerivationOutput::CAFloating {
|
(DerivationOutput::CAFloating {
|
||||||
.method = FileIngestionMethod::NixArchive,
|
.method = ContentAddressMethod::Raw::NixArchive,
|
||||||
.hashAlgo = HashAlgorithm::SHA256,
|
.hashAlgo = HashAlgorithm::SHA256,
|
||||||
}),
|
}),
|
||||||
"drv-name", "output-name")
|
"drv-name", "output-name")
|
||||||
|
@ -144,7 +145,7 @@ TEST_JSON(DerivationTest, deferred,
|
||||||
|
|
||||||
TEST_JSON(ImpureDerivationTest, impure,
|
TEST_JSON(ImpureDerivationTest, impure,
|
||||||
(DerivationOutput::Impure {
|
(DerivationOutput::Impure {
|
||||||
.method = FileIngestionMethod::NixArchive,
|
.method = ContentAddressMethod::Raw::NixArchive,
|
||||||
.hashAlgo = HashAlgorithm::SHA256,
|
.hashAlgo = HashAlgorithm::SHA256,
|
||||||
}),
|
}),
|
||||||
"drv-name", "output-name")
|
"drv-name", "output-name")
|
||||||
|
|
|
@ -55,15 +55,15 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
defaultVersion,
|
defaultVersion,
|
||||||
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
|
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = TextIngestionMethod {},
|
.method = ContentAddressMethod::Raw::Text,
|
||||||
.hash = hashString(HashAlgorithm::SHA256, "Derive(...)"),
|
.hash = hashString(HashAlgorithm::SHA256, "Derive(...)"),
|
||||||
},
|
},
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = FileIngestionMethod::Flat,
|
.method = ContentAddressMethod::Raw::Flat,
|
||||||
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
||||||
},
|
},
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = FileIngestionMethod::NixArchive,
|
.method = ContentAddressMethod::Raw::NixArchive,
|
||||||
.hash = hashString(HashAlgorithm::SHA256, "(...)"),
|
.hash = hashString(HashAlgorithm::SHA256, "(...)"),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
@ -398,7 +398,7 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
std::nullopt,
|
std::nullopt,
|
||||||
std::optional {
|
std::optional {
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = FileIngestionMethod::Flat,
|
.method = ContentAddressMethod::Raw::Flat,
|
||||||
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -56,15 +56,15 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
defaultVersion,
|
defaultVersion,
|
||||||
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
|
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = TextIngestionMethod {},
|
.method = ContentAddressMethod::Raw::Text,
|
||||||
.hash = hashString(HashAlgorithm::SHA256, "Derive(...)"),
|
.hash = hashString(HashAlgorithm::SHA256, "Derive(...)"),
|
||||||
},
|
},
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = FileIngestionMethod::Flat,
|
.method = ContentAddressMethod::Raw::Flat,
|
||||||
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
||||||
},
|
},
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = FileIngestionMethod::NixArchive,
|
.method = ContentAddressMethod::Raw::NixArchive,
|
||||||
.hash = hashString(HashAlgorithm::SHA256, "(...)"),
|
.hash = hashString(HashAlgorithm::SHA256, "(...)"),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
@ -598,7 +598,7 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
std::nullopt,
|
std::nullopt,
|
||||||
std::optional {
|
std::optional {
|
||||||
ContentAddress {
|
ContentAddress {
|
||||||
.method = FileIngestionMethod::Flat,
|
.method = ContentAddressMethod::Raw::Flat,
|
||||||
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue