Add 'nix flake archive' command
This copies a flake and all its inputs recursively to a store (e.g. a binary cache). This is intended to enable long-term reproducibility for flakes. However this will also require #3253. Example: $ nix flake archive --json --to file:///tmp/my-cache nixops {"path":"/nix/store/272igzkgl1gdzmabsjvb2kb2zqbphb3p-source","inputs":{"nixops-aws":{"path":"/nix/store/ybcykw13gr7iq1pzg18iyibbcv8k9q1v-source","inputs":{}},"nixops-hetzner":{"path":"/nix/store/6yn0205x3nz55w8ms3335p2841javz2d-source","inputs":{}},"nixpkgs":{"path":"/nix/store/li3lkr2ajrzphqqz3jj2avndnyd3i5lc-source","inputs":{}}}} $ ll /tmp/my-cache total 16 -rw-r--r-- 1 eelco users 403 Jan 30 01:01 272igzkgl1gdzmabsjvb2kb2zqbphb3p.narinfo -rw-r--r-- 1 eelco users 403 Jan 30 01:01 6yn0205x3nz55w8ms3335p2841javz2d.narinfo -rw-r--r-- 1 eelco users 408 Jan 30 01:01 li3lkr2ajrzphqqz3jj2avndnyd3i5lc.narinfo drwxr-xr-x 2 eelco users 6 Jan 30 01:01 nar -rw-r--r-- 1 eelco users 21 Jan 30 01:01 nix-cache-info -rw-r--r-- 1 eelco users 404 Jan 30 01:01 ybcykw13gr7iq1pzg18iyibbcv8k9q1v.narinfo Fixes #3336.
This commit is contained in:
parent
b9f93e7386
commit
3c54e9ba01
1 changed files with 76 additions and 1 deletions
|
@ -11,6 +11,7 @@
|
||||||
#include "attr-path.hh"
|
#include "attr-path.hh"
|
||||||
#include "fetchers/fetchers.hh"
|
#include "fetchers/fetchers.hh"
|
||||||
#include "fetchers/registry.hh"
|
#include "fetchers/registry.hh"
|
||||||
|
#include "json.hh"
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
@ -213,7 +214,7 @@ struct CmdFlakeInfo : FlakeCommand, MixJSON
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmdFlakeCheck : FlakeCommand, MixJSON
|
struct CmdFlakeCheck : FlakeCommand
|
||||||
{
|
{
|
||||||
bool build = true;
|
bool build = true;
|
||||||
|
|
||||||
|
@ -604,6 +605,79 @@ struct CmdFlakeClone : FlakeCommand
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun
|
||||||
|
{
|
||||||
|
std::string dstUri;
|
||||||
|
|
||||||
|
CmdFlakeArchive()
|
||||||
|
{
|
||||||
|
mkFlag()
|
||||||
|
.longName("to")
|
||||||
|
.labels({"store-uri"})
|
||||||
|
.description("URI of the destination Nix store")
|
||||||
|
.dest(&dstUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string description() override
|
||||||
|
{
|
||||||
|
return "copy a flake and all its inputs to a store";
|
||||||
|
}
|
||||||
|
|
||||||
|
Examples examples() override
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
Example{
|
||||||
|
"To copy the dwarffs flake and its dependencies to a binary cache:",
|
||||||
|
"nix flake archive --to file:///tmp/my-cache dwarffs"
|
||||||
|
},
|
||||||
|
Example{
|
||||||
|
"To fetch the dwarffs flake and its dependencies to the local Nix store:",
|
||||||
|
"nix flake archive dwarffs"
|
||||||
|
},
|
||||||
|
Example{
|
||||||
|
"To print the store paths of the flake sources of NixOps without fetching them:",
|
||||||
|
"nix flake archive --json --dry-run nixops"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(nix::ref<nix::Store> store) override
|
||||||
|
{
|
||||||
|
auto flake = lockFlake();
|
||||||
|
|
||||||
|
auto jsonRoot = json ? std::optional<JSONObject>(std::cout) : std::optional<JSONObject>();
|
||||||
|
|
||||||
|
StorePathSet sources;
|
||||||
|
|
||||||
|
sources.insert(flake.flake.sourceInfo->storePath.clone());
|
||||||
|
if (jsonRoot)
|
||||||
|
jsonRoot->attr("path", store->printStorePath(flake.flake.sourceInfo->storePath));
|
||||||
|
|
||||||
|
std::function<void(const LockedInputs & inputs, std::optional<JSONObject> & jsonObj)> traverse;
|
||||||
|
traverse = [&](const LockedInputs & inputs, std::optional<JSONObject> & jsonObj)
|
||||||
|
{
|
||||||
|
auto jsonObj2 = jsonObj ? jsonObj->object("inputs") : std::optional<JSONObject>();
|
||||||
|
for (auto & input : inputs.inputs) {
|
||||||
|
auto jsonObj3 = jsonObj2 ? jsonObj2->object(input.first) : std::optional<JSONObject>();
|
||||||
|
if (!dryRun)
|
||||||
|
input.second.ref.input->fetchTree(store);
|
||||||
|
auto storePath = input.second.computeStorePath(*store);
|
||||||
|
if (jsonObj3)
|
||||||
|
jsonObj3->attr("path", store->printStorePath(storePath));
|
||||||
|
sources.insert(std::move(storePath));
|
||||||
|
traverse(input.second, jsonObj3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
traverse(flake.lockFile, jsonRoot);
|
||||||
|
|
||||||
|
if (!dryRun && !dstUri.empty()) {
|
||||||
|
ref<Store> dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
|
||||||
|
copyPaths(store, dstStore, sources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct CmdFlake : virtual MultiCommand, virtual Command
|
struct CmdFlake : virtual MultiCommand, virtual Command
|
||||||
{
|
{
|
||||||
CmdFlake()
|
CmdFlake()
|
||||||
|
@ -617,6 +691,7 @@ struct CmdFlake : virtual MultiCommand, virtual Command
|
||||||
{"pin", []() { return make_ref<CmdFlakePin>(); }},
|
{"pin", []() { return make_ref<CmdFlakePin>(); }},
|
||||||
{"init", []() { return make_ref<CmdFlakeInit>(); }},
|
{"init", []() { return make_ref<CmdFlakeInit>(); }},
|
||||||
{"clone", []() { return make_ref<CmdFlakeClone>(); }},
|
{"clone", []() { return make_ref<CmdFlakeClone>(); }},
|
||||||
|
{"archive", []() { return make_ref<CmdFlakeArchive>(); }},
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue