1
1
Fork 0
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:
Sergei Zimmerman 2025-07-18 22:25:33 +03:00
parent 9b8b5d8560
commit 95d9c13716
No known key found for this signature in database
585 changed files with 23297 additions and 23164 deletions

View file

@ -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