summaryrefslogtreecommitdiff
path: root/src/buildtool/file_system/git_repo.cpp
diff options
context:
space:
mode:
authorPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2023-03-13 16:34:12 +0100
committerPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2023-03-23 14:18:48 +0100
commit8d9fd1818feee729e5adeab982608aff4eddd613 (patch)
tree0ba94d9db7d0c7933a3cd5d7246bc4d090b82540 /src/buildtool/file_system/git_repo.cpp
parentddb858a101e6da5d9e6f31c41777b7108e8952be (diff)
downloadjustbuild-8d9fd1818feee729e5adeab982608aff4eddd613.tar.gz
GitRepo: Make repository initialisation more robust
As the initialisation of Git repositories is something that only takes place once, we should check early and cheaply whether the repository is already there before trying to initialize it. If we do need to initilize a repo, we can afford more attempts and longer wait times between tries to initalize if the failure to initialize happens due to the internal Git locking mechanism.
Diffstat (limited to 'src/buildtool/file_system/git_repo.cpp')
-rw-r--r--src/buildtool/file_system/git_repo.cpp24
1 files changed, 19 insertions, 5 deletions
diff --git a/src/buildtool/file_system/git_repo.cpp b/src/buildtool/file_system/git_repo.cpp
index bf0b6ddc..4c88e4a7 100644
--- a/src/buildtool/file_system/git_repo.cpp
+++ b/src/buildtool/file_system/git_repo.cpp
@@ -361,8 +361,16 @@ auto GitRepo::InitAndOpen(std::filesystem::path const& repo_path,
auto git_state = GitContext(); // initialize libgit2
+ // check if init is actually needed
+ if (git_repository_open_ext(nullptr,
+ repo_path.c_str(),
+ GIT_REPOSITORY_OPEN_NO_SEARCH,
+ nullptr) == 0) {
+ return GitRepo(repo_path); // success
+ }
+
git_repository* tmp_repo{nullptr};
- size_t max_attempts = 3; // number of tries
+ size_t max_attempts = kGitLockNumTries; // number of tries
int err = 0;
std::string err_mess{};
while (max_attempts > 0) {
@@ -373,7 +381,11 @@ auto GitRepo::InitAndOpen(std::filesystem::path const& repo_path,
git_repository_free(tmp_repo);
return GitRepo(repo_path); // success
}
- err_mess = GitLastError(); // store last error message
+ err_mess = GitLastError(); // store last error message
+ // only retry if failure is due to locking
+ if (err != GIT_ELOCKED) {
+ break;
+ }
git_repository_free(tmp_repo); // cleanup before next attempt
// check if init hasn't already happened in another process
if (git_repository_open_ext(nullptr,
@@ -383,7 +395,8 @@ auto GitRepo::InitAndOpen(std::filesystem::path const& repo_path,
return GitRepo(repo_path); // success
}
// repo still not created, so sleep and try again
- std::this_thread::sleep_for(std::chrono::milliseconds(kWaitTime));
+ std::this_thread::sleep_for(
+ std::chrono::milliseconds(kGitLockWaitTime));
}
Logger::Log(LogLevel::Error,
"initializing git repository {} failed with:\n{}",
@@ -582,7 +595,7 @@ auto GitRepo::KeepTag(std::string const& commit,
git_oid oid;
auto name = fmt::format("keep-{}", commit);
- size_t max_attempts = 3; // number of tries
+ size_t max_attempts = kGitLockNumTries; // number of tries
int err = 0;
git_strarray tag_names{};
while (max_attempts > 0) {
@@ -607,7 +620,8 @@ auto GitRepo::KeepTag(std::string const& commit,
git_strarray_dispose(
&tag_names); // free any allocated unused space
// tag still not in, so sleep and try again
- std::this_thread::sleep_for(std::chrono::milliseconds(kWaitTime));
+ std::this_thread::sleep_for(
+ std::chrono::milliseconds(kGitLockWaitTime));
}
(*logger)(fmt::format("tag creation in git repository {} failed",
GetGitCAS()->git_path_.string()),