From fe5b6695345bd9bfab2b34af33f87f0259c9ae28 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 9 Sep 2025 16:06:47 +0200 Subject: [PATCH] Move exportPaths() / importPaths() out of the Store class --- src/libstore/export-import.cc | 51 ++++++++++--------- .../include/nix/store/export-import.hh | 24 +++++++++ src/libstore/include/nix/store/meson.build | 1 + src/libstore/include/nix/store/store-api.hh | 20 -------- src/nix/nix-store/nix-store.cc | 5 +- src/perl/lib/Nix/Store.xs | 5 +- 6 files changed, 57 insertions(+), 49 deletions(-) create mode 100644 src/libstore/include/nix/store/export-import.hh diff --git a/src/libstore/export-import.cc b/src/libstore/export-import.cc index 13444deb2..a343b5837 100644 --- a/src/libstore/export-import.cc +++ b/src/libstore/export-import.cc @@ -1,3 +1,4 @@ +#include "nix/store/export-import.hh" #include "nix/util/serialise.hh" #include "nix/store/store-api.hh" #include "nix/util/archive.hh" @@ -8,27 +9,14 @@ namespace nix { -void Store::exportPaths(const StorePathSet & paths, Sink & sink) +static void exportPath(Store & store, const StorePath & path, Sink & sink) { - auto sorted = topoSortPaths(paths); - std::reverse(sorted.begin(), sorted.end()); - - for (auto & path : sorted) { - sink << 1; - exportPath(path, sink); - } - - sink << 0; -} - -void Store::exportPath(const StorePath & path, Sink & sink) -{ - auto info = queryPathInfo(path); + auto info = store.queryPathInfo(path); HashSink hashSink(HashAlgorithm::SHA256); TeeSink teeSink(sink, hashSink); - narFromPath(path, teeSink); + store.narFromPath(path, teeSink); /* Refuse to export paths that have changed. This prevents filesystem corruption from spreading to other machines. @@ -37,16 +25,29 @@ void Store::exportPath(const StorePath & path, Sink & sink) if (hash != info->narHash && info->narHash != Hash(info->narHash.algo)) throw Error( "hash of path '%s' has changed from '%s' to '%s'!", - printStorePath(path), + store.printStorePath(path), info->narHash.to_string(HashFormat::Nix32, true), hash.to_string(HashFormat::Nix32, true)); - teeSink << exportMagic << printStorePath(path); - CommonProto::write(*this, CommonProto::WriteConn{.to = teeSink}, info->references); - teeSink << (info->deriver ? printStorePath(*info->deriver) : "") << 0; + teeSink << exportMagic << store.printStorePath(path); + CommonProto::write(store, CommonProto::WriteConn{.to = teeSink}, info->references); + teeSink << (info->deriver ? store.printStorePath(*info->deriver) : "") << 0; } -StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs) +void exportPaths(Store & store, const StorePathSet & paths, Sink & sink) +{ + auto sorted = store.topoSortPaths(paths); + std::reverse(sorted.begin(), sorted.end()); + + for (auto & path : sorted) { + sink << 1; + exportPath(store, path, sink); + } + + sink << 0; +} + +StorePaths importPaths(Store & store, Source & source, CheckSigsFlag checkSigs) { StorePaths res; while (true) { @@ -66,17 +67,17 @@ StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs) if (magic != exportMagic) throw Error("Nix archive cannot be imported; wrong format"); - auto path = parseStorePath(readString(source)); + auto path = store.parseStorePath(readString(source)); // Activity act(*logger, lvlInfo, "importing path '%s'", info.path); - auto references = CommonProto::Serialise::read(*this, CommonProto::ReadConn{.from = source}); + auto references = CommonProto::Serialise::read(store, CommonProto::ReadConn{.from = source}); auto deriver = readString(source); auto narHash = hashString(HashAlgorithm::SHA256, saved.s); ValidPathInfo info{path, narHash}; if (deriver != "") - info.deriver = parseStorePath(deriver); + info.deriver = store.parseStorePath(deriver); info.references = references; info.narSize = saved.s.size(); @@ -86,7 +87,7 @@ StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs) // Can't use underlying source, which would have been exhausted auto source = StringSource(saved.s); - addToStore(info, source, NoRepair, checkSigs); + store.addToStore(info, source, NoRepair, checkSigs); res.push_back(info.path); } diff --git a/src/libstore/include/nix/store/export-import.hh b/src/libstore/include/nix/store/export-import.hh new file mode 100644 index 000000000..15092202f --- /dev/null +++ b/src/libstore/include/nix/store/export-import.hh @@ -0,0 +1,24 @@ +#pragma once + +#include "nix/store/store-api.hh" + +namespace nix { + +/** + * Magic header of exportPath() output (obsolete). + */ +const uint32_t exportMagic = 0x4558494e; + +/** + * Export multiple paths in the format expected by `nix-store + * --import`. The paths will be sorted topologically. + */ +void exportPaths(Store & store, const StorePathSet & paths, Sink & sink); + +/** + * Import a sequence of NAR dumps created by `exportPaths()` into the + * Nix store. + */ +StorePaths importPaths(Store & store, Source & source, CheckSigsFlag checkSigs = CheckSigs); + +} // namespace nix diff --git a/src/libstore/include/nix/store/meson.build b/src/libstore/include/nix/store/meson.build index 776c7521d..60af5ff53 100644 --- a/src/libstore/include/nix/store/meson.build +++ b/src/libstore/include/nix/store/meson.build @@ -34,6 +34,7 @@ headers = [ config_pub_h ] + files( 'derived-path-map.hh', 'derived-path.hh', 'downstream-placeholder.hh', + 'export-import.hh', 'filetransfer.hh', 'gc-store.hh', 'globals.hh', diff --git a/src/libstore/include/nix/store/store-api.hh b/src/libstore/include/nix/store/store-api.hh index dad5c9e8d..2519002b3 100644 --- a/src/libstore/include/nix/store/store-api.hh +++ b/src/libstore/include/nix/store/store-api.hh @@ -48,11 +48,6 @@ enum CheckSigsFlag : bool { NoCheckSigs = false, CheckSigs = true }; enum SubstituteFlag : bool { NoSubstitute = false, Substitute = true }; -/** - * Magic header of exportPath() output (obsolete). - */ -const uint32_t exportMagic = 0x4558494e; - enum BuildMode : uint8_t { bmNormal, bmRepair, bmCheck }; enum TrustedFlag : bool { NotTrusted = false, Trusted = true }; @@ -804,21 +799,6 @@ public: */ StorePaths topoSortPaths(const StorePathSet & paths); - /** - * Export multiple paths in the format expected by ‘nix-store - * --import’. - */ - void exportPaths(const StorePathSet & paths, Sink & sink); - - void exportPath(const StorePath & path, Sink & sink); - - /** - * Import a sequence of NAR dumps created by exportPaths() into the - * Nix store. Optionally, the contents of the NARs are preloaded - * into the specified FS accessor to speed up subsequent access. - */ - StorePaths importPaths(Source & source, CheckSigsFlag checkSigs = CheckSigs); - struct Stats { std::atomic narInfoRead{0}; diff --git a/src/nix/nix-store/nix-store.cc b/src/nix/nix-store/nix-store.cc index 3ab9b7583..5f85e06f0 100644 --- a/src/nix/nix-store/nix-store.cc +++ b/src/nix/nix-store/nix-store.cc @@ -14,6 +14,7 @@ #include "nix/util/posix-source-accessor.hh" #include "nix/store/globals.hh" #include "nix/store/path-with-outputs.hh" +#include "nix/store/export-import.hh" #include "man-pages.hh" @@ -774,7 +775,7 @@ static void opExport(Strings opFlags, Strings opArgs) paths.insert(store->followLinksToStorePath(i)); FdSink sink(getStandardOutput()); - store->exportPaths(paths, sink); + exportPaths(*store, paths, sink); sink.flush(); } @@ -787,7 +788,7 @@ static void opImport(Strings opFlags, Strings opArgs) throw UsageError("no arguments expected"); FdSource source(STDIN_FILENO); - auto paths = store->importPaths(source, NoCheckSigs); + auto paths = importPaths(*store, source, NoCheckSigs); for (auto & i : paths) cout << fmt("%s\n", store->printStorePath(i)) << std::flush; diff --git a/src/perl/lib/Nix/Store.xs b/src/perl/lib/Nix/Store.xs index edcb6d72a..7aa918ba0 100644 --- a/src/perl/lib/Nix/Store.xs +++ b/src/perl/lib/Nix/Store.xs @@ -11,6 +11,7 @@ #include "nix/store/globals.hh" #include "nix/store/store-open.hh" #include "nix/util/posix-source-accessor.hh" +#include "nix/store/export-import.hh" #include #include @@ -233,7 +234,7 @@ StoreWrapper::exportPaths(int fd, ...) StorePathSet paths; for (int n = 2; n < items; ++n) paths.insert(THIS->store->parseStorePath(SvPV_nolen(ST(n)))); FdSink sink(fd); - THIS->store->exportPaths(paths, sink); + exportPaths(*THIS->store, paths, sink); } catch (Error & e) { croak("%s", e.what()); } @@ -244,7 +245,7 @@ StoreWrapper::importPaths(int fd, int dontCheckSigs) PPCODE: try { FdSource source(fd); - THIS->store->importPaths(source, dontCheckSigs ? NoCheckSigs : CheckSigs); + importPaths(*THIS->store, source, dontCheckSigs ? NoCheckSigs : CheckSigs); } catch (Error & e) { croak("%s", e.what()); }