Skip to content

Commit dbc9423

Browse files
committed
nix flake prefetch-inputs: Add
This command fetches all inputs of a flake in parallel. Example runtime for $ chmod -R u+w /tmp/nix2; rm -rf /tmp/nix2; rm ~/.cache/nix/fetcher-cache-v3.sqlite*; rm -rf ~/.cache/nix/tarball-cache/ ~/.cache/nix/gitv3/; time nix flake prefetch-inputs --store /tmp/nix2 https://api.flakehub.com/f/pinned/informalsystems/cosmos.nix/0.3.0/018ce9ed-d0be-7ce5-81b6-a3c6e3ae1187/source.tar.gz with http-connections = 1: real 4m11.859s user 2m6.931s sys 0m25.619s and http-connections = 25 (the default): real 0m57.146s user 2m49.506s sys 0m36.008s
1 parent a66d268 commit dbc9423

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

src/nix/flake-prefetch-inputs.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
R""(
2+
3+
# Examples
4+
5+
* Fetch the inputs of the `hydra` flake:
6+
7+
```console
8+
# nix flake prefetch-inputs github:NixOS/hydra
9+
```
10+
11+
# Description
12+
13+
Fetch the inputs of a flake. This ensures that they are already available for any subsequent evaluation of the flake.
14+
15+
This operation is recursive: it will fetch not just the direct inputs of the top-level flake, but also transitive inputs.
16+
17+
)""

src/nix/flake.cc

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "nix/fetchers/fetch-to-store.hh"
2121
#include "nix/store/local-fs-store.hh"
2222
#include "nix/expr/parallel-eval.hh"
23+
#include "nix/util/thread-pool.hh"
24+
#include "nix/store/filetransfer.hh"
2325

2426
#include <filesystem>
2527
#include <nlohmann/json.hpp>
@@ -1148,6 +1150,59 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun
11481150
}
11491151
};
11501152

1153+
struct CmdFlakePrefetchInputs : FlakeCommand
1154+
{
1155+
std::string description() override
1156+
{
1157+
return "fetch the inputs of a flake";
1158+
}
1159+
1160+
std::string doc() override
1161+
{
1162+
return
1163+
#include "flake-prefetch-inputs.md"
1164+
;
1165+
}
1166+
1167+
void run(nix::ref<nix::Store> store) override
1168+
{
1169+
auto flake = lockFlake();
1170+
1171+
ThreadPool pool{fileTransferSettings.httpConnections};
1172+
1173+
struct State
1174+
{
1175+
std::set<const Node *> done;
1176+
};
1177+
1178+
Sync<State> state_;
1179+
1180+
std::function<void(const Node & node)> visit;
1181+
visit = [&](const Node & node)
1182+
{
1183+
if (!state_.lock()->done.insert(&node).second)
1184+
return;
1185+
1186+
if (auto lockedNode = dynamic_cast<const LockedNode *>(&node)) {
1187+
Activity act(*logger, lvlInfo, actUnknown,
1188+
fmt("fetching '%s'", lockedNode->lockedRef));
1189+
auto accessor = lockedNode->lockedRef.input.getAccessor(store).first;
1190+
if (!evalSettings.lazyTrees)
1191+
fetchToStore(*store, accessor, FetchMode::Copy, lockedNode->lockedRef.input.getName());
1192+
}
1193+
1194+
for (auto & [inputName, input] : node.inputs) {
1195+
if (auto inputNode = std::get_if<0>(&input))
1196+
pool.enqueue(std::bind(visit, **inputNode));
1197+
}
1198+
};
1199+
1200+
pool.enqueue(std::bind(visit, *flake.lockFile.root));
1201+
1202+
pool.process();
1203+
}
1204+
};
1205+
11511206
struct CmdFlakeShow : FlakeCommand, MixJSON
11521207
{
11531208
bool showLegacy = false;
@@ -1503,6 +1558,7 @@ struct CmdFlake : NixMultiCommand
15031558
{"new", []() { return make_ref<CmdFlakeNew>(); }},
15041559
{"clone", []() { return make_ref<CmdFlakeClone>(); }},
15051560
{"archive", []() { return make_ref<CmdFlakeArchive>(); }},
1561+
{"prefetch-inputs", []() { return make_ref<CmdFlakePrefetchInputs>(); }},
15061562
{"show", []() { return make_ref<CmdFlakeShow>(); }},
15071563
{"prefetch", []() { return make_ref<CmdFlakePrefetch>(); }},
15081564
})

0 commit comments

Comments
 (0)