mirror of
https://github.com/NixOS/nix.git
synced 2025-11-08 19:46:02 +01:00
Apply clang-format universally.
* It is tough to contribute to a project that doesn't use a formatter, * It is extra hard to contribute to a project which has configured the formatter, but ignores it for some files * Code formatting makes it harder to hide obscure / weird bugs by accident or on purpose, Let's rip the bandaid off? Note that PRs currently in flight should be able to be merged relatively easily by applying `clang-format` to their tip prior to merge. Co-authored-by: Graham Christensen <graham@grahamc.com>
This commit is contained in:
parent
9b8b5d8560
commit
95d9c13716
585 changed files with 23297 additions and 23164 deletions
|
|
@ -37,23 +37,24 @@
|
|||
|
||||
namespace std {
|
||||
|
||||
template<> struct hash<git_oid>
|
||||
template<>
|
||||
struct hash<git_oid>
|
||||
{
|
||||
size_t operator()(const git_oid & oid) const
|
||||
{
|
||||
return * (size_t *) oid.id;
|
||||
return *(size_t *) oid.id;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
std::ostream & operator << (std::ostream & str, const git_oid & oid)
|
||||
std::ostream & operator<<(std::ostream & str, const git_oid & oid)
|
||||
{
|
||||
str << git_oid_tostr_s(&oid);
|
||||
return str;
|
||||
}
|
||||
|
||||
bool operator == (const git_oid & oid1, const git_oid & oid2)
|
||||
bool operator==(const git_oid & oid1, const git_oid & oid2)
|
||||
{
|
||||
return git_oid_equal(&oid1, &oid2);
|
||||
}
|
||||
|
|
@ -81,9 +82,9 @@ typedef std::unique_ptr<git_indexer, Deleter<git_indexer_free>> Indexer;
|
|||
|
||||
Hash toHash(const git_oid & oid)
|
||||
{
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
assert(oid.type == GIT_OID_SHA1);
|
||||
#endif
|
||||
#endif
|
||||
Hash hash(HashAlgorithm::SHA1);
|
||||
memcpy(hash.hash, oid.id, hash.hashSize);
|
||||
return hash;
|
||||
|
|
@ -117,7 +118,7 @@ template<typename T>
|
|||
T peelObject(git_object * obj, git_object_t type)
|
||||
{
|
||||
T obj2;
|
||||
if (git_object_peel((git_object * *) (typename T::pointer *) Setter(obj2), obj, type)) {
|
||||
if (git_object_peel((git_object **) (typename T::pointer *) Setter(obj2), obj, type)) {
|
||||
auto err = git_error_last();
|
||||
throw Error("peeling Git object '%s': %s", *git_object_id(obj), err->message);
|
||||
}
|
||||
|
|
@ -128,7 +129,7 @@ template<typename T>
|
|||
T dupObject(typename T::pointer obj)
|
||||
{
|
||||
T obj2;
|
||||
if (git_object_dup((git_object * *) (typename T::pointer *) Setter(obj2), (git_object *) obj))
|
||||
if (git_object_dup((git_object **) (typename T::pointer *) Setter(obj2), (git_object *) obj))
|
||||
throw Error("duplicating object '%s': %s", *git_object_id((git_object *) obj), git_error_last()->message);
|
||||
return obj2;
|
||||
}
|
||||
|
|
@ -147,21 +148,22 @@ static Object peelToTreeOrBlob(git_object * obj)
|
|||
return peelObject<Object>(obj, GIT_OBJECT_TREE);
|
||||
}
|
||||
|
||||
struct PackBuilderContext {
|
||||
struct PackBuilderContext
|
||||
{
|
||||
std::exception_ptr exception;
|
||||
|
||||
void handleException(const char * activity, int errCode)
|
||||
{
|
||||
switch (errCode) {
|
||||
case GIT_OK:
|
||||
break;
|
||||
case GIT_EUSER:
|
||||
if (!exception)
|
||||
panic("PackBuilderContext::handleException: user error, but exception was not set");
|
||||
case GIT_OK:
|
||||
break;
|
||||
case GIT_EUSER:
|
||||
if (!exception)
|
||||
panic("PackBuilderContext::handleException: user error, but exception was not set");
|
||||
|
||||
std::rethrow_exception(exception);
|
||||
default:
|
||||
throw Error("%s: %i, %s", Uncolored(activity), errCode, git_error_last()->message);
|
||||
std::rethrow_exception(exception);
|
||||
default:
|
||||
throw Error("%s: %i, %s", Uncolored(activity), errCode, git_error_last()->message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -171,9 +173,9 @@ extern "C" {
|
|||
/**
|
||||
* A `git_packbuilder_progress` implementation that aborts the pack building if needed.
|
||||
*/
|
||||
static int packBuilderProgressCheckInterrupt(int stage, uint32_t current, uint32_t total, void *payload)
|
||||
static int packBuilderProgressCheckInterrupt(int stage, uint32_t current, uint32_t total, void * payload)
|
||||
{
|
||||
PackBuilderContext & args = * (PackBuilderContext *) payload;
|
||||
PackBuilderContext & args = *(PackBuilderContext *) payload;
|
||||
try {
|
||||
checkInterrupt();
|
||||
return GIT_OK;
|
||||
|
|
@ -182,15 +184,17 @@ static int packBuilderProgressCheckInterrupt(int stage, uint32_t current, uint32
|
|||
return GIT_EUSER;
|
||||
}
|
||||
};
|
||||
|
||||
static git_packbuilder_progress PACKBUILDER_PROGRESS_CHECK_INTERRUPT = &packBuilderProgressCheckInterrupt;
|
||||
|
||||
} // extern "C"
|
||||
|
||||
static void initRepoAtomically(std::filesystem::path &path, bool bare)
|
||||
static void initRepoAtomically(std::filesystem::path & path, bool bare)
|
||||
{
|
||||
if (pathExists(path.string())) return;
|
||||
if (pathExists(path.string()))
|
||||
return;
|
||||
|
||||
Path tmpDir = createTempDir(os_string_to_string(PathViewNG { std::filesystem::path(path).parent_path() }));
|
||||
Path tmpDir = createTempDir(os_string_to_string(PathViewNG{std::filesystem::path(path).parent_path()}));
|
||||
AutoDelete delTmpDir(tmpDir, true);
|
||||
Repository tmpRepo;
|
||||
|
||||
|
|
@ -204,8 +208,7 @@ static void initRepoAtomically(std::filesystem::path &path, bool bare)
|
|||
// `path` may be attempted to be deleted by s::f::rename, in which case the code is:
|
||||
|| e.code() == std::errc::directory_not_empty) {
|
||||
return;
|
||||
}
|
||||
else
|
||||
} else
|
||||
throw SysError("moving temporary git repository from %s to %s", tmpDir, path);
|
||||
}
|
||||
// we successfully moved the repository, so the temporary directory no longer exists.
|
||||
|
|
@ -249,16 +252,17 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
throw Error("adding mempack backend to Git object database: %s", git_error_last()->message);
|
||||
}
|
||||
|
||||
operator git_repository * ()
|
||||
operator git_repository *()
|
||||
{
|
||||
return repo.get();
|
||||
}
|
||||
|
||||
void flush() override {
|
||||
void flush() override
|
||||
{
|
||||
checkInterrupt();
|
||||
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
Finally _disposeBuf { [&] { git_buf_dispose(&buf); } };
|
||||
Finally _disposeBuf{[&] { git_buf_dispose(&buf); }};
|
||||
PackBuilder packBuilder;
|
||||
PackBuilderContext packBuilderContext;
|
||||
git_packbuilder_new(Setter(packBuilder), *this);
|
||||
|
|
@ -266,14 +270,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
git_packbuilder_set_threads(packBuilder.get(), 0 /* autodetect */);
|
||||
|
||||
packBuilderContext.handleException(
|
||||
"preparing packfile",
|
||||
git_mempack_write_thin_pack(mempack_backend, packBuilder.get())
|
||||
);
|
||||
"preparing packfile", git_mempack_write_thin_pack(mempack_backend, packBuilder.get()));
|
||||
checkInterrupt();
|
||||
packBuilderContext.handleException(
|
||||
"writing packfile",
|
||||
git_packbuilder_write_buf(&buf, packBuilder.get())
|
||||
);
|
||||
packBuilderContext.handleException("writing packfile", git_packbuilder_write_buf(&buf, packBuilder.get()));
|
||||
checkInterrupt();
|
||||
|
||||
std::string repo_path = std::string(git_repository_path(repo.get()));
|
||||
|
|
@ -318,7 +317,8 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
todo.push(peelObject<Commit>(lookupObject(*this, hashToOID(rev)).get(), GIT_OBJECT_COMMIT));
|
||||
|
||||
while (auto commit = pop(todo)) {
|
||||
if (!done.insert(*git_commit_id(commit->get())).second) continue;
|
||||
if (!done.insert(*git_commit_id(commit->get())).second)
|
||||
continue;
|
||||
|
||||
for (size_t n = 0; n < git_commit_parentcount(commit->get()); ++n) {
|
||||
git_commit * parent;
|
||||
|
|
@ -330,8 +330,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
"or add set the shallow parameter to true in builtins.fetchGit, "
|
||||
"or fetch the complete history for this branch.",
|
||||
*git_commit_id(commit->get()),
|
||||
git_error_last()->message
|
||||
);
|
||||
git_error_last()->message);
|
||||
}
|
||||
todo.push(Commit(parent));
|
||||
}
|
||||
|
|
@ -382,7 +381,8 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
while (true) {
|
||||
git_config_entry * entry = nullptr;
|
||||
if (auto err = git_config_next(&entry, it.get())) {
|
||||
if (err == GIT_ITEROVER) break;
|
||||
if (err == GIT_ITEROVER)
|
||||
break;
|
||||
throw Error("iterating over .gitmodules: %s", git_error_last()->message);
|
||||
}
|
||||
entries.emplace(entry->name + 10, entry->value);
|
||||
|
|
@ -391,14 +391,16 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
std::vector<Submodule> result;
|
||||
|
||||
for (auto & [key, value] : entries) {
|
||||
if (!hasSuffix(key, ".path")) continue;
|
||||
if (!hasSuffix(key, ".path"))
|
||||
continue;
|
||||
std::string key2(key, 0, key.size() - 5);
|
||||
auto path = CanonPath(value);
|
||||
result.push_back(Submodule {
|
||||
.path = path,
|
||||
.url = entries[key2 + ".url"],
|
||||
.branch = entries[key2 + ".branch"],
|
||||
});
|
||||
result.push_back(
|
||||
Submodule{
|
||||
.path = path,
|
||||
.url = entries[key2 + ".url"],
|
||||
.branch = entries[key2 + ".branch"],
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -424,11 +426,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
|
||||
/* Get all tracked files and determine whether the working
|
||||
directory is dirty. */
|
||||
std::function<int(const char * path, unsigned int statusFlags)> statusCallback = [&](const char * path, unsigned int statusFlags)
|
||||
{
|
||||
if (!(statusFlags & GIT_STATUS_INDEX_DELETED) &&
|
||||
!(statusFlags & GIT_STATUS_WT_DELETED))
|
||||
{
|
||||
std::function<int(const char * path, unsigned int statusFlags)> statusCallback = [&](const char * path,
|
||||
unsigned int statusFlags) {
|
||||
if (!(statusFlags & GIT_STATUS_INDEX_DELETED) && !(statusFlags & GIT_STATUS_WT_DELETED)) {
|
||||
info.files.insert(CanonPath(path));
|
||||
if (statusFlags != GIT_STATUS_CURRENT)
|
||||
info.dirtyFiles.insert(CanonPath(path));
|
||||
|
|
@ -484,7 +484,8 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
|
||||
Object obj;
|
||||
if (auto errCode = git_object_lookup(Setter(obj), *this, &oid, GIT_OBJECT_ANY)) {
|
||||
if (errCode == GIT_ENOTFOUND) return false;
|
||||
if (errCode == GIT_ENOTFOUND)
|
||||
return false;
|
||||
auto err = git_error_last();
|
||||
throw Error("getting Git object '%s': %s", oid, err->message);
|
||||
}
|
||||
|
|
@ -495,15 +496,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
/**
|
||||
* A 'GitSourceAccessor' with no regard for export-ignore or any other transformations.
|
||||
*/
|
||||
ref<GitSourceAccessor> getRawAccessor(
|
||||
const Hash & rev,
|
||||
bool smudgeLfs = false);
|
||||
ref<GitSourceAccessor> getRawAccessor(const Hash & rev, bool smudgeLfs = false);
|
||||
|
||||
ref<SourceAccessor> getAccessor(
|
||||
const Hash & rev,
|
||||
bool exportIgnore,
|
||||
std::string displayPrefix,
|
||||
bool smudgeLfs = false) override;
|
||||
ref<SourceAccessor>
|
||||
getAccessor(const Hash & rev, bool exportIgnore, std::string displayPrefix, bool smudgeLfs = false) override;
|
||||
|
||||
ref<SourceAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError e) override;
|
||||
|
||||
|
|
@ -519,7 +515,8 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
static int transferProgressCallback(const git_indexer_progress * stats, void * payload)
|
||||
{
|
||||
auto act = (Activity *) payload;
|
||||
act->result(resFetchStatus,
|
||||
act->result(
|
||||
resFetchStatus,
|
||||
fmt("%d/%d objects received, %d/%d deltas indexed, %.1f MiB",
|
||||
stats->received_objects,
|
||||
stats->total_objects,
|
||||
|
|
@ -529,14 +526,12 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
return getInterrupted() ? -1 : 0;
|
||||
}
|
||||
|
||||
void fetch(
|
||||
const std::string & url,
|
||||
const std::string & refspec,
|
||||
bool shallow) override
|
||||
void fetch(const std::string & url, const std::string & refspec, bool shallow) override
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actFetchTree, fmt("fetching Git repository '%s'", url));
|
||||
|
||||
// TODO: implement git-credential helper support (preferably via libgit2, which as of 2024-01 does not support that)
|
||||
// TODO: implement git-credential helper support (preferably via libgit2, which as of 2024-01 does not support
|
||||
// that)
|
||||
// then use code that was removed in this commit (see blame)
|
||||
|
||||
auto dir = this->path;
|
||||
|
|
@ -545,55 +540,52 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
append(gitArgs, {"--depth", "1"});
|
||||
append(gitArgs, {std::string("--"), url, refspec});
|
||||
|
||||
runProgram(RunOptions {
|
||||
.program = "git",
|
||||
.lookupPath = true,
|
||||
// FIXME: git stderr messes up our progress indicator, so
|
||||
// we're using --quiet for now. Should process its stderr.
|
||||
.args = gitArgs,
|
||||
.input = {},
|
||||
.isInteractive = true
|
||||
});
|
||||
runProgram(
|
||||
RunOptions{
|
||||
.program = "git",
|
||||
.lookupPath = true,
|
||||
// FIXME: git stderr messes up our progress indicator, so
|
||||
// we're using --quiet for now. Should process its stderr.
|
||||
.args = gitArgs,
|
||||
.input = {},
|
||||
.isInteractive = true});
|
||||
}
|
||||
|
||||
void verifyCommit(
|
||||
const Hash & rev,
|
||||
const std::vector<fetchers::PublicKey> & publicKeys) override
|
||||
void verifyCommit(const Hash & rev, const std::vector<fetchers::PublicKey> & publicKeys) override
|
||||
{
|
||||
// Create ad-hoc allowedSignersFile and populate it with publicKeys
|
||||
auto allowedSignersFile = createTempFile().second;
|
||||
std::string allowedSigners;
|
||||
for (const fetchers::PublicKey & k : publicKeys) {
|
||||
if (k.type != "ssh-dsa"
|
||||
&& k.type != "ssh-ecdsa"
|
||||
&& k.type != "ssh-ecdsa-sk"
|
||||
&& k.type != "ssh-ed25519"
|
||||
&& k.type != "ssh-ed25519-sk"
|
||||
&& k.type != "ssh-rsa")
|
||||
throw Error("Unknown key type '%s'.\n"
|
||||
if (k.type != "ssh-dsa" && k.type != "ssh-ecdsa" && k.type != "ssh-ecdsa-sk" && k.type != "ssh-ed25519"
|
||||
&& k.type != "ssh-ed25519-sk" && k.type != "ssh-rsa")
|
||||
throw Error(
|
||||
"Unknown key type '%s'.\n"
|
||||
"Please use one of\n"
|
||||
"- ssh-dsa\n"
|
||||
" ssh-ecdsa\n"
|
||||
" ssh-ecdsa-sk\n"
|
||||
" ssh-ed25519\n"
|
||||
" ssh-ed25519-sk\n"
|
||||
" ssh-rsa", k.type);
|
||||
" ssh-rsa",
|
||||
k.type);
|
||||
allowedSigners += "* " + k.type + " " + k.key + "\n";
|
||||
}
|
||||
writeFile(allowedSignersFile, allowedSigners);
|
||||
|
||||
// Run verification command
|
||||
auto [status, output] = runProgram(RunOptions {
|
||||
auto [status, output] = runProgram(
|
||||
RunOptions{
|
||||
.program = "git",
|
||||
.args = {
|
||||
"-c",
|
||||
"gpg.ssh.allowedSignersFile=" + allowedSignersFile,
|
||||
"-C", path.string(),
|
||||
"verify-commit",
|
||||
rev.gitRev()
|
||||
},
|
||||
.args =
|
||||
{"-c",
|
||||
"gpg.ssh.allowedSignersFile=" + allowedSignersFile,
|
||||
"-C",
|
||||
path.string(),
|
||||
"verify-commit",
|
||||
rev.gitRev()},
|
||||
.mergeStderrToStdout = true,
|
||||
});
|
||||
});
|
||||
|
||||
/* Evaluate result through status code and checking if public
|
||||
key fingerprints appear on stderr. This is necessary
|
||||
|
|
@ -601,7 +593,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
commit being signed by gpg keys that are present in the
|
||||
users key agent. */
|
||||
std::string re = R"(Good "git" signature for \* with .* key SHA256:[)";
|
||||
for (const fetchers::PublicKey & k : publicKeys){
|
||||
for (const fetchers::PublicKey & k : publicKeys) {
|
||||
// Calculate sha256 fingerprint from public key and escape the regex symbol '+' to match the key literally
|
||||
std::string keyDecoded;
|
||||
try {
|
||||
|
|
@ -609,8 +601,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
} catch (Error & e) {
|
||||
e.addTrace({}, "while decoding public key '%s' used for git signature", k.key);
|
||||
}
|
||||
auto fingerprint = trim(hashString(HashAlgorithm::SHA256, keyDecoded).to_string(nix::HashFormat::Base64, false), "=");
|
||||
auto escaped_fingerprint = std::regex_replace(fingerprint, std::regex("\\+"), "\\+" );
|
||||
auto fingerprint =
|
||||
trim(hashString(HashAlgorithm::SHA256, keyDecoded).to_string(nix::HashFormat::Base64, false), "=");
|
||||
auto escaped_fingerprint = std::regex_replace(fingerprint, std::regex("\\+"), "\\+");
|
||||
re += "(" + escaped_fingerprint + ")";
|
||||
}
|
||||
re += "]";
|
||||
|
|
@ -675,13 +668,11 @@ struct GitSourceAccessor : SourceAccessor
|
|||
Sync<State> state_;
|
||||
|
||||
GitSourceAccessor(ref<GitRepoImpl> repo_, const Hash & rev, bool smudgeLfs)
|
||||
: state_{
|
||||
State {
|
||||
.repo = repo_,
|
||||
.root = peelToTreeOrBlob(lookupObject(*repo_, hashToOID(rev)).get()),
|
||||
.lfsFetch = smudgeLfs ? std::make_optional(lfs::Fetch(*repo_, hashToOID(rev))) : std::nullopt,
|
||||
}
|
||||
}
|
||||
: state_{State{
|
||||
.repo = repo_,
|
||||
.root = peelToTreeOrBlob(lookupObject(*repo_, hashToOID(rev)).get()),
|
||||
.lfsFetch = smudgeLfs ? std::make_optional(lfs::Fetch(*repo_, hashToOID(rev))) : std::nullopt,
|
||||
}}
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -697,8 +688,9 @@ struct GitSourceAccessor : SourceAccessor
|
|||
try {
|
||||
// FIXME: do we need to hold the state lock while
|
||||
// doing this?
|
||||
auto contents = std::string((const char *) git_blob_rawcontent(blob.get()), git_blob_rawsize(blob.get()));
|
||||
state->lfsFetch->fetch(contents, path, s, [&s](uint64_t size){ s.s.reserve(size); });
|
||||
auto contents =
|
||||
std::string((const char *) git_blob_rawcontent(blob.get()), git_blob_rawsize(blob.get()));
|
||||
state->lfsFetch->fetch(contents, path, s, [&s](uint64_t size) { s.s.reserve(size); });
|
||||
} catch (Error & e) {
|
||||
e.addTrace({}, "while smudging git-lfs file '%s'", path);
|
||||
throw;
|
||||
|
|
@ -726,7 +718,7 @@ struct GitSourceAccessor : SourceAccessor
|
|||
auto state(state_.lock());
|
||||
|
||||
if (path.isRoot())
|
||||
return Stat { .type = git_object_type(state->root.get()) == GIT_OBJECT_TREE ? tDirectory : tRegular };
|
||||
return Stat{.type = git_object_type(state->root.get()) == GIT_OBJECT_TREE ? tDirectory : tRegular};
|
||||
|
||||
auto entry = lookup(*state, path);
|
||||
if (!entry)
|
||||
|
|
@ -735,20 +727,20 @@ struct GitSourceAccessor : SourceAccessor
|
|||
auto mode = git_tree_entry_filemode(entry);
|
||||
|
||||
if (mode == GIT_FILEMODE_TREE)
|
||||
return Stat { .type = tDirectory };
|
||||
return Stat{.type = tDirectory};
|
||||
|
||||
else if (mode == GIT_FILEMODE_BLOB)
|
||||
return Stat { .type = tRegular };
|
||||
return Stat{.type = tRegular};
|
||||
|
||||
else if (mode == GIT_FILEMODE_BLOB_EXECUTABLE)
|
||||
return Stat { .type = tRegular, .isExecutable = true };
|
||||
return Stat{.type = tRegular, .isExecutable = true};
|
||||
|
||||
else if (mode == GIT_FILEMODE_LINK)
|
||||
return Stat { .type = tSymlink };
|
||||
return Stat{.type = tSymlink};
|
||||
|
||||
else if (mode == GIT_FILEMODE_COMMIT)
|
||||
// Treat submodules as an empty directory.
|
||||
return Stat { .type = tDirectory };
|
||||
return Stat{.type = tDirectory};
|
||||
|
||||
else
|
||||
throw Error("file '%s' has an unsupported Git file type");
|
||||
|
|
@ -758,24 +750,23 @@ struct GitSourceAccessor : SourceAccessor
|
|||
{
|
||||
auto state(state_.lock());
|
||||
|
||||
return std::visit(overloaded {
|
||||
[&](Tree tree) {
|
||||
DirEntries res;
|
||||
return std::visit(
|
||||
overloaded{
|
||||
[&](Tree tree) {
|
||||
DirEntries res;
|
||||
|
||||
auto count = git_tree_entrycount(tree.get());
|
||||
auto count = git_tree_entrycount(tree.get());
|
||||
|
||||
for (size_t n = 0; n < count; ++n) {
|
||||
auto entry = git_tree_entry_byindex(tree.get(), n);
|
||||
// FIXME: add to cache
|
||||
res.emplace(std::string(git_tree_entry_name(entry)), DirEntry{});
|
||||
}
|
||||
for (size_t n = 0; n < count; ++n) {
|
||||
auto entry = git_tree_entry_byindex(tree.get(), n);
|
||||
// FIXME: add to cache
|
||||
res.emplace(std::string(git_tree_entry_name(entry)), DirEntry{});
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
[&](Submodule) {
|
||||
return DirEntries();
|
||||
}
|
||||
}, getTree(*state, path));
|
||||
return res;
|
||||
},
|
||||
[&](Submodule) { return DirEntries(); }},
|
||||
getTree(*state, path));
|
||||
}
|
||||
|
||||
std::string readLink(const CanonPath & path) override
|
||||
|
|
@ -805,15 +796,18 @@ struct GitSourceAccessor : SourceAccessor
|
|||
git_tree_entry * lookup(State & state, const CanonPath & path)
|
||||
{
|
||||
auto i = lookupCache.find(path);
|
||||
if (i != lookupCache.end()) return i->second.get();
|
||||
if (i != lookupCache.end())
|
||||
return i->second.get();
|
||||
|
||||
auto parent = path.parent();
|
||||
if (!parent) return nullptr;
|
||||
if (!parent)
|
||||
return nullptr;
|
||||
|
||||
auto name = path.baseName().value();
|
||||
|
||||
auto parentTree = lookupTree(state, *parent);
|
||||
if (!parentTree) return nullptr;
|
||||
if (!parentTree)
|
||||
return nullptr;
|
||||
|
||||
auto count = git_tree_entrycount(parentTree->get());
|
||||
|
||||
|
|
@ -855,7 +849,7 @@ struct GitSourceAccessor : SourceAccessor
|
|||
return std::nullopt;
|
||||
|
||||
Tree tree;
|
||||
if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(tree), *state.repo, entry))
|
||||
if (git_tree_entry_to_object((git_object **) (git_tree **) Setter(tree), *state.repo, entry))
|
||||
throw Error("looking up directory '%s': %s", showPath(path), git_error_last()->message);
|
||||
|
||||
return tree;
|
||||
|
|
@ -869,7 +863,8 @@ struct GitSourceAccessor : SourceAccessor
|
|||
return entry;
|
||||
}
|
||||
|
||||
struct Submodule { };
|
||||
struct Submodule
|
||||
{};
|
||||
|
||||
std::variant<Tree, Submodule> getTree(State & state, const CanonPath & path)
|
||||
{
|
||||
|
|
@ -889,7 +884,7 @@ struct GitSourceAccessor : SourceAccessor
|
|||
throw Error("'%s' is not a directory", showPath(path));
|
||||
|
||||
Tree tree;
|
||||
if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(tree), *state.repo, entry))
|
||||
if (git_tree_entry_to_object((git_object **) (git_tree **) Setter(tree), *state.repo, entry))
|
||||
throw Error("looking up directory '%s': %s", showPath(path), git_error_last()->message);
|
||||
|
||||
return tree;
|
||||
|
|
@ -900,16 +895,12 @@ struct GitSourceAccessor : SourceAccessor
|
|||
if (!expectSymlink && git_object_type(state.root.get()) == GIT_OBJECT_BLOB)
|
||||
return dupObject<Blob>((git_blob *) &*state.root);
|
||||
|
||||
auto notExpected = [&]()
|
||||
{
|
||||
throw Error(
|
||||
expectSymlink
|
||||
? "'%s' is not a symlink"
|
||||
: "'%s' is not a regular file",
|
||||
showPath(path));
|
||||
auto notExpected = [&]() {
|
||||
throw Error(expectSymlink ? "'%s' is not a symlink" : "'%s' is not a regular file", showPath(path));
|
||||
};
|
||||
|
||||
if (path.isRoot()) notExpected();
|
||||
if (path.isRoot())
|
||||
notExpected();
|
||||
|
||||
auto entry = need(state, path);
|
||||
|
||||
|
|
@ -926,26 +917,31 @@ struct GitSourceAccessor : SourceAccessor
|
|||
}
|
||||
|
||||
Blob blob;
|
||||
if (git_tree_entry_to_object((git_object * *) (git_blob * *) Setter(blob), *state.repo, entry))
|
||||
if (git_tree_entry_to_object((git_object **) (git_blob **) Setter(blob), *state.repo, entry))
|
||||
throw Error("looking up file '%s': %s", showPath(path), git_error_last()->message);
|
||||
|
||||
return blob;
|
||||
}
|
||||
};
|
||||
|
||||
struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor {
|
||||
struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor
|
||||
{
|
||||
ref<GitRepoImpl> repo;
|
||||
std::optional<Hash> rev;
|
||||
|
||||
GitExportIgnoreSourceAccessor(ref<GitRepoImpl> repo, ref<SourceAccessor> next, std::optional<Hash> rev)
|
||||
: CachingFilteringSourceAccessor(next, [&](const CanonPath & path) {
|
||||
return RestrictedPathError(fmt("'%s' does not exist because it was fetched with exportIgnore enabled", path));
|
||||
})
|
||||
: CachingFilteringSourceAccessor(
|
||||
next,
|
||||
[&](const CanonPath & path) {
|
||||
return RestrictedPathError(
|
||||
fmt("'%s' does not exist because it was fetched with exportIgnore enabled", path));
|
||||
})
|
||||
, repo(repo)
|
||||
, rev(rev)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
bool gitAttrGet(const CanonPath & path, const char * attrName, const char * & valueOut)
|
||||
bool gitAttrGet(const CanonPath & path, const char * attrName, const char *& valueOut)
|
||||
{
|
||||
const char * pathCStr = path.rel_c_str();
|
||||
|
||||
|
|
@ -955,27 +951,16 @@ struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor {
|
|||
// TODO: test that gitattributes from global and system are not used
|
||||
// (ie more or less: home and etc - both of them!)
|
||||
opts.flags = GIT_ATTR_CHECK_INCLUDE_COMMIT | GIT_ATTR_CHECK_NO_SYSTEM;
|
||||
return git_attr_get_ext(
|
||||
&valueOut,
|
||||
*repo,
|
||||
&opts,
|
||||
pathCStr,
|
||||
attrName
|
||||
);
|
||||
}
|
||||
else {
|
||||
return git_attr_get_ext(&valueOut, *repo, &opts, pathCStr, attrName);
|
||||
} else {
|
||||
return git_attr_get(
|
||||
&valueOut,
|
||||
*repo,
|
||||
GIT_ATTR_CHECK_INDEX_ONLY | GIT_ATTR_CHECK_NO_SYSTEM,
|
||||
pathCStr,
|
||||
attrName);
|
||||
&valueOut, *repo, GIT_ATTR_CHECK_INDEX_ONLY | GIT_ATTR_CHECK_NO_SYSTEM, pathCStr, attrName);
|
||||
}
|
||||
}
|
||||
|
||||
bool isExportIgnored(const CanonPath & path)
|
||||
{
|
||||
const char *exportIgnoreEntry = nullptr;
|
||||
const char * exportIgnoreEntry = nullptr;
|
||||
|
||||
// GIT_ATTR_CHECK_INDEX_ONLY:
|
||||
// > It will use index only for creating archives or for a bare repo
|
||||
|
|
@ -986,8 +971,7 @@ struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor {
|
|||
return false;
|
||||
else
|
||||
throw Error("looking up '%s': %s", showPath(path), git_error_last()->message);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Official git will silently reject export-ignore lines that have
|
||||
// values. We do the same.
|
||||
return GIT_ATTR_IS_TRUE(exportIgnoreEntry);
|
||||
|
|
@ -998,7 +982,6 @@ struct GitExportIgnoreSourceAccessor : CachingFilteringSourceAccessor {
|
|||
{
|
||||
return !isExportIgnored(path);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
||||
|
|
@ -1018,26 +1001,25 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
|||
const git_tree_entry * entry;
|
||||
Tree prevTree = nullptr;
|
||||
|
||||
if (!pendingDirs.empty() &&
|
||||
(entry = git_treebuilder_get(pendingDirs.back().builder.get(), name.c_str())))
|
||||
{
|
||||
if (!pendingDirs.empty() && (entry = git_treebuilder_get(pendingDirs.back().builder.get(), name.c_str()))) {
|
||||
/* Clone a tree that we've already finished. This happens
|
||||
if a tarball has directory entries that are not
|
||||
contiguous. */
|
||||
if (git_tree_entry_type(entry) != GIT_OBJECT_TREE)
|
||||
throw Error("parent of '%s' is not a directory", name);
|
||||
|
||||
if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(prevTree), *repo, entry))
|
||||
if (git_tree_entry_to_object((git_object **) (git_tree **) Setter(prevTree), *repo, entry))
|
||||
throw Error("looking up parent of '%s': %s", name, git_error_last()->message);
|
||||
}
|
||||
|
||||
git_treebuilder * b;
|
||||
if (git_treebuilder_new(&b, *repo, prevTree.get()))
|
||||
throw Error("creating a tree builder: %s", git_error_last()->message);
|
||||
pendingDirs.push_back({ .name = std::move(name), .builder = TreeBuilder(b) });
|
||||
pendingDirs.push_back({.name = std::move(name), .builder = TreeBuilder(b)});
|
||||
};
|
||||
|
||||
GitFileSystemObjectSinkImpl(ref<GitRepoImpl> repo) : repo(repo)
|
||||
GitFileSystemObjectSinkImpl(ref<GitRepoImpl> repo)
|
||||
: repo(repo)
|
||||
{
|
||||
pushBuilder("");
|
||||
}
|
||||
|
|
@ -1084,53 +1066,54 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
|||
{
|
||||
std::span<const std::string> pathComponents2{pathComponents};
|
||||
|
||||
updateBuilders(
|
||||
isDir
|
||||
? pathComponents2
|
||||
: pathComponents2.first(pathComponents2.size() - 1));
|
||||
updateBuilders(isDir ? pathComponents2 : pathComponents2.first(pathComponents2.size() - 1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void createRegularFile(
|
||||
const CanonPath & path,
|
||||
std::function<void(CreateRegularFileSink &)> func) override
|
||||
void createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func) override
|
||||
{
|
||||
auto pathComponents = tokenizeString<std::vector<std::string>>(path.rel(), "/");
|
||||
if (!prepareDirs(pathComponents, false)) return;
|
||||
if (!prepareDirs(pathComponents, false))
|
||||
return;
|
||||
|
||||
git_writestream * stream = nullptr;
|
||||
if (git_blob_create_from_stream(&stream, *repo, nullptr))
|
||||
throw Error("creating a blob stream object: %s", git_error_last()->message);
|
||||
|
||||
struct CRF : CreateRegularFileSink {
|
||||
struct CRF : CreateRegularFileSink
|
||||
{
|
||||
const CanonPath & path;
|
||||
GitFileSystemObjectSinkImpl & back;
|
||||
git_writestream * stream;
|
||||
bool executable = false;
|
||||
|
||||
CRF(const CanonPath & path, GitFileSystemObjectSinkImpl & back, git_writestream * stream)
|
||||
: path(path), back(back), stream(stream)
|
||||
{}
|
||||
void operator () (std::string_view data) override
|
||||
: path(path)
|
||||
, back(back)
|
||||
, stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(std::string_view data) override
|
||||
{
|
||||
if (stream->write(stream, data.data(), data.size()))
|
||||
throw Error("writing a blob for tarball member '%s': %s", path, git_error_last()->message);
|
||||
}
|
||||
|
||||
void isExecutable() override
|
||||
{
|
||||
executable = true;
|
||||
}
|
||||
} crf { path, *this, stream };
|
||||
} crf{path, *this, stream};
|
||||
|
||||
func(crf);
|
||||
|
||||
git_oid oid;
|
||||
if (git_blob_create_from_stream_commit(&oid, stream))
|
||||
throw Error("creating a blob object for tarball member '%s': %s", path, git_error_last()->message);
|
||||
|
||||
addToTree(*pathComponents.rbegin(), oid,
|
||||
crf.executable
|
||||
? GIT_FILEMODE_BLOB_EXECUTABLE
|
||||
: GIT_FILEMODE_BLOB);
|
||||
addToTree(*pathComponents.rbegin(), oid, crf.executable ? GIT_FILEMODE_BLOB_EXECUTABLE : GIT_FILEMODE_BLOB);
|
||||
}
|
||||
|
||||
void createDirectory(const CanonPath & path) override
|
||||
|
|
@ -1142,7 +1125,8 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
|||
void createSymlink(const CanonPath & path, const std::string & target) override
|
||||
{
|
||||
auto pathComponents = tokenizeString<std::vector<std::string>>(path.rel(), "/");
|
||||
if (!prepareDirs(pathComponents, false)) return;
|
||||
if (!prepareDirs(pathComponents, false))
|
||||
return;
|
||||
|
||||
git_oid oid;
|
||||
if (git_blob_create_from_buffer(&oid, *repo, target.c_str(), target.size()))
|
||||
|
|
@ -1157,7 +1141,8 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
|||
for (auto & c : path)
|
||||
pathComponents.emplace_back(c);
|
||||
|
||||
if (!prepareDirs(pathComponents, false)) return;
|
||||
if (!prepareDirs(pathComponents, false))
|
||||
return;
|
||||
|
||||
// We can't just look up the path from the start of the root, since
|
||||
// some parent directories may not have finished yet, so we compute
|
||||
|
|
@ -1201,9 +1186,7 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
|||
|
||||
assert(entry);
|
||||
|
||||
addToTree(*pathComponents.rbegin(),
|
||||
*git_tree_entry_id(entry),
|
||||
git_tree_entry_filemode(entry));
|
||||
addToTree(*pathComponents.rbegin(), *git_tree_entry_id(entry), git_tree_entry_filemode(entry));
|
||||
}
|
||||
|
||||
Hash flush() override
|
||||
|
|
@ -1218,19 +1201,14 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
|||
}
|
||||
};
|
||||
|
||||
ref<GitSourceAccessor> GitRepoImpl::getRawAccessor(
|
||||
const Hash & rev,
|
||||
bool smudgeLfs)
|
||||
ref<GitSourceAccessor> GitRepoImpl::getRawAccessor(const Hash & rev, bool smudgeLfs)
|
||||
{
|
||||
auto self = ref<GitRepoImpl>(shared_from_this());
|
||||
return make_ref<GitSourceAccessor>(self, rev, smudgeLfs);
|
||||
}
|
||||
|
||||
ref<SourceAccessor> GitRepoImpl::getAccessor(
|
||||
const Hash & rev,
|
||||
bool exportIgnore,
|
||||
std::string displayPrefix,
|
||||
bool smudgeLfs)
|
||||
ref<SourceAccessor>
|
||||
GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore, std::string displayPrefix, bool smudgeLfs)
|
||||
{
|
||||
auto self = ref<GitRepoImpl>(shared_from_this());
|
||||
ref<GitSourceAccessor> rawGitAccessor = getRawAccessor(rev, smudgeLfs);
|
||||
|
|
@ -1241,16 +1219,17 @@ ref<SourceAccessor> GitRepoImpl::getAccessor(
|
|||
return rawGitAccessor;
|
||||
}
|
||||
|
||||
ref<SourceAccessor> GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError)
|
||||
ref<SourceAccessor>
|
||||
GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError)
|
||||
{
|
||||
auto self = ref<GitRepoImpl>(shared_from_this());
|
||||
ref<SourceAccessor> fileAccessor =
|
||||
AllowListSourceAccessor::create(
|
||||
makeFSSourceAccessor(path),
|
||||
std::set<CanonPath>{ wd.files },
|
||||
// Always allow access to the root, but not its children.
|
||||
std::unordered_set<CanonPath>{CanonPath::root},
|
||||
std::move(makeNotAllowedError)).cast<SourceAccessor>();
|
||||
ref<SourceAccessor> fileAccessor = AllowListSourceAccessor::create(
|
||||
makeFSSourceAccessor(path),
|
||||
std::set<CanonPath>{wd.files},
|
||||
// Always allow access to the root, but not its children.
|
||||
std::unordered_set<CanonPath>{CanonPath::root},
|
||||
std::move(makeNotAllowedError))
|
||||
.cast<SourceAccessor>();
|
||||
if (exportIgnore)
|
||||
return make_ref<GitExportIgnoreSourceAccessor>(self, fileAccessor, std::nullopt);
|
||||
else
|
||||
|
|
@ -1268,7 +1247,8 @@ std::vector<std::tuple<GitRepoImpl::Submodule, Hash>> GitRepoImpl::getSubmodules
|
|||
CanonPath modulesFile(".gitmodules");
|
||||
|
||||
auto accessor = getAccessor(rev, exportIgnore, "");
|
||||
if (!accessor->pathExists(modulesFile)) return {};
|
||||
if (!accessor->pathExists(modulesFile))
|
||||
return {};
|
||||
|
||||
/* Parse it and get the revision of each submodule. */
|
||||
auto configS = accessor->readFile(modulesFile);
|
||||
|
|
@ -1308,11 +1288,12 @@ GitRepo::WorkdirInfo GitRepo::getCachedWorkdirInfo(const std::filesystem::path &
|
|||
{
|
||||
auto cache(_cache.lock());
|
||||
auto i = cache->find(path);
|
||||
if (i != cache->end()) return i->second;
|
||||
if (i != cache->end())
|
||||
return i->second;
|
||||
}
|
||||
auto workdirInfo = GitRepo::openRepo(path)->getWorkdirInfo();
|
||||
_cache.lock()->emplace(path, workdirInfo);
|
||||
return workdirInfo;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace nix
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue