mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
Split out UnkeyedRealisation from Realisation
Realisations are conceptually key-value pairs, mapping `DrvOutputs` (the key) to information about that derivation output. This separate the value type, which will be useful in maps, etc., where we don't want to denormalize by including the key twice. This matches similar changes for existing types: | keyed | unkeyed | |--------------------|------------------------| | `ValidPathInfo` | `UnkeyedValidPathInfo` | | `KeyedBuildResult` | `BuildResult` | | `Realisation` | `UnkeyedRealisation` | Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
This commit is contained in:
parent
a543519ca9
commit
6995d325ef
28 changed files with 363 additions and 251 deletions
|
|
@ -117,10 +117,11 @@ RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const
|
||||||
"the derivation '%s' has unrealised output '%s' (derived-path.cc/toRealisedPaths)",
|
"the derivation '%s' has unrealised output '%s' (derived-path.cc/toRealisedPaths)",
|
||||||
store.printStorePath(p.drvPath->outPath()),
|
store.printStorePath(p.drvPath->outPath()),
|
||||||
outputName);
|
outputName);
|
||||||
auto thisRealisation = store.queryRealisation(DrvOutput{*drvOutput, outputName});
|
DrvOutput key{*drvOutput, outputName};
|
||||||
|
auto thisRealisation = store.queryRealisation(key);
|
||||||
assert(thisRealisation); // We’ve built it, so we must
|
assert(thisRealisation); // We’ve built it, so we must
|
||||||
// have the realisation
|
// have the realisation
|
||||||
res.insert(*thisRealisation);
|
res.insert(Realisation{*thisRealisation, std::move(key)});
|
||||||
} else {
|
} else {
|
||||||
res.insert(outputPath);
|
res.insert(outputPath);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,32 +112,34 @@ CHARACTERIZATION_TEST(
|
||||||
"realisation",
|
"realisation",
|
||||||
(std::tuple<Realisation, Realisation>{
|
(std::tuple<Realisation, Realisation>{
|
||||||
Realisation{
|
Realisation{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
.signatures = {"asdf", "qwer"},
|
||||||
.outputName = "baz",
|
},
|
||||||
},
|
DrvOutput{
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||||
.signatures = {"asdf", "qwer"},
|
.outputName = "baz",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Realisation{
|
Realisation{
|
||||||
.id =
|
{
|
||||||
{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
.signatures = {"asdf", "qwer"},
|
||||||
.outputName = "baz",
|
.dependentRealisations =
|
||||||
},
|
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
|
||||||
.signatures = {"asdf", "qwer"},
|
|
||||||
.dependentRealisations =
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
DrvOutput{
|
{
|
||||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "quux",
|
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
|
.outputName = "quux",
|
||||||
|
},
|
||||||
|
StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
},
|
},
|
||||||
StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||||
|
.outputName = "baz",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,16 +49,16 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
RealisationJsonTest,
|
RealisationJsonTest,
|
||||||
([] {
|
([] {
|
||||||
Realisation simple{
|
Realisation simple{
|
||||||
|
{
|
||||||
.id =
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"},
|
||||||
{
|
},
|
||||||
.drvHash = Hash::parseExplicitFormatUnprefixed(
|
{
|
||||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
.drvHash = Hash::parseExplicitFormatUnprefixed(
|
||||||
HashAlgorithm::SHA256,
|
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||||
HashFormat::Base16),
|
HashAlgorithm::SHA256,
|
||||||
.outputName = "foo",
|
HashFormat::Base16),
|
||||||
},
|
.outputName = "foo",
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"},
|
},
|
||||||
};
|
};
|
||||||
return ::testing::Values(
|
return ::testing::Values(
|
||||||
std::pair{
|
std::pair{
|
||||||
|
|
|
||||||
|
|
@ -95,32 +95,34 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
defaultVersion,
|
defaultVersion,
|
||||||
(std::tuple<Realisation, Realisation>{
|
(std::tuple<Realisation, Realisation>{
|
||||||
Realisation{
|
Realisation{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
.signatures = {"asdf", "qwer"},
|
||||||
.outputName = "baz",
|
},
|
||||||
},
|
{
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||||
.signatures = {"asdf", "qwer"},
|
.outputName = "baz",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Realisation{
|
Realisation{
|
||||||
.id =
|
{
|
||||||
{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
.signatures = {"asdf", "qwer"},
|
||||||
.outputName = "baz",
|
.dependentRealisations =
|
||||||
},
|
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
|
||||||
.signatures = {"asdf", "qwer"},
|
|
||||||
.dependentRealisations =
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
DrvOutput{
|
{
|
||||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "quux",
|
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
|
.outputName = "quux",
|
||||||
|
},
|
||||||
|
StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
},
|
},
|
||||||
StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||||
|
.outputName = "baz",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
@ -196,25 +198,27 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
{
|
{
|
||||||
"foo",
|
"foo",
|
||||||
{
|
{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash =
|
},
|
||||||
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "foo",
|
.drvHash =
|
||||||
},
|
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
.outputName = "foo",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bar",
|
"bar",
|
||||||
{
|
{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"},
|
||||||
.drvHash =
|
},
|
||||||
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "bar",
|
.drvHash =
|
||||||
},
|
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"},
|
.outputName = "bar",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -148,32 +148,34 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
defaultVersion,
|
defaultVersion,
|
||||||
(std::tuple<Realisation, Realisation>{
|
(std::tuple<Realisation, Realisation>{
|
||||||
Realisation{
|
Realisation{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
.signatures = {"asdf", "qwer"},
|
||||||
.outputName = "baz",
|
},
|
||||||
},
|
DrvOutput{
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||||
.signatures = {"asdf", "qwer"},
|
.outputName = "baz",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Realisation{
|
Realisation{
|
||||||
.id =
|
{
|
||||||
{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
.signatures = {"asdf", "qwer"},
|
||||||
.outputName = "baz",
|
.dependentRealisations =
|
||||||
},
|
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
|
||||||
.signatures = {"asdf", "qwer"},
|
|
||||||
.dependentRealisations =
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
DrvOutput{
|
{
|
||||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "quux",
|
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
|
.outputName = "quux",
|
||||||
|
},
|
||||||
|
StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
},
|
},
|
||||||
StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DrvOutput{
|
||||||
|
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||||
|
.outputName = "baz",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
@ -214,25 +216,25 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
{
|
{
|
||||||
"foo",
|
"foo",
|
||||||
{
|
{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash =
|
},
|
||||||
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "foo",
|
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
},
|
.outputName = "foo",
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bar",
|
"bar",
|
||||||
{
|
{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"},
|
||||||
.drvHash =
|
},
|
||||||
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "bar",
|
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
},
|
.outputName = "bar",
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -267,25 +269,27 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
{
|
{
|
||||||
"foo",
|
"foo",
|
||||||
{
|
{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash =
|
},
|
||||||
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "foo",
|
.drvHash =
|
||||||
},
|
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
.outputName = "foo",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bar",
|
"bar",
|
||||||
{
|
{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"},
|
||||||
.drvHash =
|
},
|
||||||
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "bar",
|
.drvHash =
|
||||||
},
|
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"},
|
.outputName = "bar",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -324,25 +328,27 @@ VERSIONED_CHARACTERIZATION_TEST(
|
||||||
{
|
{
|
||||||
"foo",
|
"foo",
|
||||||
{
|
{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
||||||
.drvHash =
|
},
|
||||||
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "foo",
|
.drvHash =
|
||||||
},
|
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"},
|
.outputName = "foo",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bar",
|
"bar",
|
||||||
{
|
{
|
||||||
.id =
|
{
|
||||||
DrvOutput{
|
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"},
|
||||||
.drvHash =
|
},
|
||||||
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
DrvOutput{
|
||||||
.outputName = "bar",
|
.drvHash =
|
||||||
},
|
Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||||
.outPath = StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"},
|
.outputName = "bar",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -502,10 +502,15 @@ StorePath BinaryCacheStore::addToStore(
|
||||||
->path;
|
->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinaryCacheStore::queryRealisationUncached(
|
std::string BinaryCacheStore::makeRealisationPath(const DrvOutput & id)
|
||||||
const DrvOutput & id, Callback<std::shared_ptr<const Realisation>> callback) noexcept
|
|
||||||
{
|
{
|
||||||
auto outputInfoFilePath = realisationsPrefix + "/" + id.to_string() + ".doi";
|
return realisationsPrefix + "/" + id.to_string() + ".doi";
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryCacheStore::queryRealisationUncached(
|
||||||
|
const DrvOutput & id, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept
|
||||||
|
{
|
||||||
|
auto outputInfoFilePath = makeRealisationPath(id);
|
||||||
|
|
||||||
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));
|
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));
|
||||||
|
|
||||||
|
|
@ -515,11 +520,12 @@ void BinaryCacheStore::queryRealisationUncached(
|
||||||
if (!data)
|
if (!data)
|
||||||
return (*callbackPtr)({});
|
return (*callbackPtr)({});
|
||||||
|
|
||||||
std::shared_ptr<const Realisation> realisation;
|
std::shared_ptr<const UnkeyedRealisation> realisation;
|
||||||
try {
|
try {
|
||||||
realisation = std::make_shared<const Realisation>(nlohmann::json::parse(*data));
|
realisation = std::make_shared<const UnkeyedRealisation>(nlohmann::json::parse(*data));
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace({}, "while parsing file '%s' as a realisation", outputInfoFilePath);
|
e.addTrace(
|
||||||
|
{}, "while parsing file '%s' as a realisation for key '%s'", outputInfoFilePath, id.to_string());
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
return (*callbackPtr)(std::move(realisation));
|
return (*callbackPtr)(std::move(realisation));
|
||||||
|
|
@ -535,8 +541,7 @@ void BinaryCacheStore::registerDrvOutput(const Realisation & info)
|
||||||
{
|
{
|
||||||
if (diskCache)
|
if (diskCache)
|
||||||
diskCache->upsertRealisation(config.getReference().render(/*FIXME withParams=*/false), info);
|
diskCache->upsertRealisation(config.getReference().render(/*FIXME withParams=*/false), info);
|
||||||
auto filePath = realisationsPrefix + "/" + info.id.to_string() + ".doi";
|
upsertFile(makeRealisationPath(info.id), static_cast<nlohmann::json>(info).dump(), "application/json");
|
||||||
upsertFile(filePath, static_cast<nlohmann::json>(info).dump(), "application/json");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<RemoteFSAccessor> BinaryCacheStore::getRemoteFSAccessor(bool requireValidPath)
|
ref<RemoteFSAccessor> BinaryCacheStore::getRemoteFSAccessor(bool requireValidPath)
|
||||||
|
|
|
||||||
|
|
@ -1111,13 +1111,22 @@ DerivationBuildingGoal::checkPathValidity(std::map<std::string, InitialOutput> &
|
||||||
// without the `ca-derivations` experimental flag).
|
// without the `ca-derivations` experimental flag).
|
||||||
worker.store.registerDrvOutput(
|
worker.store.registerDrvOutput(
|
||||||
Realisation{
|
Realisation{
|
||||||
|
{
|
||||||
|
.outPath = info.known->path,
|
||||||
|
},
|
||||||
drvOutput,
|
drvOutput,
|
||||||
info.known->path,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info.known && info.known->isValid())
|
if (info.known && info.known->isValid())
|
||||||
validOutputs.emplace(i.first, Realisation{drvOutput, info.known->path});
|
validOutputs.emplace(
|
||||||
|
i.first,
|
||||||
|
Realisation{
|
||||||
|
{
|
||||||
|
.outPath = info.known->path,
|
||||||
|
},
|
||||||
|
drvOutput,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allValid = true;
|
bool allValid = true;
|
||||||
|
|
|
||||||
|
|
@ -181,13 +181,17 @@ Goal::Co DerivationGoal::haveDerivation(bool storeDerivation)
|
||||||
auto realisation = [&] {
|
auto realisation = [&] {
|
||||||
auto take1 = get(success.builtOutputs, wantedOutput);
|
auto take1 = get(success.builtOutputs, wantedOutput);
|
||||||
if (take1)
|
if (take1)
|
||||||
return *take1;
|
return static_cast<UnkeyedRealisation>(*take1);
|
||||||
|
|
||||||
/* The above `get` should work. But stateful tracking of
|
/* The above `get` should work. But stateful tracking of
|
||||||
outputs in resolvedResult, this can get out of sync with the
|
outputs in resolvedResult, this can get out of sync with the
|
||||||
store, which is our actual source of truth. For now we just
|
store, which is our actual source of truth. For now we just
|
||||||
check the store directly if it fails. */
|
check the store directly if it fails. */
|
||||||
auto take2 = worker.evalStore.queryRealisation(DrvOutput{*resolvedHash, wantedOutput});
|
auto take2 = worker.evalStore.queryRealisation(
|
||||||
|
DrvOutput{
|
||||||
|
.drvHash = *resolvedHash,
|
||||||
|
.outputName = wantedOutput,
|
||||||
|
});
|
||||||
if (take2)
|
if (take2)
|
||||||
return *take2;
|
return *take2;
|
||||||
|
|
||||||
|
|
@ -198,8 +202,12 @@ Goal::Co DerivationGoal::haveDerivation(bool storeDerivation)
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (!drv->type().isImpure()) {
|
if (!drv->type().isImpure()) {
|
||||||
auto newRealisation = realisation;
|
Realisation newRealisation{
|
||||||
newRealisation.id = DrvOutput{*outputHash, wantedOutput};
|
realisation,
|
||||||
|
{
|
||||||
|
.drvHash = *outputHash,
|
||||||
|
.outputName = wantedOutput,
|
||||||
|
}};
|
||||||
newRealisation.signatures.clear();
|
newRealisation.signatures.clear();
|
||||||
if (!drv->type().isFixed()) {
|
if (!drv->type().isFixed()) {
|
||||||
auto & drvStore = worker.evalStore.isValidPath(drvPath) ? worker.evalStore : worker.store;
|
auto & drvStore = worker.evalStore.isValidPath(drvPath) ? worker.evalStore : worker.store;
|
||||||
|
|
@ -248,7 +256,16 @@ Goal::Co DerivationGoal::haveDerivation(bool storeDerivation)
|
||||||
/* In checking mode, the builder will not register any outputs.
|
/* In checking mode, the builder will not register any outputs.
|
||||||
So we want to make sure the ones that we wanted to check are
|
So we want to make sure the ones that we wanted to check are
|
||||||
properly there. */
|
properly there. */
|
||||||
success.builtOutputs = {{wantedOutput, assertPathValidity()}};
|
success.builtOutputs = {{
|
||||||
|
wantedOutput,
|
||||||
|
{
|
||||||
|
assertPathValidity(),
|
||||||
|
{
|
||||||
|
.drvHash = outputHash,
|
||||||
|
.outputName = wantedOutput,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}};
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise the builder will give us info for out output, but
|
/* Otherwise the builder will give us info for out output, but
|
||||||
also for other outputs. Filter down to just our output so as
|
also for other outputs. Filter down to just our output so as
|
||||||
|
|
@ -352,18 +369,20 @@ Goal::Co DerivationGoal::repairClosure()
|
||||||
co_return doneSuccess(BuildResult::Success::AlreadyValid, assertPathValidity());
|
co_return doneSuccess(BuildResult::Success::AlreadyValid, assertPathValidity());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::pair<Realisation, PathStatus>> DerivationGoal::checkPathValidity()
|
std::optional<std::pair<UnkeyedRealisation, PathStatus>> DerivationGoal::checkPathValidity()
|
||||||
{
|
{
|
||||||
if (drv->type().isImpure())
|
if (drv->type().isImpure())
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
auto drvOutput = DrvOutput{outputHash, wantedOutput};
|
auto drvOutput = DrvOutput{outputHash, wantedOutput};
|
||||||
|
|
||||||
std::optional<Realisation> mRealisation;
|
std::optional<UnkeyedRealisation> mRealisation;
|
||||||
|
|
||||||
if (auto * mOutput = get(drv->outputs, wantedOutput)) {
|
if (auto * mOutput = get(drv->outputs, wantedOutput)) {
|
||||||
if (auto mPath = mOutput->path(worker.store, drv->name, wantedOutput)) {
|
if (auto mPath = mOutput->path(worker.store, drv->name, wantedOutput)) {
|
||||||
mRealisation = Realisation{drvOutput, std::move(*mPath)};
|
mRealisation = UnkeyedRealisation{
|
||||||
|
.outPath = std::move(*mPath),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Error(
|
throw Error(
|
||||||
|
|
@ -391,7 +410,14 @@ std::optional<std::pair<Realisation, PathStatus>> DerivationGoal::checkPathValid
|
||||||
// derivation, and the output path is valid, but we don't have
|
// derivation, and the output path is valid, but we don't have
|
||||||
// its realisation stored (probably because it has been built
|
// its realisation stored (probably because it has been built
|
||||||
// without the `ca-derivations` experimental flag).
|
// without the `ca-derivations` experimental flag).
|
||||||
worker.store.registerDrvOutput(*mRealisation);
|
worker.store.registerDrvOutput(
|
||||||
|
Realisation{
|
||||||
|
*mRealisation,
|
||||||
|
{
|
||||||
|
.drvHash = outputHash,
|
||||||
|
.outputName = wantedOutput,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {{*mRealisation, status}};
|
return {{*mRealisation, status}};
|
||||||
|
|
@ -399,7 +425,7 @@ std::optional<std::pair<Realisation, PathStatus>> DerivationGoal::checkPathValid
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Realisation DerivationGoal::assertPathValidity()
|
UnkeyedRealisation DerivationGoal::assertPathValidity()
|
||||||
{
|
{
|
||||||
auto checkResult = checkPathValidity();
|
auto checkResult = checkPathValidity();
|
||||||
if (!(checkResult && checkResult->second == PathStatus::Valid))
|
if (!(checkResult && checkResult->second == PathStatus::Valid))
|
||||||
|
|
@ -407,11 +433,20 @@ Realisation DerivationGoal::assertPathValidity()
|
||||||
return checkResult->first;
|
return checkResult->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
Goal::Done DerivationGoal::doneSuccess(BuildResult::Success::Status status, Realisation builtOutput)
|
Goal::Done DerivationGoal::doneSuccess(BuildResult::Success::Status status, UnkeyedRealisation builtOutput)
|
||||||
{
|
{
|
||||||
buildResult.inner = BuildResult::Success{
|
buildResult.inner = BuildResult::Success{
|
||||||
.status = status,
|
.status = status,
|
||||||
.builtOutputs = {{wantedOutput, std::move(builtOutput)}},
|
.builtOutputs = {{
|
||||||
|
wantedOutput,
|
||||||
|
{
|
||||||
|
std::move(builtOutput),
|
||||||
|
DrvOutput{
|
||||||
|
.drvHash = outputHash,
|
||||||
|
.outputName = wantedOutput,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
};
|
};
|
||||||
|
|
||||||
mcExpectedBuilds.reset();
|
mcExpectedBuilds.reset();
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,10 @@ Goal::Co DrvOutputSubstitutionGoal::init()
|
||||||
outPipe->createAsyncPipe(worker.ioport.get());
|
outPipe->createAsyncPipe(worker.ioport.get());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto promise = std::make_shared<std::promise<std::shared_ptr<const Realisation>>>();
|
auto promise = std::make_shared<std::promise<std::shared_ptr<const UnkeyedRealisation>>>();
|
||||||
|
|
||||||
sub->queryRealisation(
|
sub->queryRealisation(
|
||||||
id, {[outPipe(outPipe), promise(promise)](std::future<std::shared_ptr<const Realisation>> res) {
|
id, {[outPipe(outPipe), promise(promise)](std::future<std::shared_ptr<const UnkeyedRealisation>> res) {
|
||||||
try {
|
try {
|
||||||
Finally updateStats([&]() { outPipe->writeSide.close(); });
|
Finally updateStats([&]() { outPipe->writeSide.close(); });
|
||||||
promise->set_value(res.get());
|
promise->set_value(res.get());
|
||||||
|
|
@ -74,7 +74,7 @@ Goal::Co DrvOutputSubstitutionGoal::init()
|
||||||
* The realisation corresponding to the given output id.
|
* The realisation corresponding to the given output id.
|
||||||
* Will be filled once we can get it.
|
* Will be filled once we can get it.
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<const Realisation> outputInfo;
|
std::shared_ptr<const UnkeyedRealisation> outputInfo;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
outputInfo = promise->get_future().get();
|
outputInfo = promise->get_future().get();
|
||||||
|
|
@ -131,7 +131,7 @@ Goal::Co DrvOutputSubstitutionGoal::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
Goal::Co DrvOutputSubstitutionGoal::realisationFetched(
|
Goal::Co DrvOutputSubstitutionGoal::realisationFetched(
|
||||||
Goals waitees, std::shared_ptr<const Realisation> outputInfo, nix::ref<nix::Store> sub)
|
Goals waitees, std::shared_ptr<const UnkeyedRealisation> outputInfo, nix::ref<nix::Store> sub)
|
||||||
{
|
{
|
||||||
waitees.insert(worker.makePathSubstitutionGoal(outputInfo->outPath));
|
waitees.insert(worker.makePathSubstitutionGoal(outputInfo->outPath));
|
||||||
|
|
||||||
|
|
@ -144,7 +144,7 @@ Goal::Co DrvOutputSubstitutionGoal::realisationFetched(
|
||||||
co_return amDone(nrNoSubstituters > 0 ? ecNoSubstituters : ecFailed);
|
co_return amDone(nrNoSubstituters > 0 ? ecNoSubstituters : ecFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
worker.store.registerDrvOutput(*outputInfo);
|
worker.store.registerDrvOutput({*outputInfo, id});
|
||||||
|
|
||||||
trace("finished");
|
trace("finished");
|
||||||
co_return amDone(ecSuccess);
|
co_return amDone(ecSuccess);
|
||||||
|
|
|
||||||
|
|
@ -964,7 +964,7 @@ static void performOp(
|
||||||
if (GET_PROTOCOL_MINOR(conn.protoVersion) < 31) {
|
if (GET_PROTOCOL_MINOR(conn.protoVersion) < 31) {
|
||||||
auto outputId = DrvOutput::parse(readString(conn.from));
|
auto outputId = DrvOutput::parse(readString(conn.from));
|
||||||
auto outputPath = StorePath(readString(conn.from));
|
auto outputPath = StorePath(readString(conn.from));
|
||||||
store->registerDrvOutput(Realisation{.id = outputId, .outPath = outputPath});
|
store->registerDrvOutput(Realisation{{.outPath = outputPath}, outputId});
|
||||||
} else {
|
} else {
|
||||||
auto realisation = WorkerProto::Serialise<Realisation>::read(*store, rconn);
|
auto realisation = WorkerProto::Serialise<Realisation>::read(*store, rconn);
|
||||||
store->registerDrvOutput(realisation);
|
store->registerDrvOutput(realisation);
|
||||||
|
|
@ -986,7 +986,7 @@ static void performOp(
|
||||||
} else {
|
} else {
|
||||||
std::set<Realisation> realisations;
|
std::set<Realisation> realisations;
|
||||||
if (info)
|
if (info)
|
||||||
realisations.insert(*info);
|
realisations.insert({*info, outputId});
|
||||||
WorkerProto::write(*store, wconn, realisations);
|
WorkerProto::write(*store, wconn, realisations);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -266,8 +266,8 @@ struct DummyStoreImpl : DummyStore
|
||||||
throw Error("path '%s' is not valid", printStorePath(path));
|
throw Error("path '%s' is not valid", printStorePath(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void queryRealisationUncached(
|
||||||
queryRealisationUncached(const DrvOutput &, Callback<std::shared_ptr<const Realisation>> callback) noexcept override
|
const DrvOutput &, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept override
|
||||||
{
|
{
|
||||||
callback(nullptr);
|
callback(nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,13 +80,22 @@ private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// The prefix under which realisation infos will be stored
|
/**
|
||||||
const std::string realisationsPrefix = "realisations";
|
* The prefix under which realisation infos will be stored
|
||||||
|
*/
|
||||||
|
constexpr const static std::string realisationsPrefix = "realisations";
|
||||||
|
|
||||||
const std::string cacheInfoFile = "nix-cache-info";
|
constexpr const static std::string cacheInfoFile = "nix-cache-info";
|
||||||
|
|
||||||
BinaryCacheStore(Config &);
|
BinaryCacheStore(Config &);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the path to the given realisation
|
||||||
|
*
|
||||||
|
* It's `${realisationsPrefix}/${drvOutput}.doi`.
|
||||||
|
*/
|
||||||
|
std::string makeRealisationPath(const DrvOutput & id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual bool fileExists(const std::string & path) = 0;
|
virtual bool fileExists(const std::string & path) = 0;
|
||||||
|
|
@ -175,7 +184,7 @@ public:
|
||||||
void registerDrvOutput(const Realisation & info) override;
|
void registerDrvOutput(const Realisation & info) override;
|
||||||
|
|
||||||
void queryRealisationUncached(
|
void queryRealisationUncached(
|
||||||
const DrvOutput &, Callback<std::shared_ptr<const Realisation>> callback) noexcept override;
|
const DrvOutput &, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept override;
|
||||||
|
|
||||||
void narFromPath(const StorePath & path, Sink & sink) override;
|
void narFromPath(const StorePath & path, Sink & sink) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,17 +93,17 @@ private:
|
||||||
* of the wanted output, and a `PathStatus` with the
|
* of the wanted output, and a `PathStatus` with the
|
||||||
* current status of that output.
|
* current status of that output.
|
||||||
*/
|
*/
|
||||||
std::optional<std::pair<Realisation, PathStatus>> checkPathValidity();
|
std::optional<std::pair<UnkeyedRealisation, PathStatus>> checkPathValidity();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts if any output is not valid or corrupt, and otherwise
|
* Aborts if any output is not valid or corrupt, and otherwise
|
||||||
* returns a 'Realisation' for the wanted output.
|
* returns a 'Realisation' for the wanted output.
|
||||||
*/
|
*/
|
||||||
Realisation assertPathValidity();
|
UnkeyedRealisation assertPathValidity();
|
||||||
|
|
||||||
Co repairClosure();
|
Co repairClosure();
|
||||||
|
|
||||||
Done doneSuccess(BuildResult::Success::Status status, Realisation builtOutput);
|
Done doneSuccess(BuildResult::Success::Status status, UnkeyedRealisation builtOutput);
|
||||||
|
|
||||||
Done doneFailure(BuildError ex);
|
Done doneFailure(BuildError ex);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ public:
|
||||||
DrvOutputSubstitutionGoal(const DrvOutput & id, Worker & worker);
|
DrvOutputSubstitutionGoal(const DrvOutput & id, Worker & worker);
|
||||||
|
|
||||||
Co init();
|
Co init();
|
||||||
Co realisationFetched(Goals waitees, std::shared_ptr<const Realisation> outputInfo, nix::ref<nix::Store> sub);
|
Co
|
||||||
|
realisationFetched(Goals waitees, std::shared_ptr<const UnkeyedRealisation> outputInfo, nix::ref<nix::Store> sub);
|
||||||
|
|
||||||
void timedOut(Error && ex) override
|
void timedOut(Error && ex) override
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -208,8 +208,8 @@ public:
|
||||||
*/
|
*/
|
||||||
std::optional<TrustedFlag> isTrustedClient() override;
|
std::optional<TrustedFlag> isTrustedClient() override;
|
||||||
|
|
||||||
void
|
void queryRealisationUncached(
|
||||||
queryRealisationUncached(const DrvOutput &, Callback<std::shared_ptr<const Realisation>> callback) noexcept override
|
const DrvOutput &, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept override
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
{
|
{
|
||||||
unsupported("queryRealisation");
|
unsupported("queryRealisation");
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ private:
|
||||||
* Check lower store if upper DB does not have.
|
* Check lower store if upper DB does not have.
|
||||||
*/
|
*/
|
||||||
void queryRealisationUncached(
|
void queryRealisationUncached(
|
||||||
const DrvOutput &, Callback<std::shared_ptr<const Realisation>> callback) noexcept override;
|
const DrvOutput &, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call `remountIfNecessary` after collecting garbage normally.
|
* Call `remountIfNecessary` after collecting garbage normally.
|
||||||
|
|
|
||||||
|
|
@ -385,10 +385,10 @@ public:
|
||||||
void cacheDrvOutputMapping(
|
void cacheDrvOutputMapping(
|
||||||
State & state, const uint64_t deriver, const std::string & outputName, const StorePath & output);
|
State & state, const uint64_t deriver, const std::string & outputName, const StorePath & output);
|
||||||
|
|
||||||
std::optional<const Realisation> queryRealisation_(State & state, const DrvOutput & id);
|
std::optional<const UnkeyedRealisation> queryRealisation_(State & state, const DrvOutput & id);
|
||||||
std::optional<std::pair<int64_t, Realisation>> queryRealisationCore_(State & state, const DrvOutput & id);
|
std::optional<std::pair<int64_t, UnkeyedRealisation>> queryRealisationCore_(State & state, const DrvOutput & id);
|
||||||
void queryRealisationUncached(
|
void queryRealisationUncached(
|
||||||
const DrvOutput &, Callback<std::shared_ptr<const Realisation>> callback) noexcept override;
|
const DrvOutput &, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept override;
|
||||||
|
|
||||||
std::optional<std::string> getVersion() override;
|
std::optional<std::string> getVersion() override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,12 +46,12 @@ struct DrvOutput
|
||||||
|
|
||||||
static DrvOutput parse(const std::string &);
|
static DrvOutput parse(const std::string &);
|
||||||
|
|
||||||
GENERATE_CMP(DrvOutput, me->drvHash, me->outputName);
|
bool operator==(const DrvOutput &) const = default;
|
||||||
|
auto operator<=>(const DrvOutput &) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Realisation
|
struct UnkeyedRealisation
|
||||||
{
|
{
|
||||||
DrvOutput id;
|
|
||||||
StorePath outPath;
|
StorePath outPath;
|
||||||
|
|
||||||
StringSet signatures;
|
StringSet signatures;
|
||||||
|
|
@ -64,22 +64,35 @@ struct Realisation
|
||||||
*/
|
*/
|
||||||
std::map<DrvOutput, StorePath> dependentRealisations;
|
std::map<DrvOutput, StorePath> dependentRealisations;
|
||||||
|
|
||||||
std::string fingerprint() const;
|
std::string fingerprint(const DrvOutput & key) const;
|
||||||
void sign(const Signer &);
|
|
||||||
bool checkSignature(const PublicKeys & publicKeys, const std::string & sig) const;
|
|
||||||
size_t checkSignatures(const PublicKeys & publicKeys) const;
|
|
||||||
|
|
||||||
static std::set<Realisation> closure(Store &, const std::set<Realisation> &);
|
void sign(const DrvOutput & key, const Signer &);
|
||||||
static void closure(Store &, const std::set<Realisation> &, std::set<Realisation> & res);
|
|
||||||
|
|
||||||
bool isCompatibleWith(const Realisation & other) const;
|
bool checkSignature(const DrvOutput & key, const PublicKeys & publicKeys, const std::string & sig) const;
|
||||||
|
|
||||||
StorePath getPath() const
|
size_t checkSignatures(const DrvOutput & key, const PublicKeys & publicKeys) const;
|
||||||
|
|
||||||
|
const StorePath & getPath() const
|
||||||
{
|
{
|
||||||
return outPath;
|
return outPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
GENERATE_CMP(Realisation, me->id, me->outPath);
|
// TODO sketchy that it avoids signatures
|
||||||
|
GENERATE_CMP(UnkeyedRealisation, me->outPath);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Realisation : UnkeyedRealisation
|
||||||
|
{
|
||||||
|
DrvOutput id;
|
||||||
|
|
||||||
|
bool isCompatibleWith(const UnkeyedRealisation & other) const;
|
||||||
|
|
||||||
|
static std::set<Realisation> closure(Store &, const std::set<Realisation> &);
|
||||||
|
|
||||||
|
static void closure(Store &, const std::set<Realisation> &, std::set<Realisation> & res);
|
||||||
|
|
||||||
|
bool operator==(const Realisation &) const = default;
|
||||||
|
auto operator<=>(const Realisation &) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -103,12 +116,13 @@ struct OpaquePath
|
||||||
{
|
{
|
||||||
StorePath path;
|
StorePath path;
|
||||||
|
|
||||||
StorePath getPath() const
|
const StorePath & getPath() const &
|
||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
GENERATE_CMP(OpaquePath, me->path);
|
bool operator==(const OpaquePath &) const = default;
|
||||||
|
auto operator<=>(const OpaquePath &) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -116,7 +130,7 @@ struct OpaquePath
|
||||||
*/
|
*/
|
||||||
struct RealisedPath
|
struct RealisedPath
|
||||||
{
|
{
|
||||||
/*
|
/**
|
||||||
* A path is either the result of the realisation of a derivation or
|
* A path is either the result of the realisation of a derivation or
|
||||||
* an opaque blob that has been directly added to the store
|
* an opaque blob that has been directly added to the store
|
||||||
*/
|
*/
|
||||||
|
|
@ -138,13 +152,14 @@ struct RealisedPath
|
||||||
/**
|
/**
|
||||||
* Get the raw store path associated to this
|
* Get the raw store path associated to this
|
||||||
*/
|
*/
|
||||||
StorePath path() const;
|
const StorePath & path() const &;
|
||||||
|
|
||||||
void closure(Store & store, Set & ret) const;
|
void closure(Store & store, Set & ret) const;
|
||||||
static void closure(Store & store, const Set & startPaths, Set & ret);
|
static void closure(Store & store, const Set & startPaths, Set & ret);
|
||||||
Set closure(Store & store) const;
|
Set closure(Store & store) const;
|
||||||
|
|
||||||
GENERATE_CMP(RealisedPath, me->raw);
|
bool operator==(const RealisedPath &) const = default;
|
||||||
|
auto operator<=>(const RealisedPath &) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MissingRealisation : public Error
|
class MissingRealisation : public Error
|
||||||
|
|
@ -167,4 +182,5 @@ public:
|
||||||
|
|
||||||
} // namespace nix
|
} // namespace nix
|
||||||
|
|
||||||
|
JSON_IMPL(nix::UnkeyedRealisation)
|
||||||
JSON_IMPL(nix::Realisation)
|
JSON_IMPL(nix::Realisation)
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ struct RemoteStore : public virtual Store, public virtual GcStore, public virtua
|
||||||
void registerDrvOutput(const Realisation & info) override;
|
void registerDrvOutput(const Realisation & info) override;
|
||||||
|
|
||||||
void queryRealisationUncached(
|
void queryRealisationUncached(
|
||||||
const DrvOutput &, Callback<std::shared_ptr<const Realisation>> callback) noexcept override;
|
const DrvOutput &, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept override;
|
||||||
|
|
||||||
void
|
void
|
||||||
buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode, std::shared_ptr<Store> evalStore) override;
|
buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode, std::shared_ptr<Store> evalStore) override;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ MakeError(SubstituterDisabled, Error);
|
||||||
|
|
||||||
MakeError(InvalidStoreReference, Error);
|
MakeError(InvalidStoreReference, Error);
|
||||||
|
|
||||||
|
struct UnkeyedRealisation;
|
||||||
struct Realisation;
|
struct Realisation;
|
||||||
struct RealisedPath;
|
struct RealisedPath;
|
||||||
struct DrvOutput;
|
struct DrvOutput;
|
||||||
|
|
@ -398,12 +399,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* Query the information about a realisation.
|
* Query the information about a realisation.
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<const Realisation> queryRealisation(const DrvOutput &);
|
std::shared_ptr<const UnkeyedRealisation> queryRealisation(const DrvOutput &);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronous version of queryRealisation().
|
* Asynchronous version of queryRealisation().
|
||||||
*/
|
*/
|
||||||
void queryRealisation(const DrvOutput &, Callback<std::shared_ptr<const Realisation>> callback) noexcept;
|
void queryRealisation(const DrvOutput &, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the given valid path info is sufficiently attested, by
|
* Check whether the given valid path info is sufficiently attested, by
|
||||||
|
|
@ -430,8 +431,8 @@ protected:
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
queryPathInfoUncached(const StorePath & path, Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept = 0;
|
queryPathInfoUncached(const StorePath & path, Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept = 0;
|
||||||
virtual void
|
virtual void queryRealisationUncached(
|
||||||
queryRealisationUncached(const DrvOutput &, Callback<std::shared_ptr<const Realisation>> callback) noexcept = 0;
|
const DrvOutput &, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ void LocalOverlayStore::registerDrvOutput(const Realisation & info)
|
||||||
// First do queryRealisation on lower layer to populate DB
|
// First do queryRealisation on lower layer to populate DB
|
||||||
auto res = lowerStore->queryRealisation(info.id);
|
auto res = lowerStore->queryRealisation(info.id);
|
||||||
if (res)
|
if (res)
|
||||||
LocalStore::registerDrvOutput(*res);
|
LocalStore::registerDrvOutput({*res, info.id});
|
||||||
|
|
||||||
LocalStore::registerDrvOutput(info);
|
LocalStore::registerDrvOutput(info);
|
||||||
}
|
}
|
||||||
|
|
@ -108,12 +108,12 @@ void LocalOverlayStore::queryPathInfoUncached(
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalOverlayStore::queryRealisationUncached(
|
void LocalOverlayStore::queryRealisationUncached(
|
||||||
const DrvOutput & drvOutput, Callback<std::shared_ptr<const Realisation>> callback) noexcept
|
const DrvOutput & drvOutput, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept
|
||||||
{
|
{
|
||||||
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));
|
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));
|
||||||
|
|
||||||
LocalStore::queryRealisationUncached(
|
LocalStore::queryRealisationUncached(
|
||||||
drvOutput, {[this, drvOutput, callbackPtr](std::future<std::shared_ptr<const Realisation>> fut) {
|
drvOutput, {[this, drvOutput, callbackPtr](std::future<std::shared_ptr<const UnkeyedRealisation>> fut) {
|
||||||
try {
|
try {
|
||||||
auto info = fut.get();
|
auto info = fut.get();
|
||||||
if (info)
|
if (info)
|
||||||
|
|
@ -123,7 +123,7 @@ void LocalOverlayStore::queryRealisationUncached(
|
||||||
}
|
}
|
||||||
// If we don't have it, check lower store
|
// If we don't have it, check lower store
|
||||||
lowerStore->queryRealisation(
|
lowerStore->queryRealisation(
|
||||||
drvOutput, {[callbackPtr](std::future<std::shared_ptr<const Realisation>> fut) {
|
drvOutput, {[callbackPtr](std::future<std::shared_ptr<const UnkeyedRealisation>> fut) {
|
||||||
try {
|
try {
|
||||||
(*callbackPtr)(fut.get());
|
(*callbackPtr)(fut.get());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
|
||||||
|
|
@ -1036,7 +1036,7 @@ bool LocalStore::pathInfoIsUntrusted(const ValidPathInfo & info)
|
||||||
|
|
||||||
bool LocalStore::realisationIsUntrusted(const Realisation & realisation)
|
bool LocalStore::realisationIsUntrusted(const Realisation & realisation)
|
||||||
{
|
{
|
||||||
return config->requireSigs && !realisation.checkSignatures(getPublicKeys());
|
return config->requireSigs && !realisation.checkSignatures(realisation.id, getPublicKeys());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalStore::addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs)
|
void LocalStore::addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs)
|
||||||
|
|
@ -1586,7 +1586,7 @@ void LocalStore::addSignatures(const StorePath & storePath, const StringSet & si
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::pair<int64_t, Realisation>>
|
std::optional<std::pair<int64_t, UnkeyedRealisation>>
|
||||||
LocalStore::queryRealisationCore_(LocalStore::State & state, const DrvOutput & id)
|
LocalStore::queryRealisationCore_(LocalStore::State & state, const DrvOutput & id)
|
||||||
{
|
{
|
||||||
auto useQueryRealisedOutput(state.stmts->QueryRealisedOutput.use()(id.strHash())(id.outputName));
|
auto useQueryRealisedOutput(state.stmts->QueryRealisedOutput.use()(id.strHash())(id.outputName));
|
||||||
|
|
@ -1598,14 +1598,13 @@ LocalStore::queryRealisationCore_(LocalStore::State & state, const DrvOutput & i
|
||||||
|
|
||||||
return {
|
return {
|
||||||
{realisationDbId,
|
{realisationDbId,
|
||||||
Realisation{
|
UnkeyedRealisation{
|
||||||
.id = id,
|
|
||||||
.outPath = outputPath,
|
.outPath = outputPath,
|
||||||
.signatures = signatures,
|
.signatures = signatures,
|
||||||
}}};
|
}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<const Realisation> LocalStore::queryRealisation_(LocalStore::State & state, const DrvOutput & id)
|
std::optional<const UnkeyedRealisation> LocalStore::queryRealisation_(LocalStore::State & state, const DrvOutput & id)
|
||||||
{
|
{
|
||||||
auto maybeCore = queryRealisationCore_(state, id);
|
auto maybeCore = queryRealisationCore_(state, id);
|
||||||
if (!maybeCore)
|
if (!maybeCore)
|
||||||
|
|
@ -1631,13 +1630,13 @@ std::optional<const Realisation> LocalStore::queryRealisation_(LocalStore::State
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalStore::queryRealisationUncached(
|
void LocalStore::queryRealisationUncached(
|
||||||
const DrvOutput & id, Callback<std::shared_ptr<const Realisation>> callback) noexcept
|
const DrvOutput & id, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
auto maybeRealisation =
|
auto maybeRealisation = retrySQLite<std::optional<const UnkeyedRealisation>>(
|
||||||
retrySQLite<std::optional<const Realisation>>([&]() { return queryRealisation_(*_state->lock(), id); });
|
[&]() { return queryRealisation_(*_state->lock(), id); });
|
||||||
if (maybeRealisation)
|
if (maybeRealisation)
|
||||||
callback(std::make_shared<const Realisation>(maybeRealisation.value()));
|
callback(std::make_shared<const UnkeyedRealisation>(maybeRealisation.value()));
|
||||||
else
|
else
|
||||||
callback(nullptr);
|
callback(nullptr);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -360,11 +360,12 @@ drvOutputReferences(Store & store, const Derivation & drv, const StorePath & out
|
||||||
if (!outputHash)
|
if (!outputHash)
|
||||||
throw Error(
|
throw Error(
|
||||||
"output '%s' of derivation '%s' isn't realised", outputName, store.printStorePath(inputDrv));
|
"output '%s' of derivation '%s' isn't realised", outputName, store.printStorePath(inputDrv));
|
||||||
auto thisRealisation = store.queryRealisation(DrvOutput{*outputHash, outputName});
|
DrvOutput key{*outputHash, outputName};
|
||||||
|
auto thisRealisation = store.queryRealisation(key);
|
||||||
if (!thisRealisation)
|
if (!thisRealisation)
|
||||||
throw Error(
|
throw Error(
|
||||||
"output '%s' of derivation '%s' isn’t built", outputName, store.printStorePath(inputDrv));
|
"output '%s' of derivation '%s' isn’t built", outputName, store.printStorePath(inputDrv));
|
||||||
inputRealisations.insert(*thisRealisation);
|
inputRealisations.insert({*thisRealisation, std::move(key)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!inputNode.value.empty()) {
|
if (!inputNode.value.empty()) {
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ void Realisation::closure(Store & store, const std::set<Realisation> & startOutp
|
||||||
std::set<Realisation> res;
|
std::set<Realisation> res;
|
||||||
for (auto & [currentDep, _] : current.dependentRealisations) {
|
for (auto & [currentDep, _] : current.dependentRealisations) {
|
||||||
if (auto currentRealisation = store.queryRealisation(currentDep))
|
if (auto currentRealisation = store.queryRealisation(currentDep))
|
||||||
res.insert(*currentRealisation);
|
res.insert({*currentRealisation, currentDep});
|
||||||
else
|
else
|
||||||
throw Error("Unrealised derivation '%s'", currentDep.to_string());
|
throw Error("Unrealised derivation '%s'", currentDep.to_string());
|
||||||
}
|
}
|
||||||
|
|
@ -61,24 +61,25 @@ void Realisation::closure(Store & store, const std::set<Realisation> & startOutp
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Realisation::fingerprint() const
|
std::string UnkeyedRealisation::fingerprint(const DrvOutput & key) const
|
||||||
{
|
{
|
||||||
nlohmann::json serialized = *this;
|
nlohmann::json serialized = Realisation{*this, key};
|
||||||
serialized.erase("signatures");
|
serialized.erase("signatures");
|
||||||
return serialized.dump();
|
return serialized.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Realisation::sign(const Signer & signer)
|
void UnkeyedRealisation::sign(const DrvOutput & key, const Signer & signer)
|
||||||
{
|
{
|
||||||
signatures.insert(signer.signDetached(fingerprint()));
|
signatures.insert(signer.signDetached(fingerprint(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Realisation::checkSignature(const PublicKeys & publicKeys, const std::string & sig) const
|
bool UnkeyedRealisation::checkSignature(
|
||||||
|
const DrvOutput & key, const PublicKeys & publicKeys, const std::string & sig) const
|
||||||
{
|
{
|
||||||
return verifyDetached(fingerprint(), sig, publicKeys);
|
return verifyDetached(fingerprint(key), sig, publicKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Realisation::checkSignatures(const PublicKeys & publicKeys) const
|
size_t UnkeyedRealisation::checkSignatures(const DrvOutput & key, const PublicKeys & publicKeys) const
|
||||||
{
|
{
|
||||||
// FIXME: Maybe we should return `maxSigs` if the realisation corresponds to
|
// FIXME: Maybe we should return `maxSigs` if the realisation corresponds to
|
||||||
// an input-addressed one − because in that case the drv is enough to check
|
// an input-addressed one − because in that case the drv is enough to check
|
||||||
|
|
@ -86,19 +87,18 @@ size_t Realisation::checkSignatures(const PublicKeys & publicKeys) const
|
||||||
|
|
||||||
size_t good = 0;
|
size_t good = 0;
|
||||||
for (auto & sig : signatures)
|
for (auto & sig : signatures)
|
||||||
if (checkSignature(publicKeys, sig))
|
if (checkSignature(key, publicKeys, sig))
|
||||||
good++;
|
good++;
|
||||||
return good;
|
return good;
|
||||||
}
|
}
|
||||||
|
|
||||||
StorePath RealisedPath::path() const
|
const StorePath & RealisedPath::path() const &
|
||||||
{
|
{
|
||||||
return std::visit([](auto && arg) { return arg.getPath(); }, raw);
|
return std::visit([](auto & arg) -> auto & { return arg.getPath(); }, raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Realisation::isCompatibleWith(const Realisation & other) const
|
bool Realisation::isCompatibleWith(const UnkeyedRealisation & other) const
|
||||||
{
|
{
|
||||||
assert(id == other.id);
|
|
||||||
if (outPath == other.outPath) {
|
if (outPath == other.outPath) {
|
||||||
if (dependentRealisations.empty() != other.dependentRealisations.empty()) {
|
if (dependentRealisations.empty() != other.dependentRealisations.empty()) {
|
||||||
warn(
|
warn(
|
||||||
|
|
@ -144,7 +144,7 @@ namespace nlohmann {
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
Realisation adl_serializer<Realisation>::from_json(const json & json0)
|
UnkeyedRealisation adl_serializer<UnkeyedRealisation>::from_json(const json & json0)
|
||||||
{
|
{
|
||||||
auto json = getObject(json0);
|
auto json = getObject(json0);
|
||||||
|
|
||||||
|
|
@ -157,25 +157,39 @@ Realisation adl_serializer<Realisation>::from_json(const json & json0)
|
||||||
for (auto & [jsonDepId, jsonDepOutPath] : getObject(*jsonDependencies))
|
for (auto & [jsonDepId, jsonDepOutPath] : getObject(*jsonDependencies))
|
||||||
dependentRealisations.insert({DrvOutput::parse(jsonDepId), jsonDepOutPath});
|
dependentRealisations.insert({DrvOutput::parse(jsonDepId), jsonDepOutPath});
|
||||||
|
|
||||||
return Realisation{
|
return UnkeyedRealisation{
|
||||||
.id = DrvOutput::parse(valueAt(json, "id")),
|
|
||||||
.outPath = valueAt(json, "outPath"),
|
.outPath = valueAt(json, "outPath"),
|
||||||
.signatures = signatures,
|
.signatures = signatures,
|
||||||
.dependentRealisations = dependentRealisations,
|
.dependentRealisations = dependentRealisations,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void adl_serializer<Realisation>::to_json(json & json, const Realisation & r)
|
void adl_serializer<UnkeyedRealisation>::to_json(json & json, const UnkeyedRealisation & r)
|
||||||
{
|
{
|
||||||
auto jsonDependentRealisations = nlohmann::json::object();
|
auto jsonDependentRealisations = nlohmann::json::object();
|
||||||
for (auto & [depId, depOutPath] : r.dependentRealisations)
|
for (auto & [depId, depOutPath] : r.dependentRealisations)
|
||||||
jsonDependentRealisations.emplace(depId.to_string(), depOutPath);
|
jsonDependentRealisations.emplace(depId.to_string(), depOutPath);
|
||||||
json = {
|
json = {
|
||||||
{"id", r.id.to_string()},
|
|
||||||
{"outPath", r.outPath},
|
{"outPath", r.outPath},
|
||||||
{"signatures", r.signatures},
|
{"signatures", r.signatures},
|
||||||
{"dependentRealisations", jsonDependentRealisations},
|
{"dependentRealisations", jsonDependentRealisations},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Realisation adl_serializer<Realisation>::from_json(const json & json0)
|
||||||
|
{
|
||||||
|
auto json = getObject(json0);
|
||||||
|
|
||||||
|
return Realisation{
|
||||||
|
static_cast<UnkeyedRealisation>(json0),
|
||||||
|
DrvOutput::parse(valueAt(json, "id")),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void adl_serializer<Realisation>::to_json(json & json, const Realisation & r)
|
||||||
|
{
|
||||||
|
json = static_cast<const UnkeyedRealisation &>(r);
|
||||||
|
json["id"] = r.id.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
||||||
|
|
|
||||||
|
|
@ -501,7 +501,7 @@ void RemoteStore::registerDrvOutput(const Realisation & info)
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteStore::queryRealisationUncached(
|
void RemoteStore::queryRealisationUncached(
|
||||||
const DrvOutput & id, Callback<std::shared_ptr<const Realisation>> callback) noexcept
|
const DrvOutput & id, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
auto conn(getConnection());
|
auto conn(getConnection());
|
||||||
|
|
@ -515,21 +515,21 @@ void RemoteStore::queryRealisationUncached(
|
||||||
conn->to << id.to_string();
|
conn->to << id.to_string();
|
||||||
conn.processStderr();
|
conn.processStderr();
|
||||||
|
|
||||||
auto real = [&]() -> std::shared_ptr<const Realisation> {
|
auto real = [&]() -> std::shared_ptr<const UnkeyedRealisation> {
|
||||||
if (GET_PROTOCOL_MINOR(conn->protoVersion) < 31) {
|
if (GET_PROTOCOL_MINOR(conn->protoVersion) < 31) {
|
||||||
auto outPaths = WorkerProto::Serialise<std::set<StorePath>>::read(*this, *conn);
|
auto outPaths = WorkerProto::Serialise<std::set<StorePath>>::read(*this, *conn);
|
||||||
if (outPaths.empty())
|
if (outPaths.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return std::make_shared<const Realisation>(Realisation{.id = id, .outPath = *outPaths.begin()});
|
return std::make_shared<const UnkeyedRealisation>(UnkeyedRealisation{.outPath = *outPaths.begin()});
|
||||||
} else {
|
} else {
|
||||||
auto realisations = WorkerProto::Serialise<std::set<Realisation>>::read(*this, *conn);
|
auto realisations = WorkerProto::Serialise<std::set<Realisation>>::read(*this, *conn);
|
||||||
if (realisations.empty())
|
if (realisations.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return std::make_shared<const Realisation>(*realisations.begin());
|
return std::make_shared<const UnkeyedRealisation>(*realisations.begin());
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
callback(std::shared_ptr<const Realisation>(real));
|
callback(std::shared_ptr<const UnkeyedRealisation>(real));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return callback.rethrow();
|
return callback.rethrow();
|
||||||
}
|
}
|
||||||
|
|
@ -626,13 +626,15 @@ std::vector<KeyedBuildResult> RemoteStore::buildPathsWithResults(
|
||||||
auto realisation = queryRealisation(outputId);
|
auto realisation = queryRealisation(outputId);
|
||||||
if (!realisation)
|
if (!realisation)
|
||||||
throw MissingRealisation(outputId);
|
throw MissingRealisation(outputId);
|
||||||
success.builtOutputs.emplace(output, *realisation);
|
success.builtOutputs.emplace(output, Realisation{*realisation, outputId});
|
||||||
} else {
|
} else {
|
||||||
success.builtOutputs.emplace(
|
success.builtOutputs.emplace(
|
||||||
output,
|
output,
|
||||||
Realisation{
|
Realisation{
|
||||||
.id = outputId,
|
UnkeyedRealisation{
|
||||||
.outPath = outputPath,
|
.outPath = outputPath,
|
||||||
|
},
|
||||||
|
outputId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ struct RestrictedStore : public virtual IndirectRootStore, public virtual GcStor
|
||||||
void registerDrvOutput(const Realisation & info) override;
|
void registerDrvOutput(const Realisation & info) override;
|
||||||
|
|
||||||
void queryRealisationUncached(
|
void queryRealisationUncached(
|
||||||
const DrvOutput & id, Callback<std::shared_ptr<const Realisation>> callback) noexcept override;
|
const DrvOutput & id, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept override;
|
||||||
|
|
||||||
void
|
void
|
||||||
buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode, std::shared_ptr<Store> evalStore) override;
|
buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode, std::shared_ptr<Store> evalStore) override;
|
||||||
|
|
@ -244,7 +244,7 @@ void RestrictedStore::registerDrvOutput(const Realisation & info)
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestrictedStore::queryRealisationUncached(
|
void RestrictedStore::queryRealisationUncached(
|
||||||
const DrvOutput & id, Callback<std::shared_ptr<const Realisation>> callback) noexcept
|
const DrvOutput & id, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept
|
||||||
// XXX: This should probably be allowed if the realisation corresponds to
|
// XXX: This should probably be allowed if the realisation corresponds to
|
||||||
// an allowed derivation
|
// an allowed derivation
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -598,7 +598,8 @@ void Store::queryPathInfo(const StorePath & storePath, Callback<ref<const ValidP
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Store::queryRealisation(const DrvOutput & id, Callback<std::shared_ptr<const Realisation>> callback) noexcept
|
void Store::queryRealisation(
|
||||||
|
const DrvOutput & id, Callback<std::shared_ptr<const UnkeyedRealisation>> callback) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -624,20 +625,20 @@ void Store::queryRealisation(const DrvOutput & id, Callback<std::shared_ptr<cons
|
||||||
|
|
||||||
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));
|
auto callbackPtr = std::make_shared<decltype(callback)>(std::move(callback));
|
||||||
|
|
||||||
queryRealisationUncached(id, {[this, id, callbackPtr](std::future<std::shared_ptr<const Realisation>> fut) {
|
queryRealisationUncached(id, {[this, id, callbackPtr](std::future<std::shared_ptr<const UnkeyedRealisation>> fut) {
|
||||||
try {
|
try {
|
||||||
auto info = fut.get();
|
auto info = fut.get();
|
||||||
|
|
||||||
if (diskCache) {
|
if (diskCache) {
|
||||||
if (info)
|
if (info)
|
||||||
diskCache->upsertRealisation(
|
diskCache->upsertRealisation(
|
||||||
config.getReference().render(/*FIXME withParams=*/false), *info);
|
config.getReference().render(/*FIXME withParams=*/false), {*info, id});
|
||||||
else
|
else
|
||||||
diskCache->upsertAbsentRealisation(
|
diskCache->upsertAbsentRealisation(
|
||||||
config.getReference().render(/*FIXME withParams=*/false), id);
|
config.getReference().render(/*FIXME withParams=*/false), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
(*callbackPtr)(std::shared_ptr<const Realisation>(info));
|
(*callbackPtr)(std::shared_ptr<const UnkeyedRealisation>(info));
|
||||||
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
callbackPtr->rethrow();
|
callbackPtr->rethrow();
|
||||||
|
|
@ -645,9 +646,9 @@ void Store::queryRealisation(const DrvOutput & id, Callback<std::shared_ptr<cons
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const Realisation> Store::queryRealisation(const DrvOutput & id)
|
std::shared_ptr<const UnkeyedRealisation> Store::queryRealisation(const DrvOutput & id)
|
||||||
{
|
{
|
||||||
using RealPtr = std::shared_ptr<const Realisation>;
|
using RealPtr = std::shared_ptr<const UnkeyedRealisation>;
|
||||||
std::promise<RealPtr> promise;
|
std::promise<RealPtr> promise;
|
||||||
|
|
||||||
queryRealisation(id, {[&](std::future<RealPtr> result) {
|
queryRealisation(id, {[&](std::future<RealPtr> result) {
|
||||||
|
|
@ -910,11 +911,12 @@ std::map<StorePath, StorePath> copyPaths(
|
||||||
std::set<Realisation> toplevelRealisations;
|
std::set<Realisation> toplevelRealisations;
|
||||||
for (auto & path : paths) {
|
for (auto & path : paths) {
|
||||||
storePaths.insert(path.path());
|
storePaths.insert(path.path());
|
||||||
if (auto realisation = std::get_if<Realisation>(&path.raw)) {
|
if (auto * realisation = std::get_if<Realisation>(&path.raw)) {
|
||||||
experimentalFeatureSettings.require(Xp::CaDerivations);
|
experimentalFeatureSettings.require(Xp::CaDerivations);
|
||||||
toplevelRealisations.insert(*realisation);
|
toplevelRealisations.insert(*realisation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pathsMap = copyPaths(srcStore, dstStore, storePaths, repair, checkSigs, substitute);
|
auto pathsMap = copyPaths(srcStore, dstStore, storePaths, repair, checkSigs, substitute);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -931,7 +933,7 @@ std::map<StorePath, StorePath> copyPaths(
|
||||||
"dependency of '%s' but isn't registered",
|
"dependency of '%s' but isn't registered",
|
||||||
drvOutput.to_string(),
|
drvOutput.to_string(),
|
||||||
current.id.to_string());
|
current.id.to_string());
|
||||||
children.insert(*currentChild);
|
children.insert({*currentChild, drvOutput});
|
||||||
}
|
}
|
||||||
return children;
|
return children;
|
||||||
},
|
},
|
||||||
|
|
@ -1199,7 +1201,7 @@ void Store::signRealisation(Realisation & realisation)
|
||||||
for (auto & secretKeyFile : secretKeyFiles.get()) {
|
for (auto & secretKeyFile : secretKeyFiles.get()) {
|
||||||
SecretKey secretKey(readFile(secretKeyFile));
|
SecretKey secretKey(readFile(secretKeyFile));
|
||||||
LocalSigner signer(std::move(secretKey));
|
LocalSigner signer(std::move(secretKey));
|
||||||
realisation.sign(signer);
|
realisation.sign(realisation.id, signer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1866,7 +1866,12 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
|
||||||
for (auto & [outputName, newInfo] : infos) {
|
for (auto & [outputName, newInfo] : infos) {
|
||||||
auto oldinfo = get(initialOutputs, outputName);
|
auto oldinfo = get(initialOutputs, outputName);
|
||||||
assert(oldinfo);
|
assert(oldinfo);
|
||||||
auto thisRealisation = Realisation{.id = DrvOutput{oldinfo->outputHash, outputName}, .outPath = newInfo.path};
|
auto thisRealisation = Realisation{
|
||||||
|
{
|
||||||
|
.outPath = newInfo.path,
|
||||||
|
},
|
||||||
|
DrvOutput{oldinfo->outputHash, outputName},
|
||||||
|
};
|
||||||
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations) && !drv.type().isImpure()) {
|
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations) && !drv.type().isImpure()) {
|
||||||
store.signRealisation(thisRealisation);
|
store.signRealisation(thisRealisation);
|
||||||
store.registerDrvOutput(thisRealisation);
|
store.registerDrvOutput(thisRealisation);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue