diff options
author | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-03-13 16:34:12 +0100 |
---|---|---|
committer | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-03-23 14:18:48 +0100 |
commit | 8d9fd1818feee729e5adeab982608aff4eddd613 (patch) | |
tree | 0ba94d9db7d0c7933a3cd5d7246bc4d090b82540 /src/buildtool/file_system/git_repo.cpp | |
parent | ddb858a101e6da5d9e6f31c41777b7108e8952be (diff) | |
download | justbuild-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.cpp | 24 |
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()), |