mirror of
https://github.com/NixOS/nix.git
synced 2025-12-04 08:00:59 +01:00
Git fetcher: Improve submodule handling
Instead of making a complete copy of the repo, fetching the submodules, and writing the result to the store (which is all superexpensive), we now fetch the submodules recursively using the Git fetcher, and return a union accessor that "mounts" the accessors for the submodules on top of the root accessor.
This commit is contained in:
parent
ee36a44bf2
commit
d88106df24
6 changed files with 212 additions and 84 deletions
80
src/libfetchers/union-input-accessor.cc
Normal file
80
src/libfetchers/union-input-accessor.cc
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#include "union-input-accessor.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct UnionInputAccessor : InputAccessor
|
||||
{
|
||||
std::map<CanonPath, ref<InputAccessor>> mounts;
|
||||
|
||||
UnionInputAccessor(std::map<CanonPath, ref<InputAccessor>> _mounts)
|
||||
: mounts(std::move(_mounts))
|
||||
{
|
||||
// Currently we require a root filesystem. This could be relaxed.
|
||||
assert(mounts.contains(CanonPath::root));
|
||||
|
||||
// FIXME: should check that every mount point exists. Or we
|
||||
// could return dummy parent directories automatically.
|
||||
}
|
||||
|
||||
std::string readFile(const CanonPath & path) override
|
||||
{
|
||||
auto [accessor, subpath] = resolve(path);
|
||||
return accessor->readFile(subpath);
|
||||
}
|
||||
|
||||
bool pathExists(const CanonPath & path) override
|
||||
{
|
||||
auto [accessor, subpath] = resolve(path);
|
||||
return accessor->pathExists(subpath);
|
||||
}
|
||||
|
||||
Stat lstat(const CanonPath & path) override
|
||||
{
|
||||
auto [accessor, subpath] = resolve(path);
|
||||
return accessor->lstat(subpath);
|
||||
}
|
||||
|
||||
DirEntries readDirectory(const CanonPath & path) override
|
||||
{
|
||||
auto [accessor, subpath] = resolve(path);
|
||||
return accessor->readDirectory(subpath);
|
||||
}
|
||||
|
||||
std::string readLink(const CanonPath & path) override
|
||||
{
|
||||
auto [accessor, subpath] = resolve(path);
|
||||
return accessor->readLink(subpath);
|
||||
}
|
||||
|
||||
std::string showPath(const CanonPath & path) override
|
||||
{
|
||||
auto [accessor, subpath] = resolve(path);
|
||||
return accessor->showPath(subpath);
|
||||
}
|
||||
|
||||
std::pair<ref<InputAccessor>, CanonPath> resolve(CanonPath path)
|
||||
{
|
||||
// Find the nearest parent of `path` that is a mount point.
|
||||
std::vector<std::string> ss;
|
||||
while (true) {
|
||||
auto i = mounts.find(path);
|
||||
if (i != mounts.end()) {
|
||||
auto subpath = CanonPath::root;
|
||||
for (auto j = ss.rbegin(); j != ss.rend(); ++j)
|
||||
subpath.push(*j);
|
||||
return {i->second, std::move(subpath)};
|
||||
}
|
||||
|
||||
assert(!path.isRoot());
|
||||
ss.push_back(std::string(*path.baseName()));
|
||||
path.pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ref<InputAccessor> makeUnionInputAccessor(std::map<CanonPath, ref<InputAccessor>> mounts)
|
||||
{
|
||||
return make_ref<UnionInputAccessor>(std::move(mounts));
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue