mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-25 15:26:17 +02:00
use CanonPath
in fs-sink
and its derivatives
This commit is contained in:
parent
32e6cc64b5
commit
72bb530141
12 changed files with 73 additions and 79 deletions
|
@ -851,10 +851,10 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
||||||
}
|
}
|
||||||
|
|
||||||
void createRegularFile(
|
void createRegularFile(
|
||||||
const Path & path,
|
const CanonPath & path,
|
||||||
std::function<void(CreateRegularFileSink &)> func) override
|
std::function<void(CreateRegularFileSink &)> func) override
|
||||||
{
|
{
|
||||||
auto pathComponents = tokenizeString<std::vector<std::string>>(path, "/");
|
auto pathComponents = tokenizeString<std::vector<std::string>>(path.rel(), "/");
|
||||||
if (!prepareDirs(pathComponents, false)) return;
|
if (!prepareDirs(pathComponents, false)) return;
|
||||||
|
|
||||||
git_writestream * stream = nullptr;
|
git_writestream * stream = nullptr;
|
||||||
|
@ -862,11 +862,11 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
||||||
throw Error("creating a blob stream object: %s", git_error_last()->message);
|
throw Error("creating a blob stream object: %s", git_error_last()->message);
|
||||||
|
|
||||||
struct CRF : CreateRegularFileSink {
|
struct CRF : CreateRegularFileSink {
|
||||||
const Path & path;
|
const CanonPath & path;
|
||||||
GitFileSystemObjectSinkImpl & back;
|
GitFileSystemObjectSinkImpl & back;
|
||||||
git_writestream * stream;
|
git_writestream * stream;
|
||||||
bool executable = false;
|
bool executable = false;
|
||||||
CRF(const Path & path, GitFileSystemObjectSinkImpl & back, git_writestream * stream)
|
CRF(const CanonPath & path, GitFileSystemObjectSinkImpl & back, git_writestream * stream)
|
||||||
: path(path), back(back), stream(stream)
|
: path(path), back(back), stream(stream)
|
||||||
{}
|
{}
|
||||||
void operator () (std::string_view data) override
|
void operator () (std::string_view data) override
|
||||||
|
@ -891,15 +891,15 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
||||||
: GIT_FILEMODE_BLOB);
|
: GIT_FILEMODE_BLOB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createDirectory(const Path & path) override
|
void createDirectory(const CanonPath & path) override
|
||||||
{
|
{
|
||||||
auto pathComponents = tokenizeString<std::vector<std::string>>(path, "/");
|
auto pathComponents = tokenizeString<std::vector<std::string>>(path.rel(), "/");
|
||||||
(void) prepareDirs(pathComponents, true);
|
(void) prepareDirs(pathComponents, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSymlink(const Path & path, const std::string & target) override
|
void createSymlink(const CanonPath & path, const std::string & target) override
|
||||||
{
|
{
|
||||||
auto pathComponents = tokenizeString<std::vector<std::string>>(path, "/");
|
auto pathComponents = tokenizeString<std::vector<std::string>>(path.rel(), "/");
|
||||||
if (!prepareDirs(pathComponents, false)) return;
|
if (!prepareDirs(pathComponents, false)) return;
|
||||||
|
|
||||||
git_oid oid;
|
git_oid oid;
|
||||||
|
|
|
@ -71,9 +71,9 @@ struct NarAccessor : public SourceAccessor
|
||||||
: acc(acc), source(source)
|
: acc(acc), source(source)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
NarMember & createMember(const Path & path, NarMember member)
|
NarMember & createMember(const CanonPath & path, NarMember member)
|
||||||
{
|
{
|
||||||
size_t level = std::count(path.begin(), path.end(), '/');
|
size_t level = std::count(path.rel().begin(), path.rel().end(), '/');
|
||||||
while (parents.size() > level) parents.pop();
|
while (parents.size() > level) parents.pop();
|
||||||
|
|
||||||
if (parents.empty()) {
|
if (parents.empty()) {
|
||||||
|
@ -83,14 +83,14 @@ struct NarAccessor : public SourceAccessor
|
||||||
} else {
|
} else {
|
||||||
if (parents.top()->stat.type != Type::tDirectory)
|
if (parents.top()->stat.type != Type::tDirectory)
|
||||||
throw Error("NAR file missing parent directory of path '%s'", path);
|
throw Error("NAR file missing parent directory of path '%s'", path);
|
||||||
auto result = parents.top()->children.emplace(baseNameOf(path), std::move(member));
|
auto result = parents.top()->children.emplace(baseNameOf(path.rel()), std::move(member));
|
||||||
auto & ref = result.first->second;
|
auto & ref = result.first->second;
|
||||||
parents.push(&ref);
|
parents.push(&ref);
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createDirectory(const Path & path) override
|
void createDirectory(const CanonPath & path) override
|
||||||
{
|
{
|
||||||
createMember(path, NarMember{ .stat = {
|
createMember(path, NarMember{ .stat = {
|
||||||
.type = Type::tDirectory,
|
.type = Type::tDirectory,
|
||||||
|
@ -100,7 +100,7 @@ struct NarAccessor : public SourceAccessor
|
||||||
} });
|
} });
|
||||||
}
|
}
|
||||||
|
|
||||||
void createRegularFile(const Path & path, std::function<void(CreateRegularFileSink &)> func) override
|
void createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func) override
|
||||||
{
|
{
|
||||||
auto & nm = createMember(path, NarMember{ .stat = {
|
auto & nm = createMember(path, NarMember{ .stat = {
|
||||||
.type = Type::tRegular,
|
.type = Type::tRegular,
|
||||||
|
@ -112,7 +112,7 @@ struct NarAccessor : public SourceAccessor
|
||||||
func(nmc);
|
func(nmc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSymlink(const Path & path, const std::string & target) override
|
void createSymlink(const CanonPath & path, const std::string & target) override
|
||||||
{
|
{
|
||||||
createMember(path,
|
createMember(path,
|
||||||
NarMember{
|
NarMember{
|
||||||
|
|
|
@ -165,7 +165,7 @@ struct CaseInsensitiveCompare
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void parse(FileSystemObjectSink & sink, Source & source, const Path & path)
|
static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath & path)
|
||||||
{
|
{
|
||||||
std::string s;
|
std::string s;
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ static void parse(FileSystemObjectSink & sink, Source & source, const Path & pat
|
||||||
}
|
}
|
||||||
} else if (s == "node") {
|
} else if (s == "node") {
|
||||||
if (name.empty()) throw badArchive("entry name missing");
|
if (name.empty()) throw badArchive("entry name missing");
|
||||||
parse(sink, source, path + "/" + name);
|
parse(sink, source, path / name);
|
||||||
} else
|
} else
|
||||||
throw badArchive("unknown field " + s);
|
throw badArchive("unknown field " + s);
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,7 @@ void parseDump(FileSystemObjectSink & sink, Source & source)
|
||||||
}
|
}
|
||||||
if (version != narVersionMagic1)
|
if (version != narVersionMagic1)
|
||||||
throw badArchive("input doesn't look like a Nix archive");
|
throw badArchive("input doesn't look like a Nix archive");
|
||||||
parse(sink, source, "");
|
parse(sink, source, CanonPath{""});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ Path dirOf(const PathView path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string_view baseNameOf(std::string_view path)
|
std::string_view baseNameOf(PathView path)
|
||||||
{
|
{
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace nix {
|
||||||
|
|
||||||
void copyRecursive(
|
void copyRecursive(
|
||||||
SourceAccessor & accessor, const CanonPath & from,
|
SourceAccessor & accessor, const CanonPath & from,
|
||||||
FileSystemObjectSink & sink, const Path & to)
|
FileSystemObjectSink & sink, const CanonPath & to)
|
||||||
{
|
{
|
||||||
auto stat = accessor.lstat(from);
|
auto stat = accessor.lstat(from);
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ void copyRecursive(
|
||||||
for (auto & [name, _] : accessor.readDirectory(from)) {
|
for (auto & [name, _] : accessor.readDirectory(from)) {
|
||||||
copyRecursive(
|
copyRecursive(
|
||||||
accessor, from / name,
|
accessor, from / name,
|
||||||
sink, to + "/" + name);
|
sink, to / name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -69,17 +69,9 @@ static RestoreSinkSettings restoreSinkSettings;
|
||||||
static GlobalConfig::Register r1(&restoreSinkSettings);
|
static GlobalConfig::Register r1(&restoreSinkSettings);
|
||||||
|
|
||||||
|
|
||||||
void RestoreSink::createDirectory(const Path & path)
|
void RestoreSink::createDirectory(const CanonPath & path)
|
||||||
{
|
{
|
||||||
Path p = dstPath + path;
|
std::filesystem::create_directory(dstPath / path.rel());
|
||||||
if (
|
|
||||||
#ifndef _WIN32 // TODO abstract mkdir perms for Windows
|
|
||||||
mkdir(p.c_str(), 0777) == -1
|
|
||||||
#else
|
|
||||||
!CreateDirectoryW(pathNG(p).c_str(), NULL)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
throw NativeSysError("creating directory '%1%'", p);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RestoreRegularFile : CreateRegularFileSink {
|
struct RestoreRegularFile : CreateRegularFileSink {
|
||||||
|
@ -90,13 +82,14 @@ struct RestoreRegularFile : CreateRegularFileSink {
|
||||||
void preallocateContents(uint64_t size) override;
|
void preallocateContents(uint64_t size) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
void RestoreSink::createRegularFile(const Path & path, std::function<void(CreateRegularFileSink &)> func)
|
void RestoreSink::createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func)
|
||||||
{
|
{
|
||||||
Path p = dstPath + path;
|
std::cout << "SCREAM!!!====== " << dstPath / path.rel() << std::endl;
|
||||||
|
std::filesystem::path p = dstPath / path.rel();
|
||||||
RestoreRegularFile crf;
|
RestoreRegularFile crf;
|
||||||
crf.fd =
|
crf.fd =
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
CreateFileW(pathNG(path).c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)
|
CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)
|
||||||
#else
|
#else
|
||||||
open(p.c_str(), O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC, 0666)
|
open(p.c_str(), O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC, 0666)
|
||||||
#endif
|
#endif
|
||||||
|
@ -141,14 +134,14 @@ void RestoreRegularFile::operator () (std::string_view data)
|
||||||
writeFull(fd.get(), data);
|
writeFull(fd.get(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestoreSink::createSymlink(const Path & path, const std::string & target)
|
void RestoreSink::createSymlink(const CanonPath & path, const std::string & target)
|
||||||
{
|
{
|
||||||
Path p = dstPath + path;
|
std::filesystem::path p = dstPath / path.rel();
|
||||||
nix::createSymlink(target, p);
|
nix::createSymlink(target, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegularFileSink::createRegularFile(const Path & path, std::function<void(CreateRegularFileSink &)> func)
|
void RegularFileSink::createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func)
|
||||||
{
|
{
|
||||||
struct CRF : CreateRegularFileSink {
|
struct CRF : CreateRegularFileSink {
|
||||||
RegularFileSink & back;
|
RegularFileSink & back;
|
||||||
|
@ -163,7 +156,7 @@ void RegularFileSink::createRegularFile(const Path & path, std::function<void(Cr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NullFileSystemObjectSink::createRegularFile(const Path & path, std::function<void(CreateRegularFileSink &)> func)
|
void NullFileSystemObjectSink::createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func)
|
||||||
{
|
{
|
||||||
struct : CreateRegularFileSink {
|
struct : CreateRegularFileSink {
|
||||||
void operator () (std::string_view data) override {}
|
void operator () (std::string_view data) override {}
|
||||||
|
|
|
@ -28,17 +28,17 @@ struct FileSystemObjectSink
|
||||||
{
|
{
|
||||||
virtual ~FileSystemObjectSink() = default;
|
virtual ~FileSystemObjectSink() = default;
|
||||||
|
|
||||||
virtual void createDirectory(const Path & path) = 0;
|
virtual void createDirectory(const CanonPath & path) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function in general is no re-entrant. Only one file can be
|
* This function in general is no re-entrant. Only one file can be
|
||||||
* written at a time.
|
* written at a time.
|
||||||
*/
|
*/
|
||||||
virtual void createRegularFile(
|
virtual void createRegularFile(
|
||||||
const Path & path,
|
const CanonPath & path,
|
||||||
std::function<void(CreateRegularFileSink &)>) = 0;
|
std::function<void(CreateRegularFileSink &)>) = 0;
|
||||||
|
|
||||||
virtual void createSymlink(const Path & path, const std::string & target) = 0;
|
virtual void createSymlink(const CanonPath & path, const std::string & target) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,17 +46,17 @@ struct FileSystemObjectSink
|
||||||
*/
|
*/
|
||||||
void copyRecursive(
|
void copyRecursive(
|
||||||
SourceAccessor & accessor, const CanonPath & sourcePath,
|
SourceAccessor & accessor, const CanonPath & sourcePath,
|
||||||
FileSystemObjectSink & sink, const Path & destPath);
|
FileSystemObjectSink & sink, const CanonPath & destPath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ignore everything and do nothing
|
* Ignore everything and do nothing
|
||||||
*/
|
*/
|
||||||
struct NullFileSystemObjectSink : FileSystemObjectSink
|
struct NullFileSystemObjectSink : FileSystemObjectSink
|
||||||
{
|
{
|
||||||
void createDirectory(const Path & path) override { }
|
void createDirectory(const CanonPath & path) override { }
|
||||||
void createSymlink(const Path & path, const std::string & target) override { }
|
void createSymlink(const CanonPath & path, const std::string & target) override { }
|
||||||
void createRegularFile(
|
void createRegularFile(
|
||||||
const Path & path,
|
const CanonPath & path,
|
||||||
std::function<void(CreateRegularFileSink &)>) override;
|
std::function<void(CreateRegularFileSink &)>) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,15 +65,15 @@ struct NullFileSystemObjectSink : FileSystemObjectSink
|
||||||
*/
|
*/
|
||||||
struct RestoreSink : FileSystemObjectSink
|
struct RestoreSink : FileSystemObjectSink
|
||||||
{
|
{
|
||||||
Path dstPath;
|
std::filesystem::path dstPath;
|
||||||
|
|
||||||
void createDirectory(const Path & path) override;
|
void createDirectory(const CanonPath & path) override;
|
||||||
|
|
||||||
void createRegularFile(
|
void createRegularFile(
|
||||||
const Path & path,
|
const CanonPath & path,
|
||||||
std::function<void(CreateRegularFileSink &)>) override;
|
std::function<void(CreateRegularFileSink &)>) override;
|
||||||
|
|
||||||
void createSymlink(const Path & path, const std::string & target) override;
|
void createSymlink(const CanonPath & path, const std::string & target) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,18 +88,18 @@ struct RegularFileSink : FileSystemObjectSink
|
||||||
|
|
||||||
RegularFileSink(Sink & sink) : sink(sink) { }
|
RegularFileSink(Sink & sink) : sink(sink) { }
|
||||||
|
|
||||||
void createDirectory(const Path & path) override
|
void createDirectory(const CanonPath & path) override
|
||||||
{
|
{
|
||||||
regular = false;
|
regular = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSymlink(const Path & path, const std::string & target) override
|
void createSymlink(const CanonPath & path, const std::string & target) override
|
||||||
{
|
{
|
||||||
regular = false;
|
regular = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void createRegularFile(
|
void createRegularFile(
|
||||||
const Path & path,
|
const CanonPath & path,
|
||||||
std::function<void(CreateRegularFileSink &)>) override;
|
std::function<void(CreateRegularFileSink &)>) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ static std::string getString(Source & source, int n)
|
||||||
|
|
||||||
void parseBlob(
|
void parseBlob(
|
||||||
FileSystemObjectSink & sink,
|
FileSystemObjectSink & sink,
|
||||||
const Path & sinkPath,
|
const CanonPath & sinkPath,
|
||||||
Source & source,
|
Source & source,
|
||||||
BlobMode blobMode,
|
BlobMode blobMode,
|
||||||
const ExperimentalFeatureSettings & xpSettings)
|
const ExperimentalFeatureSettings & xpSettings)
|
||||||
|
@ -116,7 +116,7 @@ void parseBlob(
|
||||||
|
|
||||||
void parseTree(
|
void parseTree(
|
||||||
FileSystemObjectSink & sink,
|
FileSystemObjectSink & sink,
|
||||||
const Path & sinkPath,
|
const CanonPath & sinkPath,
|
||||||
Source & source,
|
Source & source,
|
||||||
std::function<SinkHook> hook,
|
std::function<SinkHook> hook,
|
||||||
const ExperimentalFeatureSettings & xpSettings)
|
const ExperimentalFeatureSettings & xpSettings)
|
||||||
|
@ -147,7 +147,7 @@ void parseTree(
|
||||||
Hash hash(HashAlgorithm::SHA1);
|
Hash hash(HashAlgorithm::SHA1);
|
||||||
std::copy(hashs.begin(), hashs.end(), hash.hash);
|
std::copy(hashs.begin(), hashs.end(), hash.hash);
|
||||||
|
|
||||||
hook(name, TreeEntry {
|
hook(CanonPath{name}, TreeEntry {
|
||||||
.mode = mode,
|
.mode = mode,
|
||||||
.hash = hash,
|
.hash = hash,
|
||||||
});
|
});
|
||||||
|
@ -171,7 +171,7 @@ ObjectType parseObjectType(
|
||||||
|
|
||||||
void parse(
|
void parse(
|
||||||
FileSystemObjectSink & sink,
|
FileSystemObjectSink & sink,
|
||||||
const Path & sinkPath,
|
const CanonPath & sinkPath,
|
||||||
Source & source,
|
Source & source,
|
||||||
BlobMode rootModeIfBlob,
|
BlobMode rootModeIfBlob,
|
||||||
std::function<SinkHook> hook,
|
std::function<SinkHook> hook,
|
||||||
|
@ -208,7 +208,7 @@ std::optional<Mode> convertMode(SourceAccessor::Type type)
|
||||||
|
|
||||||
void restore(FileSystemObjectSink & sink, Source & source, std::function<RestoreHook> hook)
|
void restore(FileSystemObjectSink & sink, Source & source, std::function<RestoreHook> hook)
|
||||||
{
|
{
|
||||||
parse(sink, "", source, BlobMode::Regular, [&](Path name, TreeEntry entry) {
|
parse(sink, CanonPath{""}, source, BlobMode::Regular, [&](CanonPath name, TreeEntry entry) {
|
||||||
auto [accessor, from] = hook(entry.hash);
|
auto [accessor, from] = hook(entry.hash);
|
||||||
auto stat = accessor->lstat(from);
|
auto stat = accessor->lstat(from);
|
||||||
auto gotOpt = convertMode(stat.type);
|
auto gotOpt = convertMode(stat.type);
|
||||||
|
|
|
@ -64,7 +64,7 @@ using Tree = std::map<std::string, TreeEntry>;
|
||||||
* Implementations may seek to memoize resources (bandwidth, storage,
|
* Implementations may seek to memoize resources (bandwidth, storage,
|
||||||
* etc.) for the same Git hash.
|
* etc.) for the same Git hash.
|
||||||
*/
|
*/
|
||||||
using SinkHook = void(const Path & name, TreeEntry entry);
|
using SinkHook = void(const CanonPath & name, TreeEntry entry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the "blob " or "tree " prefix.
|
* Parse the "blob " or "tree " prefix.
|
||||||
|
@ -89,13 +89,13 @@ enum struct BlobMode : RawMode
|
||||||
};
|
};
|
||||||
|
|
||||||
void parseBlob(
|
void parseBlob(
|
||||||
FileSystemObjectSink & sink, const Path & sinkPath,
|
FileSystemObjectSink & sink, const CanonPath & sinkPath,
|
||||||
Source & source,
|
Source & source,
|
||||||
BlobMode blobMode,
|
BlobMode blobMode,
|
||||||
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
|
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
|
||||||
|
|
||||||
void parseTree(
|
void parseTree(
|
||||||
FileSystemObjectSink & sink, const Path & sinkPath,
|
FileSystemObjectSink & sink, const CanonPath & sinkPath,
|
||||||
Source & source,
|
Source & source,
|
||||||
std::function<SinkHook> hook,
|
std::function<SinkHook> hook,
|
||||||
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
|
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
|
||||||
|
@ -108,7 +108,7 @@ void parseTree(
|
||||||
* a blob, this is ignored.
|
* a blob, this is ignored.
|
||||||
*/
|
*/
|
||||||
void parse(
|
void parse(
|
||||||
FileSystemObjectSink & sink, const Path & sinkPath,
|
FileSystemObjectSink & sink, const CanonPath & sinkPath,
|
||||||
Source & source,
|
Source & source,
|
||||||
BlobMode rootModeIfBlob,
|
BlobMode rootModeIfBlob,
|
||||||
std::function<SinkHook> hook,
|
std::function<SinkHook> hook,
|
||||||
|
|
|
@ -124,9 +124,9 @@ SourcePath MemorySourceAccessor::addFile(CanonPath path, std::string && contents
|
||||||
|
|
||||||
using File = MemorySourceAccessor::File;
|
using File = MemorySourceAccessor::File;
|
||||||
|
|
||||||
void MemorySink::createDirectory(const Path & path)
|
void MemorySink::createDirectory(const CanonPath & path)
|
||||||
{
|
{
|
||||||
auto * f = dst.open(CanonPath{path}, File { File::Directory { } });
|
auto * f = dst.open(path, File { File::Directory { } });
|
||||||
if (!f)
|
if (!f)
|
||||||
throw Error("file '%s' cannot be made because some parent file is not a directory", path);
|
throw Error("file '%s' cannot be made because some parent file is not a directory", path);
|
||||||
|
|
||||||
|
@ -146,9 +146,9 @@ struct CreateMemoryRegularFile : CreateRegularFileSink {
|
||||||
void preallocateContents(uint64_t size) override;
|
void preallocateContents(uint64_t size) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
void MemorySink::createRegularFile(const Path & path, std::function<void(CreateRegularFileSink &)> func)
|
void MemorySink::createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func)
|
||||||
{
|
{
|
||||||
auto * f = dst.open(CanonPath{path}, File { File::Regular {} });
|
auto * f = dst.open(path, File { File::Regular {} });
|
||||||
if (!f)
|
if (!f)
|
||||||
throw Error("file '%s' cannot be made because some parent file is not a directory", path);
|
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)) {
|
if (auto * rp = std::get_if<File::Regular>(&f->raw)) {
|
||||||
|
@ -173,9 +173,9 @@ void CreateMemoryRegularFile::operator () (std::string_view data)
|
||||||
regularFile.contents += data;
|
regularFile.contents += data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemorySink::createSymlink(const Path & path, const std::string & target)
|
void MemorySink::createSymlink(const CanonPath & path, const std::string & target)
|
||||||
{
|
{
|
||||||
auto * f = dst.open(CanonPath{path}, File { File::Symlink { } });
|
auto * f = dst.open(path, File { File::Symlink { } });
|
||||||
if (!f)
|
if (!f)
|
||||||
throw Error("file '%s' cannot be made because some parent file is not a directory", path);
|
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))
|
if (auto * s = std::get_if<File::Symlink>(&f->raw))
|
||||||
|
|
|
@ -81,13 +81,13 @@ struct MemorySink : FileSystemObjectSink
|
||||||
|
|
||||||
MemorySink(MemorySourceAccessor & dst) : dst(dst) { }
|
MemorySink(MemorySourceAccessor & dst) : dst(dst) { }
|
||||||
|
|
||||||
void createDirectory(const Path & path) override;
|
void createDirectory(const CanonPath & path) override;
|
||||||
|
|
||||||
void createRegularFile(
|
void createRegularFile(
|
||||||
const Path & path,
|
const CanonPath & path,
|
||||||
std::function<void(CreateRegularFileSink &)>) override;
|
std::function<void(CreateRegularFileSink &)>) override;
|
||||||
|
|
||||||
void createSymlink(const Path & path, const std::string & target) override;
|
void createSymlink(const CanonPath & path, const std::string & target) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,6 +178,7 @@ time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSin
|
||||||
auto path = archive_entry_pathname(entry);
|
auto path = archive_entry_pathname(entry);
|
||||||
if (!path)
|
if (!path)
|
||||||
throw Error("cannot get archive member name: %s", archive_error_string(archive.archive));
|
throw Error("cannot get archive member name: %s", archive_error_string(archive.archive));
|
||||||
|
auto cpath = CanonPath{path};
|
||||||
if (r == ARCHIVE_WARN)
|
if (r == ARCHIVE_WARN)
|
||||||
warn(archive_error_string(archive.archive));
|
warn(archive_error_string(archive.archive));
|
||||||
else
|
else
|
||||||
|
@ -188,11 +189,11 @@ time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSin
|
||||||
switch (archive_entry_filetype(entry)) {
|
switch (archive_entry_filetype(entry)) {
|
||||||
|
|
||||||
case AE_IFDIR:
|
case AE_IFDIR:
|
||||||
parseSink.createDirectory(path);
|
parseSink.createDirectory(cpath);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AE_IFREG: {
|
case AE_IFREG: {
|
||||||
parseSink.createRegularFile(path, [&](auto & crf) {
|
parseSink.createRegularFile(cpath, [&](auto & crf) {
|
||||||
if (archive_entry_mode(entry) & S_IXUSR)
|
if (archive_entry_mode(entry) & S_IXUSR)
|
||||||
crf.isExecutable();
|
crf.isExecutable();
|
||||||
|
|
||||||
|
@ -216,7 +217,7 @@ time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSin
|
||||||
case AE_IFLNK: {
|
case AE_IFLNK: {
|
||||||
auto target = archive_entry_symlink(entry);
|
auto target = archive_entry_symlink(entry);
|
||||||
|
|
||||||
parseSink.createSymlink(path, target);
|
parseSink.createSymlink(cpath, target);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ TEST_F(GitTest, blob_read) {
|
||||||
StringSink out;
|
StringSink out;
|
||||||
RegularFileSink out2 { out };
|
RegularFileSink out2 { out };
|
||||||
ASSERT_EQ(parseObjectType(in, mockXpSettings), ObjectType::Blob);
|
ASSERT_EQ(parseObjectType(in, mockXpSettings), ObjectType::Blob);
|
||||||
parseBlob(out2, "", in, BlobMode::Regular, mockXpSettings);
|
parseBlob(out2, CanonPath{""}, in, BlobMode::Regular, mockXpSettings);
|
||||||
|
|
||||||
auto expected = readFile(goldenMaster("hello-world.bin"));
|
auto expected = readFile(goldenMaster("hello-world.bin"));
|
||||||
|
|
||||||
|
@ -132,8 +132,8 @@ TEST_F(GitTest, tree_read) {
|
||||||
NullFileSystemObjectSink out;
|
NullFileSystemObjectSink out;
|
||||||
Tree got;
|
Tree got;
|
||||||
ASSERT_EQ(parseObjectType(in, mockXpSettings), ObjectType::Tree);
|
ASSERT_EQ(parseObjectType(in, mockXpSettings), ObjectType::Tree);
|
||||||
parseTree(out, "", in, [&](auto & name, auto entry) {
|
parseTree(out, CanonPath{""}, in, [&](auto & name, auto entry) {
|
||||||
auto name2 = name;
|
auto name2 = std::string{name.rel()};
|
||||||
if (entry.mode == Mode::Directory)
|
if (entry.mode == Mode::Directory)
|
||||||
name2 += '/';
|
name2 += '/';
|
||||||
got.insert_or_assign(name2, std::move(entry));
|
got.insert_or_assign(name2, std::move(entry));
|
||||||
|
@ -210,14 +210,14 @@ TEST_F(GitTest, both_roundrip) {
|
||||||
|
|
||||||
MemorySink sinkFiles2 { *files2 };
|
MemorySink sinkFiles2 { *files2 };
|
||||||
|
|
||||||
std::function<void(const Path, const Hash &, BlobMode)> mkSinkHook;
|
std::function<void(const CanonPath, const Hash &, BlobMode)> mkSinkHook;
|
||||||
mkSinkHook = [&](auto prefix, auto & hash, auto blobMode) {
|
mkSinkHook = [&](auto prefix, auto & hash, auto blobMode) {
|
||||||
StringSource in { cas[hash] };
|
StringSource in { cas[hash] };
|
||||||
parse(
|
parse(
|
||||||
sinkFiles2, prefix, in, blobMode,
|
sinkFiles2, prefix, in, blobMode,
|
||||||
[&](const Path & name, const auto & entry) {
|
[&](const CanonPath & name, const auto & entry) {
|
||||||
mkSinkHook(
|
mkSinkHook(
|
||||||
prefix + "/" + name,
|
prefix / name,
|
||||||
entry.hash,
|
entry.hash,
|
||||||
// N.B. this cast would not be acceptable in real
|
// N.B. this cast would not be acceptable in real
|
||||||
// code, because it would make an assert reachable,
|
// code, because it would make an assert reachable,
|
||||||
|
@ -227,7 +227,7 @@ TEST_F(GitTest, both_roundrip) {
|
||||||
mockXpSettings);
|
mockXpSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
mkSinkHook("", root.hash, BlobMode::Regular);
|
mkSinkHook(CanonPath{""}, root.hash, BlobMode::Regular);
|
||||||
|
|
||||||
ASSERT_EQ(*files, *files2);
|
ASSERT_EQ(*files, *files2);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue