mirror of
https://github.com/NixOS/nix.git
synced 2025-11-14 14:32:42 +01:00
For example, instead of doing
#include "nix/store-config.hh"
#include "nix/derived-path.hh"
Now do
#include "nix/store/config.hh"
#include "nix/store/derived-path.hh"
This was originally planned in the issue, and also recent requested by
Eelco.
Most of the change is purely mechanical. There is just one small
additional issue. See how, in the example above, we took this
opportunity to also turn `<comp>-config.hh` into `<comp>/config.hh`.
Well, there was already a `nix/util/config.{cc,hh}`. Even though there
is not a public configuration header for libutil (which also would be
called `nix/util/config.{cc,hh}`) that's still confusing, To avoid any
such confusion, we renamed that to `nix/util/configuration.{cc,hh}`.
Finally, note that the libflake headers already did this, so we didn't
need to do anything to them. We wouldn't want to mistakenly get
`nix/flake/flake/flake.hh`!
Progress on #7876
(cherry picked from commit cc24766fa6)
193 lines
5.4 KiB
C++
193 lines
5.4 KiB
C++
#include "nix/util/memory-source-accessor.hh"
|
|
|
|
namespace nix {
|
|
|
|
MemorySourceAccessor::File *
|
|
MemorySourceAccessor::open(const CanonPath & path, std::optional<File> create)
|
|
{
|
|
File * cur = &root;
|
|
|
|
bool newF = false;
|
|
|
|
for (std::string_view name : path)
|
|
{
|
|
auto * curDirP = std::get_if<File::Directory>(&cur->raw);
|
|
if (!curDirP)
|
|
return nullptr;
|
|
auto & curDir = *curDirP;
|
|
|
|
auto i = curDir.contents.find(name);
|
|
if (i == curDir.contents.end()) {
|
|
if (!create)
|
|
return nullptr;
|
|
else {
|
|
newF = true;
|
|
i = curDir.contents.insert(i, {
|
|
std::string { name },
|
|
File::Directory {},
|
|
});
|
|
}
|
|
}
|
|
cur = &i->second;
|
|
}
|
|
|
|
if (newF && create) *cur = std::move(*create);
|
|
|
|
return cur;
|
|
}
|
|
|
|
std::string MemorySourceAccessor::readFile(const CanonPath & path)
|
|
{
|
|
auto * f = open(path, std::nullopt);
|
|
if (!f)
|
|
throw Error("file '%s' does not exist", path);
|
|
if (auto * r = std::get_if<File::Regular>(&f->raw))
|
|
return r->contents;
|
|
else
|
|
throw Error("file '%s' is not a regular file", path);
|
|
}
|
|
|
|
bool MemorySourceAccessor::pathExists(const CanonPath & path)
|
|
{
|
|
return open(path, std::nullopt);
|
|
}
|
|
|
|
MemorySourceAccessor::Stat MemorySourceAccessor::File::lstat() const
|
|
{
|
|
return std::visit(overloaded {
|
|
[](const Regular & r) {
|
|
return Stat {
|
|
.type = tRegular,
|
|
.fileSize = r.contents.size(),
|
|
.isExecutable = r.executable,
|
|
};
|
|
},
|
|
[](const Directory &) {
|
|
return Stat {
|
|
.type = tDirectory,
|
|
};
|
|
},
|
|
[](const Symlink &) {
|
|
return Stat {
|
|
.type = tSymlink,
|
|
};
|
|
},
|
|
}, this->raw);
|
|
}
|
|
|
|
std::optional<MemorySourceAccessor::Stat>
|
|
MemorySourceAccessor::maybeLstat(const CanonPath & path)
|
|
{
|
|
const auto * f = open(path, std::nullopt);
|
|
return f ? std::optional { f->lstat() } : std::nullopt;
|
|
}
|
|
|
|
MemorySourceAccessor::DirEntries MemorySourceAccessor::readDirectory(const CanonPath & path)
|
|
{
|
|
auto * f = open(path, std::nullopt);
|
|
if (!f)
|
|
throw Error("file '%s' does not exist", path);
|
|
if (auto * d = std::get_if<File::Directory>(&f->raw)) {
|
|
DirEntries res;
|
|
for (auto & [name, file] : d->contents)
|
|
res.insert_or_assign(name, file.lstat().type);
|
|
return res;
|
|
} else
|
|
throw Error("file '%s' is not a directory", path);
|
|
return {};
|
|
}
|
|
|
|
std::string MemorySourceAccessor::readLink(const CanonPath & path)
|
|
{
|
|
auto * f = open(path, std::nullopt);
|
|
if (!f)
|
|
throw Error("file '%s' does not exist", path);
|
|
if (auto * s = std::get_if<File::Symlink>(&f->raw))
|
|
return s->target;
|
|
else
|
|
throw Error("file '%s' is not a symbolic link", path);
|
|
}
|
|
|
|
SourcePath MemorySourceAccessor::addFile(CanonPath path, std::string && contents)
|
|
{
|
|
auto * f = open(path, File { File::Regular {} });
|
|
if (!f)
|
|
throw Error("file '%s' cannot be made because some parent file is not a directory", path);
|
|
if (auto * r = std::get_if<File::Regular>(&f->raw))
|
|
r->contents = std::move(contents);
|
|
else
|
|
throw Error("file '%s' is not a regular file", path);
|
|
|
|
return SourcePath{ref(shared_from_this()), path};
|
|
}
|
|
|
|
|
|
using File = MemorySourceAccessor::File;
|
|
|
|
void MemorySink::createDirectory(const CanonPath & path)
|
|
{
|
|
auto * f = dst.open(path, File { File::Directory { } });
|
|
if (!f)
|
|
throw Error("file '%s' cannot be made because some parent file is not a directory", path);
|
|
|
|
if (!std::holds_alternative<File::Directory>(f->raw))
|
|
throw Error("file '%s' is not a directory", path);
|
|
};
|
|
|
|
struct CreateMemoryRegularFile : CreateRegularFileSink {
|
|
File::Regular & regularFile;
|
|
|
|
CreateMemoryRegularFile(File::Regular & r)
|
|
: regularFile(r)
|
|
{ }
|
|
|
|
void operator () (std::string_view data) override;
|
|
void isExecutable() override;
|
|
void preallocateContents(uint64_t size) override;
|
|
};
|
|
|
|
void MemorySink::createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func)
|
|
{
|
|
auto * f = dst.open(path, File { File::Regular {} });
|
|
if (!f)
|
|
throw Error("file '%s' cannot be made because some parent file is not a directory", path);
|
|
if (auto * rp = std::get_if<File::Regular>(&f->raw)) {
|
|
CreateMemoryRegularFile crf { *rp };
|
|
func(crf);
|
|
} else
|
|
throw Error("file '%s' is not a regular file", path);
|
|
}
|
|
|
|
void CreateMemoryRegularFile::isExecutable()
|
|
{
|
|
regularFile.executable = true;
|
|
}
|
|
|
|
void CreateMemoryRegularFile::preallocateContents(uint64_t len)
|
|
{
|
|
regularFile.contents.reserve(len);
|
|
}
|
|
|
|
void CreateMemoryRegularFile::operator () (std::string_view data)
|
|
{
|
|
regularFile.contents += data;
|
|
}
|
|
|
|
void MemorySink::createSymlink(const CanonPath & path, const std::string & target)
|
|
{
|
|
auto * f = dst.open(path, File { File::Symlink { } });
|
|
if (!f)
|
|
throw Error("file '%s' cannot be made because some parent file is not a directory", path);
|
|
if (auto * s = std::get_if<File::Symlink>(&f->raw))
|
|
s->target = target;
|
|
else
|
|
throw Error("file '%s' is not a symbolic link", path);
|
|
}
|
|
|
|
ref<SourceAccessor> makeEmptySourceAccessor()
|
|
{
|
|
static auto empty = make_ref<MemorySourceAccessor>().cast<SourceAccessor>();
|
|
return empty;
|
|
}
|
|
|
|
}
|