2023-10-27 19:39:00 +03:00
|
|
|
#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));
|
|
|
|
|
2023-11-14 14:57:24 +02:00
|
|
|
// FIXME: return dummy parent directories automatically?
|
2023-10-27 19:39:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-11-02 17:16:37 +02:00
|
|
|
std::optional<Stat> maybeLstat(const CanonPath & path) override
|
2023-10-27 19:39:00 +03:00
|
|
|
{
|
|
|
|
auto [accessor, subpath] = resolve(path);
|
2023-11-02 17:16:37 +02:00
|
|
|
return accessor->maybeLstat(subpath);
|
2023-10-27 19:39:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|