diff options
Diffstat (limited to 'src/buildtool/file_system/git_repo.cpp')
-rw-r--r-- | src/buildtool/file_system/git_repo.cpp | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/src/buildtool/file_system/git_repo.cpp b/src/buildtool/file_system/git_repo.cpp index 9fe63fb6..2df31960 100644 --- a/src/buildtool/file_system/git_repo.cpp +++ b/src/buildtool/file_system/git_repo.cpp @@ -16,6 +16,7 @@ #include <thread> +#include "src/buildtool/file_system/file_system_manager.hpp" #include "src/buildtool/logging/logger.hpp" #include "src/utils/cpp/gsl.hpp" #include "src/utils/cpp/hex_string.hpp" @@ -353,9 +354,15 @@ GitRepo::GitRepo(std::filesystem::path const& repo_path) noexcept { } cas->odb_.reset(odb_ptr); // retain odb pointer is_repo_fake_ = false; - // save root path - cas->git_path_ = ToNormalPath(std::filesystem::absolute( - std::filesystem::path(git_repository_path(repo_->Ptr())))); + // save root path; this differs if repository is bare or not + if (git_repository_is_bare(repo_->Ptr()) != 0) { + cas->git_path_ = std::filesystem::absolute( + ToNormalPath(git_repository_path(repo_->Ptr()))); + } + else { + cas->git_path_ = std::filesystem::absolute( + ToNormalPath(git_repository_workdir(repo_->Ptr()))); + } // retain the pointer git_cas_ = std::static_pointer_cast<GitCAS const>(cas); } catch (std::exception const& ex) { @@ -477,19 +484,32 @@ auto GitRepo::StageAndCommitAllAnonymous(std::string const& message, // share the odb lock std::shared_lock lock{GetGitCAS()->mutex_}; + // cannot perform this operation on a bare repository; this has to be + // checked because git_index_add_bypath will not do it for us! + if (not FileSystemManager::Exists(GetGitCAS()->git_path_ / ".git")) { + (*logger)("cannot stage and commit files in a bare repository!", + true /*fatal*/); + return std::nullopt; + } + // add all files to be staged git_index* index_ptr{nullptr}; git_repository_index(&index_ptr, repo_->Ptr()); auto index = std::unique_ptr<git_index, decltype(&index_closer)>( index_ptr, index_closer); - git_strarray array_obj{}; - PopulateStrarray(&array_obj, {"."}); - auto array = std::unique_ptr<git_strarray, decltype(&strarray_deleter)>( - &array_obj, strarray_deleter); - - if (git_index_add_all(index.get(), array.get(), 0, nullptr, nullptr) != - 0) { + // due to mismanagement of .gitignore rules by libgit2 when doing a + // forced add all, we resort to using git_index_add_bypath manually for + // all entries, instead of git_index_add_all with GIT_INDEX_ADD_FORCE. + auto use_entry = [&index](std::filesystem::path const& name, + bool is_tree) { + return is_tree or + git_index_add_bypath(index.get(), name.c_str()) == 0; + }; + if (not FileSystemManager::ReadDirectoryEntriesRecursive( + GetGitCAS()->git_path_, + use_entry, + /*ignored_subdirs=*/{".git"})) { (*logger)(fmt::format( "staging files in git repository {} failed with:\n{}", GetGitCAS()->git_path_.string(), @@ -497,8 +517,6 @@ auto GitRepo::StageAndCommitAllAnonymous(std::string const& message, true /*fatal*/); return std::nullopt; } - // release unused resources - array.reset(nullptr); // build tree from staged files git_oid tree_oid; if (git_index_write_tree(&tree_oid, index.get()) != 0) { |