1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
#include "lix/libstore/make-content-addressed.hh"
#include "lix/libutil/async-io.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/references.hh"
#include "lix/libutil/strings.hh"
namespace nix {
kj::Promise<Result<std::map<StorePath, StorePath>>> makeContentAddressed(
Store & srcStore,
Store & dstStore,
const StorePathSet & storePaths)
try {
StorePathSet closure;
TRY_AWAIT(srcStore.computeFSClosure(storePaths, closure));
auto paths = TRY_AWAIT(srcStore.topoSortPaths(closure));
std::reverse(paths.begin(), paths.end());
std::map<StorePath, StorePath> remappings;
for (auto & path : paths) {
auto pathS = srcStore.printStorePath(path);
auto oldInfo = TRY_AWAIT(srcStore.queryPathInfo(path));
std::string oldHashPart(path.hashPart());
StringSink sink;
TRY_AWAIT(TRY_AWAIT(srcStore.narFromPath(path))->drainInto(sink));
StringMap rewrites;
StoreReferences refs;
for (auto & ref : oldInfo->references) {
if (ref == path)
refs.self = 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));
refs.others.insert(std::move(replacement));
}
}
sink.s = rewriteStrings(sink.s, rewrites);
auto narModuloHash = [&] {
StringSource source{sink.s};
return computeHashModulo(HashType::SHA256, oldHashPart, source).first;
}();
ValidPathInfo info {
dstStore,
path.name(),
FixedOutputInfo {
.method = FileIngestionMethod::Recursive,
.hash = narModuloHash,
.references = std::move(refs),
},
Hash::dummy,
};
printInfo("rewriting '%s' to '%s'", pathS, dstStore.printStorePath(info.path));
const auto rewritten = rewriteStrings(sink.s, {{oldHashPart, std::string(info.path.hashPart())}});
info.narHash = hashString(HashType::SHA256, rewritten);
info.narSize = sink.s.size();
AsyncStringInputStream source(rewritten);
TRY_AWAIT(dstStore.addToStore(info, source));
remappings.insert_or_assign(std::move(path), std::move(info.path));
}
co_return remappings;
} catch (...) {
co_return result::current_exception();
}
kj::Promise<Result<StorePath>> makeContentAddressed(
Store & srcStore,
Store & dstStore,
const StorePath & fromPath)
try {
auto remappings = TRY_AWAIT(makeContentAddressed(srcStore, dstStore, StorePathSet{fromPath}));
auto i = remappings.find(fromPath);
assert(i != remappings.end());
co_return i->second;
} catch (...) {
co_return result::current_exception();
}
}
|