aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/make-content-addressed.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2022-03-22 21:14:58 +0100
committerEelco Dolstra <edolstra@gmail.com>2022-03-24 21:33:33 +0100
commit545c2d0d8cbac86c169a6dd049c1ed9c3913774d (patch)
treec48cc2901ca2d4a9dc618edb733c014dd8f4abb6 /src/libstore/make-content-addressed.cc
parent7f6fe8ca1d41bceef32790aa0313aa62ae2b65fb (diff)
fetchClosure: Allow a path to be rewritten to CA on the fly
The advantage is that the resulting closure doesn't need to be signed, so you don't need to configure any binary cache keys on the client.
Diffstat (limited to 'src/libstore/make-content-addressed.cc')
-rw-r--r--src/libstore/make-content-addressed.cc79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/libstore/make-content-addressed.cc b/src/libstore/make-content-addressed.cc
new file mode 100644
index 000000000..0b95ff37c
--- /dev/null
+++ b/src/libstore/make-content-addressed.cc
@@ -0,0 +1,79 @@
+#include "make-content-addressed.hh"
+#include "references.hh"
+
+namespace nix {
+
+std::map<StorePath, StorePath> makeContentAddressed(
+ Store & srcStore,
+ Store & dstStore,
+ const StorePathSet & storePaths)
+{
+ // FIXME: use closure of storePaths.
+
+ auto paths = srcStore.topoSortPaths(storePaths);
+
+ std::reverse(paths.begin(), paths.end());
+
+ std::map<StorePath, StorePath> remappings;
+
+ for (auto & path : paths) {
+ auto pathS = srcStore.printStorePath(path);
+ auto oldInfo = srcStore.queryPathInfo(path);
+ std::string oldHashPart(path.hashPart());
+
+ StringSink sink;
+ srcStore.narFromPath(path, sink);
+
+ StringMap rewrites;
+
+ StorePathSet references;
+ bool hasSelfReference = false;
+ for (auto & ref : oldInfo->references) {
+ if (ref == path)
+ hasSelfReference = true;
+ else {
+ auto i = remappings.find(ref);
+ auto replacement = i != remappings.end() ? i->second : ref;
+ // FIXME: warn about unremapped paths?
+ if (replacement != ref)
+ rewrites.insert_or_assign(srcStore.printStorePath(ref), srcStore.printStorePath(replacement));
+ references.insert(std::move(replacement));
+ }
+ }
+
+ sink.s = rewriteStrings(sink.s, rewrites);
+
+ HashModuloSink hashModuloSink(htSHA256, oldHashPart);
+ hashModuloSink(sink.s);
+
+ auto narHash = hashModuloSink.finish().first;
+
+ ValidPathInfo info {
+ dstStore.makeFixedOutputPath(FileIngestionMethod::Recursive, narHash, path.name(), references, hasSelfReference),
+ narHash,
+ };
+ info.references = std::move(references);
+ if (hasSelfReference) info.references.insert(info.path);
+ info.narSize = sink.s.size();
+ info.ca = FixedOutputHash {
+ .method = FileIngestionMethod::Recursive,
+ .hash = info.narHash,
+ };
+
+ printInfo("rewrote '%s' to '%s'", pathS, srcStore.printStorePath(info.path));
+
+ auto source = sinkToSource([&](Sink & nextSink) {
+ RewritingSink rsink2(oldHashPart, std::string(info.path.hashPart()), nextSink);
+ rsink2(sink.s);
+ rsink2.flush();
+ });
+
+ dstStore.addToStore(info, *source);
+
+ remappings.insert_or_assign(std::move(path), std::move(info.path));
+ }
+
+ return remappings;
+}
+
+}