mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-10 08:16:15 +02:00
Proper parse
and render
functions for FileIngestionMethod
and ContentAddressMethod
No outward facing behavior is changed. Older methods with same names that operate on on method + algo pair (for old-style `<method>:algo`) are renamed to `*WithAlgo`.) The functions are unit-tested in the same way the names for the hash algorithms are tested.
This commit is contained in:
parent
fb5a438dca
commit
41dd9857c7
10 changed files with 162 additions and 30 deletions
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
std::string makeFileIngestionPrefix(FileIngestionMethod m)
|
std::string_view makeFileIngestionPrefix(FileIngestionMethod m)
|
||||||
{
|
{
|
||||||
switch (m) {
|
switch (m) {
|
||||||
case FileIngestionMethod::Flat:
|
case FileIngestionMethod::Flat:
|
||||||
|
@ -16,10 +16,29 @@ std::string makeFileIngestionPrefix(FileIngestionMethod m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ContentAddressMethod::renderPrefix() const
|
std::string_view ContentAddressMethod::render() const
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
return std::visit(overloaded {
|
||||||
[](TextIngestionMethod) -> std::string { return "text:"; },
|
[](TextIngestionMethod) -> std::string_view { return "text"; },
|
||||||
|
[](FileIngestionMethod m2) {
|
||||||
|
/* Not prefixed for back compat with things that couldn't produce text before. */
|
||||||
|
return renderFileIngestionMethod(m2);
|
||||||
|
},
|
||||||
|
}, raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentAddressMethod ContentAddressMethod::parse(std::string_view m)
|
||||||
|
{
|
||||||
|
if (m == "text")
|
||||||
|
return TextIngestionMethod {};
|
||||||
|
else
|
||||||
|
return parseFileIngestionMethod(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view ContentAddressMethod::renderPrefix() const
|
||||||
|
{
|
||||||
|
return std::visit(overloaded {
|
||||||
|
[](TextIngestionMethod) -> std::string_view { return "text:"; },
|
||||||
[](FileIngestionMethod m2) {
|
[](FileIngestionMethod m2) {
|
||||||
/* Not prefixed for back compat with things that couldn't produce text before. */
|
/* Not prefixed for back compat with things that couldn't produce text before. */
|
||||||
return makeFileIngestionPrefix(m2);
|
return makeFileIngestionPrefix(m2);
|
||||||
|
@ -38,7 +57,7 @@ ContentAddressMethod ContentAddressMethod::parsePrefix(std::string_view & m)
|
||||||
return FileIngestionMethod::Flat;
|
return FileIngestionMethod::Flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ContentAddressMethod::render(HashAlgorithm ha) const
|
std::string ContentAddressMethod::renderWithAlgo(HashAlgorithm ha) const
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
return std::visit(overloaded {
|
||||||
[&](const TextIngestionMethod & th) {
|
[&](const TextIngestionMethod & th) {
|
||||||
|
@ -133,7 +152,7 @@ ContentAddress ContentAddress::parse(std::string_view rawCa)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<ContentAddressMethod, HashAlgorithm> ContentAddressMethod::parse(std::string_view caMethod)
|
std::pair<ContentAddressMethod, HashAlgorithm> ContentAddressMethod::parseWithAlgo(std::string_view caMethod)
|
||||||
{
|
{
|
||||||
std::string asPrefix = std::string{caMethod} + ":";
|
std::string asPrefix = std::string{caMethod} + ":";
|
||||||
// parseContentAddressMethodPrefix takes its argument by reference
|
// parseContentAddressMethodPrefix takes its argument by reference
|
||||||
|
@ -155,7 +174,7 @@ std::string renderContentAddress(std::optional<ContentAddress> ca)
|
||||||
|
|
||||||
std::string ContentAddress::printMethodAlgo() const
|
std::string ContentAddress::printMethodAlgo() const
|
||||||
{
|
{
|
||||||
return method.renderPrefix()
|
return std::string { method.renderPrefix() }
|
||||||
+ printHashAlgo(hash.algo);
|
+ printHashAlgo(hash.algo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ 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.
|
||||||
*/
|
*/
|
||||||
std::string makeFileIngestionPrefix(FileIngestionMethod m);
|
std::string_view makeFileIngestionPrefix(FileIngestionMethod m);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enumeration of all the ways we can content-address store objects.
|
* An enumeration of all the ways we can content-address store objects.
|
||||||
|
@ -59,6 +59,20 @@ struct ContentAddressMethod
|
||||||
|
|
||||||
MAKE_WRAPPER_CONSTRUCTOR(ContentAddressMethod);
|
MAKE_WRAPPER_CONSTRUCTOR(ContentAddressMethod);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a content addressing method (name).
|
||||||
|
*
|
||||||
|
* The inverse of `render`.
|
||||||
|
*/
|
||||||
|
static ContentAddressMethod parse(std::string_view rawCaMethod);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a content addressing method (name).
|
||||||
|
*
|
||||||
|
* The inverse of `parse`.
|
||||||
|
*/
|
||||||
|
std::string_view render() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the prefix tag which indicates how the files
|
* Parse the prefix tag which indicates how the files
|
||||||
* were ingested, with the fixed output case not prefixed for back
|
* were ingested, with the fixed output case not prefixed for back
|
||||||
|
@ -74,12 +88,12 @@ struct ContentAddressMethod
|
||||||
*
|
*
|
||||||
* The rough inverse of `parsePrefix()`.
|
* The rough inverse of `parsePrefix()`.
|
||||||
*/
|
*/
|
||||||
std::string renderPrefix() const;
|
std::string_view renderPrefix() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a content addressing method and hash type.
|
* Parse a content addressing method and hash type.
|
||||||
*/
|
*/
|
||||||
static std::pair<ContentAddressMethod, HashAlgorithm> parse(std::string_view rawCaMethod);
|
static std::pair<ContentAddressMethod, HashAlgorithm> parseWithAlgo(std::string_view rawCaMethod);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a content addressing method and hash type in a
|
* Render a content addressing method and hash type in a
|
||||||
|
@ -87,7 +101,7 @@ struct ContentAddressMethod
|
||||||
*
|
*
|
||||||
* The rough inverse of `parse()`.
|
* The rough inverse of `parse()`.
|
||||||
*/
|
*/
|
||||||
std::string render(HashAlgorithm ht) const;
|
std::string renderWithAlgo(HashAlgorithm ht) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the underlying way to content-address file system objects.
|
* Get the underlying way to content-address file system objects.
|
||||||
|
|
|
@ -400,7 +400,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
|
||||||
logger->startWork();
|
logger->startWork();
|
||||||
auto pathInfo = [&]() {
|
auto pathInfo = [&]() {
|
||||||
// NB: FramedSource must be out of scope before logger->stopWork();
|
// NB: FramedSource must be out of scope before logger->stopWork();
|
||||||
auto [contentAddressMethod, hashAlgo_] = ContentAddressMethod::parse(camStr);
|
auto [contentAddressMethod, hashAlgo_] = ContentAddressMethod::parseWithAlgo(camStr);
|
||||||
auto hashAlgo = hashAlgo_; // work around clang bug
|
auto hashAlgo = hashAlgo_; // work around clang bug
|
||||||
FramedSource source(from);
|
FramedSource source(from);
|
||||||
// TODO these two steps are essentially RemoteStore::addCAToStore. Move it up to Store.
|
// TODO these two steps are essentially RemoteStore::addCAToStore. Move it up to Store.
|
||||||
|
|
|
@ -601,7 +601,7 @@ std::string Derivation::unparse(const StoreDirConfig & store, bool maskOutputs,
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::CAFloating & dof) {
|
[&](const DerivationOutput::CAFloating & dof) {
|
||||||
s += ','; printUnquotedString(s, "");
|
s += ','; printUnquotedString(s, "");
|
||||||
s += ','; printUnquotedString(s, dof.method.renderPrefix() + printHashAlgo(dof.hashAlgo));
|
s += ','; printUnquotedString(s, std::string { dof.method.renderPrefix() } + printHashAlgo(dof.hashAlgo));
|
||||||
s += ','; printUnquotedString(s, "");
|
s += ','; printUnquotedString(s, "");
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::Deferred &) {
|
[&](const DerivationOutput::Deferred &) {
|
||||||
|
@ -612,7 +612,7 @@ std::string Derivation::unparse(const StoreDirConfig & store, bool maskOutputs,
|
||||||
[&](const DerivationOutput::Impure & doi) {
|
[&](const DerivationOutput::Impure & doi) {
|
||||||
// FIXME
|
// FIXME
|
||||||
s += ','; printUnquotedString(s, "");
|
s += ','; printUnquotedString(s, "");
|
||||||
s += ','; printUnquotedString(s, doi.method.renderPrefix() + printHashAlgo(doi.hashAlgo));
|
s += ','; printUnquotedString(s, std::string { doi.method.renderPrefix() } + printHashAlgo(doi.hashAlgo));
|
||||||
s += ','; printUnquotedString(s, "impure");
|
s += ','; printUnquotedString(s, "impure");
|
||||||
}
|
}
|
||||||
}, i.second.raw);
|
}, i.second.raw);
|
||||||
|
@ -984,7 +984,7 @@ void writeDerivation(Sink & out, const StoreDirConfig & store, const BasicDeriva
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::CAFloating & dof) {
|
[&](const DerivationOutput::CAFloating & dof) {
|
||||||
out << ""
|
out << ""
|
||||||
<< (dof.method.renderPrefix() + printHashAlgo(dof.hashAlgo))
|
<< (std::string { dof.method.renderPrefix() } + printHashAlgo(dof.hashAlgo))
|
||||||
<< "";
|
<< "";
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::Deferred &) {
|
[&](const DerivationOutput::Deferred &) {
|
||||||
|
@ -994,7 +994,7 @@ void writeDerivation(Sink & out, const StoreDirConfig & store, const BasicDeriva
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::Impure & doi) {
|
[&](const DerivationOutput::Impure & doi) {
|
||||||
out << ""
|
out << ""
|
||||||
<< (doi.method.renderPrefix() + printHashAlgo(doi.hashAlgo))
|
<< (std::string { doi.method.renderPrefix() } + printHashAlgo(doi.hashAlgo))
|
||||||
<< "impure";
|
<< "impure";
|
||||||
},
|
},
|
||||||
}, i.second.raw);
|
}, i.second.raw);
|
||||||
|
@ -1221,11 +1221,11 @@ nlohmann::json DerivationOutput::toJSON(
|
||||||
// FIXME print refs?
|
// FIXME print refs?
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::CAFloating & dof) {
|
[&](const DerivationOutput::CAFloating & dof) {
|
||||||
res["hashAlgo"] = dof.method.renderPrefix() + printHashAlgo(dof.hashAlgo);
|
res["hashAlgo"] = std::string { dof.method.renderPrefix() } + printHashAlgo(dof.hashAlgo);
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::Deferred &) {},
|
[&](const DerivationOutput::Deferred &) {},
|
||||||
[&](const DerivationOutput::Impure & doi) {
|
[&](const DerivationOutput::Impure & doi) {
|
||||||
res["hashAlgo"] = doi.method.renderPrefix() + printHashAlgo(doi.hashAlgo);
|
res["hashAlgo"] = std::string { doi.method.renderPrefix() } + printHashAlgo(doi.hashAlgo);
|
||||||
res["impure"] = true;
|
res["impure"] = true;
|
||||||
},
|
},
|
||||||
}, raw);
|
}, raw);
|
||||||
|
|
|
@ -435,7 +435,7 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
|
||||||
conn->to
|
conn->to
|
||||||
<< WorkerProto::Op::AddToStore
|
<< WorkerProto::Op::AddToStore
|
||||||
<< name
|
<< name
|
||||||
<< caMethod.render(hashAlgo);
|
<< caMethod.renderWithAlgo(hashAlgo);
|
||||||
WorkerProto::write(*this, *conn, references);
|
WorkerProto::write(*this, *conn, references);
|
||||||
conn->to << repair;
|
conn->to << repair;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,31 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
FileIngestionMethod parseFileIngestionMethod(std::string_view input)
|
||||||
|
{
|
||||||
|
if (input == "flat") {
|
||||||
|
return FileIngestionMethod::Flat;
|
||||||
|
} else if (input == "nar") {
|
||||||
|
return FileIngestionMethod::Recursive;
|
||||||
|
} else {
|
||||||
|
throw UsageError("Unknown file ingestion method '%s', expect `flat` or `nar`");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string_view renderFileIngestionMethod(FileIngestionMethod method)
|
||||||
|
{
|
||||||
|
switch (method) {
|
||||||
|
case FileIngestionMethod::Flat:
|
||||||
|
return "flat";
|
||||||
|
case FileIngestionMethod::Recursive:
|
||||||
|
return "nar";
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dumpPath(
|
void dumpPath(
|
||||||
SourceAccessor & accessor, const CanonPath & path,
|
SourceAccessor & accessor, const CanonPath & path,
|
||||||
Sink & sink,
|
Sink & sink,
|
||||||
|
|
|
@ -23,6 +23,23 @@ enum struct FileIngestionMethod : uint8_t {
|
||||||
Recursive = 1,
|
Recursive = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a `FileIngestionMethod` by name. Choice of:
|
||||||
|
*
|
||||||
|
* - `flat`: `FileIngestionMethod::Flat`
|
||||||
|
* - `nar`: `FileIngestionMethod::Recursive`
|
||||||
|
*
|
||||||
|
* Oppostite of `renderFileIngestionMethod`.
|
||||||
|
*/
|
||||||
|
FileIngestionMethod parseFileIngestionMethod(std::string_view input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a `FileIngestionMethod` by name.
|
||||||
|
*
|
||||||
|
* Oppostite of `parseFileIngestionMethod`.
|
||||||
|
*/
|
||||||
|
std::string_view renderFileIngestionMethod(FileIngestionMethod method);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dump a serialization of the given file system object.
|
* Dump a serialization of the given file system object.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -6,17 +6,6 @@
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
static FileIngestionMethod parseIngestionMethod(std::string_view input)
|
|
||||||
{
|
|
||||||
if (input == "flat") {
|
|
||||||
return FileIngestionMethod::Flat;
|
|
||||||
} else if (input == "nar") {
|
|
||||||
return FileIngestionMethod::Recursive;
|
|
||||||
} else {
|
|
||||||
throw UsageError("Unknown hash mode '%s', expect `flat` or `nar`");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CmdAddToStore : MixDryRun, StoreCommand
|
struct CmdAddToStore : MixDryRun, StoreCommand
|
||||||
{
|
{
|
||||||
Path path;
|
Path path;
|
||||||
|
@ -49,7 +38,7 @@ struct CmdAddToStore : MixDryRun, StoreCommand
|
||||||
)",
|
)",
|
||||||
.labels = {"hash-mode"},
|
.labels = {"hash-mode"},
|
||||||
.handler = {[this](std::string s) {
|
.handler = {[this](std::string s) {
|
||||||
this->caMethod = parseIngestionMethod(s);
|
this->caMethod = parseFileIngestionMethod(s);
|
||||||
}},
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
35
tests/unit/libstore/content-address.cc
Normal file
35
tests/unit/libstore/content-address.cc
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "content-address.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* ContentAddressMethod::parse, ContentAddressMethod::render
|
||||||
|
* --------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
TEST(ContentAddressMethod, testRoundTripPrintParse_1) {
|
||||||
|
for (const ContentAddressMethod & cam : {
|
||||||
|
ContentAddressMethod { TextIngestionMethod {} },
|
||||||
|
ContentAddressMethod { FileIngestionMethod::Flat },
|
||||||
|
ContentAddressMethod { FileIngestionMethod::Recursive },
|
||||||
|
}) {
|
||||||
|
EXPECT_EQ(ContentAddressMethod::parse(cam.render()), cam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ContentAddressMethod, testRoundTripPrintParse_2) {
|
||||||
|
for (const std::string_view camS : {
|
||||||
|
"text",
|
||||||
|
"flat",
|
||||||
|
"nar",
|
||||||
|
}) {
|
||||||
|
EXPECT_EQ(ContentAddressMethod::parse(camS).render(), camS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ContentAddressMethod, testParseContentAddressMethodOptException) {
|
||||||
|
EXPECT_THROW(ContentAddressMethod::parse("narwhal"), UsageError);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
tests/unit/libutil/file-content-address.cc
Normal file
33
tests/unit/libutil/file-content-address.cc
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "file-content-address.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* parseFileIngestionMethod, renderFileIngestionMethod
|
||||||
|
* --------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
TEST(FileIngestionMethod, testRoundTripPrintParse_1) {
|
||||||
|
for (const FileIngestionMethod fim : {
|
||||||
|
FileIngestionMethod::Flat,
|
||||||
|
FileIngestionMethod::Recursive,
|
||||||
|
}) {
|
||||||
|
EXPECT_EQ(parseFileIngestionMethod(renderFileIngestionMethod(fim)), fim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FileIngestionMethod, testRoundTripPrintParse_2) {
|
||||||
|
for (const std::string_view fimS : {
|
||||||
|
"flat",
|
||||||
|
"nar",
|
||||||
|
}) {
|
||||||
|
EXPECT_EQ(renderFileIngestionMethod(parseFileIngestionMethod(fimS)), fimS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FileIngestionMethod, testParseFileIngestionMethodOptException) {
|
||||||
|
EXPECT_THROW(parseFileIngestionMethod("narwhal"), UsageError);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue