mirror of
https://github.com/NixOS/nix.git
synced 2024-11-29 02:02:27 +00:00
create git caches atomically
When working on speeding up the CI,
I triggered a race condition in the creation of the tarball cache.
This code now instead will ensure that half-initialized repositories
are no longer visible to any other nix process.
This is the error message that I got before:
error: opening Git repository '"/Users/runner/.cache/nix/tarball-cache"': could not find repository at '/Users/runner/.cache/nix/tarball-cache'
(cherry picked from commit 12d5b2cfa1
)
This commit is contained in:
parent
b23812a59c
commit
34fd00accc
@ -159,6 +159,27 @@ static Object peelToTreeOrBlob(git_object * obj)
|
|||||||
return peelObject<Object>(obj, GIT_OBJECT_TREE);
|
return peelObject<Object>(obj, GIT_OBJECT_TREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void initRepoAtomically(std::filesystem::path &path, bool bare) {
|
||||||
|
if (pathExists(path.string())) return;
|
||||||
|
|
||||||
|
Path tmpDir = createTempDir(std::filesystem::path(path).parent_path());
|
||||||
|
AutoDelete delTmpDir(tmpDir, true);
|
||||||
|
Repository tmpRepo;
|
||||||
|
|
||||||
|
if (git_repository_init(Setter(tmpRepo), tmpDir.c_str(), bare))
|
||||||
|
throw Error("creating Git repository %s: %s", path, git_error_last()->message);
|
||||||
|
try {
|
||||||
|
std::filesystem::rename(tmpDir, path);
|
||||||
|
} catch (std::filesystem::filesystem_error & e) {
|
||||||
|
if (e.code() == std::errc::file_exists) // Someone might race us to create the repository.
|
||||||
|
return;
|
||||||
|
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.
|
||||||
|
delTmpDir.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||||
{
|
{
|
||||||
/** Location of the repository on disk. */
|
/** Location of the repository on disk. */
|
||||||
@ -170,13 +191,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||||||
{
|
{
|
||||||
initLibGit2();
|
initLibGit2();
|
||||||
|
|
||||||
if (pathExists(path.string())) {
|
initRepoAtomically(path, bare);
|
||||||
if (git_repository_open(Setter(repo), path.string().c_str()))
|
if (git_repository_open(Setter(repo), path.string().c_str()))
|
||||||
throw Error("opening Git repository '%s': %s", path, git_error_last()->message);
|
throw Error("opening Git repository '%s': %s", path, git_error_last()->message);
|
||||||
} else {
|
|
||||||
if (git_repository_init(Setter(repo), path.string().c_str(), bare))
|
|
||||||
throw Error("creating Git repository '%s': %s", path, git_error_last()->message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operator git_repository * ()
|
operator git_repository * ()
|
||||||
|
Loading…
Reference in New Issue
Block a user