diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/file_system/TARGETS | 1 | ||||
-rw-r--r-- | src/buildtool/file_system/git_cas.cpp | 11 | ||||
-rw-r--r-- | src/buildtool/file_system/git_repo.cpp | 42 |
3 files changed, 39 insertions, 15 deletions
diff --git a/src/buildtool/file_system/TARGETS b/src/buildtool/file_system/TARGETS index 26bb3933..ee8f0204 100644 --- a/src/buildtool/file_system/TARGETS +++ b/src/buildtool/file_system/TARGETS @@ -105,6 +105,7 @@ , ["src/utils/cpp", "path"] , ["src/utils/cpp", "hex_string"] , ["src/utils/cpp", "gsl"] + , ["src/buildtool/file_system", "file_system_manager"] ] , "cflags": ["-pthread"] } diff --git a/src/buildtool/file_system/git_cas.cpp b/src/buildtool/file_system/git_cas.cpp index 7bddf6b3..ada77f3f 100644 --- a/src/buildtool/file_system/git_cas.cpp +++ b/src/buildtool/file_system/git_cas.cpp @@ -156,9 +156,14 @@ auto GitCAS::OpenODB(std::filesystem::path const& repo_path) noexcept -> bool { git_odb* odb_ptr{nullptr}; git_repository_odb(&odb_ptr, repo); odb_.reset(odb_ptr); // retain odb pointer - // set root - std::filesystem::path git_path = - ToNormalPath(git_repository_path(repo)); + // set root + std::filesystem::path git_path{}; + if (git_repository_is_bare(repo) != 0) { + git_path = ToNormalPath((git_repository_path(repo))); + } + else { + git_path = ToNormalPath(git_repository_workdir(repo)); + } if (not git_path.is_absolute()) { try { git_path = std::filesystem::absolute(git_path); 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) { |