Create Derivation::fromJSON
And test, of course
This commit is contained in:
parent
81dfc2b012
commit
fe9cbe838c
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <variant>
|
||||
#include "hash.hh"
|
||||
#include "comparator.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
@ -30,6 +31,8 @@ struct TextHash {
|
|||
* Hash of the contents of the text/file.
|
||||
*/
|
||||
Hash hash;
|
||||
|
||||
GENERATE_CMP(TextHash, me->hash);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -46,6 +49,8 @@ struct FixedOutputHash {
|
|||
Hash hash;
|
||||
|
||||
std::string printMethodAlgo() const;
|
||||
|
||||
GENERATE_CMP(FixedOutputHash, me->method, me->hash);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -889,6 +889,7 @@ std::optional<BasicDerivation> Derivation::tryResolve(
|
|||
return resolved;
|
||||
}
|
||||
|
||||
|
||||
const Hash impureOutputHash = hashString(htSHA256, "impure");
|
||||
|
||||
nlohmann::json DerivationOutput::toJSON(
|
||||
|
@ -916,6 +917,73 @@ nlohmann::json DerivationOutput::toJSON(
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
DerivationOutput DerivationOutput::fromJSON(
|
||||
const Store & store, std::string_view drvName, std::string_view outputName,
|
||||
const nlohmann::json & _json)
|
||||
{
|
||||
std::set<std::string_view> keys;
|
||||
auto json = (std::map<std::string, nlohmann::json>) _json;
|
||||
|
||||
for (const auto & [key, _] : json)
|
||||
keys.insert(key);
|
||||
|
||||
auto methodAlgo = [&]() -> std::pair<FileIngestionMethod, HashType> {
|
||||
std::string hashAlgo = json["hashAlgo"];
|
||||
auto method = FileIngestionMethod::Flat;
|
||||
if (hashAlgo.substr(0, 2) == "r:") {
|
||||
method = FileIngestionMethod::Recursive;
|
||||
hashAlgo = hashAlgo.substr(2);
|
||||
}
|
||||
auto hashType = parseHashType(hashAlgo);
|
||||
return { method, hashType };
|
||||
};
|
||||
|
||||
if (keys == (std::set<std::string_view> { "path" })) {
|
||||
return DerivationOutput::InputAddressed {
|
||||
.path = store.parseStorePath((std::string) json["path"]),
|
||||
};
|
||||
}
|
||||
|
||||
else if (keys == (std::set<std::string_view> { "path", "hashAlgo", "hash" })) {
|
||||
auto [method, hashType] = methodAlgo();
|
||||
auto dof = DerivationOutput::CAFixed {
|
||||
.hash = {
|
||||
.method = method,
|
||||
.hash = Hash::parseNonSRIUnprefixed((std::string) json["hash"], hashType),
|
||||
},
|
||||
};
|
||||
if (dof.path(store, drvName, outputName) != store.parseStorePath((std::string) json["path"]))
|
||||
throw Error("Path doesn't match derivation output");
|
||||
return dof;
|
||||
}
|
||||
|
||||
else if (keys == (std::set<std::string_view> { "hashAlgo" })) {
|
||||
auto [method, hashType] = methodAlgo();
|
||||
return DerivationOutput::CAFloating {
|
||||
.method = method,
|
||||
.hashType = hashType,
|
||||
};
|
||||
}
|
||||
|
||||
else if (keys == (std::set<std::string_view> { })) {
|
||||
return DerivationOutput::Deferred {};
|
||||
}
|
||||
|
||||
else if (keys == (std::set<std::string_view> { "hashAlgo", "impure" })) {
|
||||
auto [method, hashType] = methodAlgo();
|
||||
return DerivationOutput::Impure {
|
||||
.method = method,
|
||||
.hashType = hashType,
|
||||
};
|
||||
}
|
||||
|
||||
else {
|
||||
throw Error("invalid JSON for derivation output");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nlohmann::json Derivation::toJSON(const Store & store) const
|
||||
{
|
||||
nlohmann::json res = nlohmann::json::object();
|
||||
|
@ -950,4 +1018,41 @@ nlohmann::json Derivation::toJSON(const Store & store) const
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
Derivation Derivation::fromJSON(
|
||||
const Store & store, std::string_view drvName,
|
||||
const nlohmann::json & json)
|
||||
{
|
||||
Derivation res;
|
||||
|
||||
{
|
||||
auto & outputsObj = json["outputs"];
|
||||
for (auto & [outputName, output] : outputsObj.items()) {
|
||||
res.outputs.insert_or_assign(
|
||||
outputName,
|
||||
DerivationOutput::fromJSON(store, drvName, outputName, output));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto & inputsList = json["inputSrcs"];
|
||||
for (auto & input : inputsList)
|
||||
res.inputSrcs.insert(store.parseStorePath(static_cast<const std::string &>(input)));
|
||||
}
|
||||
|
||||
{
|
||||
auto & inputDrvsObj = json["inputDrvs"];
|
||||
for (auto & [inputDrvPath, inputOutputs] : inputDrvsObj.items())
|
||||
res.inputDrvs[store.parseStorePath(inputDrvPath)] =
|
||||
static_cast<const StringSet &>(inputOutputs);
|
||||
}
|
||||
|
||||
res.platform = json["system"];
|
||||
res.builder = json["builder"];
|
||||
res.args = json["args"];
|
||||
res.env = json["env"];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "content-address.hh"
|
||||
#include "repair-flag.hh"
|
||||
#include "sync.hh"
|
||||
#include "comparator.hh"
|
||||
|
||||
#include <map>
|
||||
#include <variant>
|
||||
|
@ -24,6 +25,8 @@ class Store;
|
|||
struct DerivationOutputInputAddressed
|
||||
{
|
||||
StorePath path;
|
||||
|
||||
GENERATE_CMP(DerivationOutputInputAddressed, me->path);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -44,6 +47,8 @@ struct DerivationOutputCAFixed
|
|||
* @param outputName The name of this output.
|
||||
*/
|
||||
StorePath path(const Store & store, std::string_view drvName, std::string_view outputName) const;
|
||||
|
||||
GENERATE_CMP(DerivationOutputCAFixed, me->hash);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -62,13 +67,17 @@ struct DerivationOutputCAFloating
|
|||
* How the serialization will be hashed
|
||||
*/
|
||||
HashType hashType;
|
||||
|
||||
GENERATE_CMP(DerivationOutputCAFloating, me->method, me->hashType);
|
||||
};
|
||||
|
||||
/**
|
||||
* Input-addressed output which depends on a (CA) derivation whose hash
|
||||
* isn't known yet.
|
||||
*/
|
||||
struct DerivationOutputDeferred {};
|
||||
struct DerivationOutputDeferred {
|
||||
GENERATE_CMP(DerivationOutputDeferred);
|
||||
};
|
||||
|
||||
/**
|
||||
* Impure output which is moved to a content-addressed location (like
|
||||
|
@ -85,6 +94,8 @@ struct DerivationOutputImpure
|
|||
* How the serialization will be hashed
|
||||
*/
|
||||
HashType hashType;
|
||||
|
||||
GENERATE_CMP(DerivationOutputImpure, me->method, me->hashType);
|
||||
};
|
||||
|
||||
typedef std::variant<
|
||||
|
@ -125,6 +136,11 @@ struct DerivationOutput : _DerivationOutputRaw
|
|||
const Store & store,
|
||||
std::string_view drvName,
|
||||
std::string_view outputName) const;
|
||||
static DerivationOutput fromJSON(
|
||||
const Store & store,
|
||||
std::string_view drvName,
|
||||
std::string_view outputName,
|
||||
const nlohmann::json & json);
|
||||
};
|
||||
|
||||
typedef std::map<std::string, DerivationOutput> DerivationOutputs;
|
||||
|
@ -273,6 +289,15 @@ struct BasicDerivation
|
|||
DerivationOutputsAndOptPaths outputsAndOptPaths(const Store & store) const;
|
||||
|
||||
static std::string_view nameFromPath(const StorePath & storePath);
|
||||
|
||||
GENERATE_CMP(BasicDerivation,
|
||||
me->outputs,
|
||||
me->inputSrcs,
|
||||
me->platform,
|
||||
me->builder,
|
||||
me->args,
|
||||
me->env,
|
||||
me->name);
|
||||
};
|
||||
|
||||
struct Derivation : BasicDerivation
|
||||
|
@ -313,6 +338,14 @@ struct Derivation : BasicDerivation
|
|||
Derivation(BasicDerivation && bd) : BasicDerivation(std::move(bd)) { }
|
||||
|
||||
nlohmann::json toJSON(const Store & store) const;
|
||||
static Derivation fromJSON(
|
||||
const Store & store,
|
||||
std::string_view drvName,
|
||||
const nlohmann::json & json);
|
||||
|
||||
GENERATE_CMP(Derivation,
|
||||
static_cast<const BasicDerivation &>(*me),
|
||||
me->inputDrvs);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -11,15 +11,29 @@ class DerivationTest : public LibStoreTest
|
|||
{
|
||||
};
|
||||
|
||||
#define TEST_JSON(TYPE, NAME, STR, VAL, ...) \
|
||||
TEST_F(DerivationTest, TYPE ## _ ## NAME ## _to_json) { \
|
||||
using nlohmann::literals::operator "" _json; \
|
||||
ASSERT_EQ( \
|
||||
STR ## _json, \
|
||||
(TYPE { VAL }).toJSON(*store __VA_OPT__(,) __VA_ARGS__)); \
|
||||
#define TEST_JSON(NAME, STR, VAL, DRV_NAME, OUTPUT_NAME) \
|
||||
TEST_F(DerivationTest, DerivationOutput_ ## NAME ## _to_json) { \
|
||||
using nlohmann::literals::operator "" _json; \
|
||||
ASSERT_EQ( \
|
||||
STR ## _json, \
|
||||
(DerivationOutput { VAL }).toJSON( \
|
||||
*store, \
|
||||
DRV_NAME, \
|
||||
OUTPUT_NAME)); \
|
||||
} \
|
||||
\
|
||||
TEST_F(DerivationTest, DerivationOutput_ ## NAME ## _from_json) { \
|
||||
using nlohmann::literals::operator "" _json; \
|
||||
ASSERT_EQ( \
|
||||
DerivationOutput { VAL }, \
|
||||
DerivationOutput::fromJSON( \
|
||||
*store, \
|
||||
DRV_NAME, \
|
||||
OUTPUT_NAME, \
|
||||
STR ## _json)); \
|
||||
}
|
||||
|
||||
TEST_JSON(DerivationOutput, inputAddressed,
|
||||
TEST_JSON(inputAddressed,
|
||||
R"({
|
||||
"path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"
|
||||
})",
|
||||
|
@ -28,7 +42,7 @@ TEST_JSON(DerivationOutput, inputAddressed,
|
|||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(DerivationOutput, caFixed,
|
||||
TEST_JSON(caFixed,
|
||||
R"({
|
||||
"hashAlgo": "r:sha256",
|
||||
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
|
||||
|
@ -42,7 +56,7 @@ TEST_JSON(DerivationOutput, caFixed,
|
|||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(DerivationOutput, caFloating,
|
||||
TEST_JSON(caFloating,
|
||||
R"({
|
||||
"hashAlgo": "r:sha256"
|
||||
})",
|
||||
|
@ -52,12 +66,12 @@ TEST_JSON(DerivationOutput, caFloating,
|
|||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(DerivationOutput, deferred,
|
||||
TEST_JSON(deferred,
|
||||
R"({ })",
|
||||
DerivationOutput::Deferred { },
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(DerivationOutput, impure,
|
||||
TEST_JSON(impure,
|
||||
R"({
|
||||
"hashAlgo": "r:sha256",
|
||||
"impure": true
|
||||
|
@ -68,7 +82,27 @@ TEST_JSON(DerivationOutput, impure,
|
|||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(Derivation, impure,
|
||||
#undef TEST_JSON
|
||||
|
||||
#define TEST_JSON(NAME, STR, VAL, DRV_NAME) \
|
||||
TEST_F(DerivationTest, Derivation_ ## NAME ## _to_json) { \
|
||||
using nlohmann::literals::operator "" _json; \
|
||||
ASSERT_EQ( \
|
||||
STR ## _json, \
|
||||
(Derivation { VAL }).toJSON(*store)); \
|
||||
} \
|
||||
\
|
||||
TEST_F(DerivationTest, Derivation_ ## NAME ## _from_json) { \
|
||||
using nlohmann::literals::operator "" _json; \
|
||||
ASSERT_EQ( \
|
||||
Derivation { VAL }, \
|
||||
Derivation::fromJSON( \
|
||||
*store, \
|
||||
DRV_NAME, \
|
||||
STR ## _json)); \
|
||||
}
|
||||
|
||||
TEST_JSON(simple,
|
||||
R"({
|
||||
"inputSrcs": [
|
||||
"/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"
|
||||
|
@ -117,7 +151,8 @@ TEST_JSON(Derivation, impure,
|
|||
},
|
||||
};
|
||||
drv;
|
||||
}))
|
||||
}),
|
||||
"drv-name")
|
||||
|
||||
#undef TEST_JSON
|
||||
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
#define GENERATE_ONE_CMP(COMPARATOR, MY_TYPE, FIELDS...) \
|
||||
#define GENERATE_ONE_CMP(COMPARATOR, MY_TYPE, ...) \
|
||||
bool operator COMPARATOR(const MY_TYPE& other) const { \
|
||||
const MY_TYPE* me = this; \
|
||||
auto fields1 = std::make_tuple( FIELDS ); \
|
||||
me = &other; \
|
||||
auto fields2 = std::make_tuple( FIELDS ); \
|
||||
__VA_OPT__(const MY_TYPE* me = this;) \
|
||||
auto fields1 = std::make_tuple( __VA_ARGS__ ); \
|
||||
__VA_OPT__(me = &other;) \
|
||||
auto fields2 = std::make_tuple( __VA_ARGS__ ); \
|
||||
return fields1 COMPARATOR fields2; \
|
||||
}
|
||||
#define GENERATE_EQUAL(args...) GENERATE_ONE_CMP(==, args)
|
||||
|
|
Loading…
Reference in a new issue