#include "nix/util/source-accessor.hh" namespace nix { struct MountedSourceAccessor : SourceAccessor { std::map> mounts; MountedSourceAccessor(std::map> _mounts) : mounts(std::move(_mounts)) { displayPrefix.clear(); // Currently we require a root filesystem. This could be relaxed. assert(mounts.contains(CanonPath::root)); // FIXME: return dummy parent directories automatically? } std::string readFile(const CanonPath & path) override { auto [accessor, subpath] = resolve(path); return accessor->readFile(subpath); } std::optional maybeLstat(const CanonPath & path) override { auto [accessor, subpath] = resolve(path); return accessor->maybeLstat(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 displayPrefix + accessor->showPath(subpath) + displaySuffix; } std::pair, CanonPath> resolve(CanonPath path) { // Find the nearest parent of `path` that is a mount point. std::vector subpath; while (true) { auto i = mounts.find(path); if (i != mounts.end()) { std::reverse(subpath.begin(), subpath.end()); return {i->second, CanonPath(subpath)}; } assert(!path.isRoot()); subpath.push_back(std::string(*path.baseName())); path.pop(); } } std::optional getPhysicalPath(const CanonPath & path) override { auto [accessor, subpath] = resolve(path); return accessor->getPhysicalPath(subpath); } }; ref makeMountedSourceAccessor(std::map> mounts) { return make_ref(std::move(mounts)); } }