#include "source-path.hh" #include "fs-sink.hh" #include "variant-wrapper.hh" namespace nix { /** * An source accessor for an in-memory file system. */ struct MemorySourceAccessor : virtual SourceAccessor { /** * In addition to being part of the implementation of * `MemorySourceAccessor`, this has a side benefit of nicely * defining what a "file system object" is in Nix. */ struct File { bool operator == (const File &) const noexcept; std::strong_ordering operator <=> (const File &) const noexcept; struct Regular { bool executable = false; std::string contents; bool operator == (const Regular &) const = default; auto operator <=> (const Regular &) const = default; }; struct Directory { using Name = std::string; std::map> contents; bool operator == (const Directory &) const noexcept; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. bool operator < (const Directory &) const noexcept; }; struct Symlink { std::string target; bool operator == (const Symlink &) const = default; auto operator <=> (const Symlink &) const = default; }; using Raw = std::variant; Raw raw; MAKE_WRAPPER_CONSTRUCTOR(File); Stat lstat() const; }; File root { File::Directory {} }; bool operator == (const MemorySourceAccessor &) const noexcept = default; bool operator < (const MemorySourceAccessor & other) const noexcept { return root < other.root; } std::string readFile(const CanonPath & path) override; bool pathExists(const CanonPath & path) override; std::optional maybeLstat(const CanonPath & path) override; DirEntries readDirectory(const CanonPath & path) override; std::string readLink(const CanonPath & path) override; /** * @param create If present, create this file and any parent directories * that are needed. * * Return null if * * - `create = false`: File does not exist. * * - `create = true`: some parent file was not a dir, so couldn't * look/create inside. */ File * open(const CanonPath & path, std::optional create); SourcePath addFile(CanonPath path, std::string && contents); }; inline bool MemorySourceAccessor::File::Directory::operator == ( const MemorySourceAccessor::File::Directory &) const noexcept = default; inline bool MemorySourceAccessor::File::Directory::operator < ( const MemorySourceAccessor::File::Directory & other) const noexcept { return contents < other.contents; } inline bool MemorySourceAccessor::File::operator == ( const MemorySourceAccessor::File &) const noexcept = default; inline std::strong_ordering MemorySourceAccessor::File::operator <=> ( const MemorySourceAccessor::File &) const noexcept = default; /** * Write to a `MemorySourceAccessor` at the given path */ struct MemorySink : FileSystemObjectSink { MemorySourceAccessor & dst; MemorySink(MemorySourceAccessor & dst) : dst(dst) { } void createDirectory(const CanonPath & path) override; void createRegularFile( const CanonPath & path, std::function) override; void createSymlink(const CanonPath & path, const std::string & target) override; }; }