Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libfetchers-tests/git-utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class GitUtilsTest : public ::testing::Test

ref<GitRepo> openRepo()
{
return GitRepo::openRepo(tmpDir, true, false);
return GitRepo::openRepo(tmpDir, {.create = true});
}

std::string getRepoName() const
Expand Down
29 changes: 16 additions & 13 deletions src/libfetchers/git-utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,19 @@ static git_packbuilder_progress PACKBUILDER_PROGRESS_CHECK_INTERRUPT = &packBuil

} // extern "C"

static void initRepoAtomically(std::filesystem::path & path, bool bare)
static void initRepoAtomically(std::filesystem::path & path, GitRepo::Options options)
{
if (pathExists(path.string()))
return;

if (!options.create)
throw Error("Git repository %s does not exist.", path);

std::filesystem::path tmpDir = createTempDir(path.parent_path());
AutoDelete delTmpDir(tmpDir, true);
Repository tmpRepo;

if (git_repository_init(Setter(tmpRepo), tmpDir.string().c_str(), bare))
if (git_repository_init(Setter(tmpRepo), tmpDir.string().c_str(), options.bare))
throw Error("creating Git repository %s: %s", path, git_error_last()->message);
try {
std::filesystem::rename(tmpDir, path);
Expand All @@ -234,7 +237,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
/** Location of the repository on disk. */
std::filesystem::path path;

bool bare;
Options options;

/**
* libgit2 repository. Note that new objects are not written to disk,
Expand All @@ -255,18 +258,18 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
*/
git_odb_backend * packBackend = nullptr;

GitRepoImpl(std::filesystem::path _path, bool create, bool bare, bool packfilesOnly = false)
GitRepoImpl(std::filesystem::path _path, Options _options)
: path(std::move(_path))
, bare(bare)
, options(_options)
{
initLibGit2();

initRepoAtomically(path, bare);
initRepoAtomically(path, options);
if (git_repository_open(Setter(repo), path.string().c_str()))
throw Error("opening Git repository %s: %s", path, git_error_last()->message);

ObjectDb odb;
if (packfilesOnly) {
if (options.packfilesOnly) {
/* Create a fresh object database because by default the repo also
loose object backends. We are not using any of those for the
tarball cache, but libgit2 still does a bunch of unnecessary
Expand Down Expand Up @@ -295,7 +298,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
if (git_odb_add_backend(odb.get(), mempackBackend, 999))
throw Error("adding mempack backend to Git object database: %s", git_error_last()->message);

if (packfilesOnly) {
if (options.packfilesOnly) {
if (git_repository_set_odb(repo.get(), odb.get()))
throw Error("setting Git object database: %s", git_error_last()->message);
}
Expand Down Expand Up @@ -366,7 +369,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
{
// TODO: as an optimization, it would be nice to include `this` in the pool.
return Pool<GitRepoImpl>(std::numeric_limits<size_t>::max(), [this]() -> ref<GitRepoImpl> {
return make_ref<GitRepoImpl>(path, false, bare);
return make_ref<GitRepoImpl>(path, options);
});
}

Expand Down Expand Up @@ -712,9 +715,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
}
};

ref<GitRepo> GitRepo::openRepo(const std::filesystem::path & path, bool create, bool bare, bool packfilesOnly)
ref<GitRepo> GitRepo::openRepo(const std::filesystem::path & path, GitRepo::Options options)
{
return make_ref<GitRepoImpl>(path, create, bare, packfilesOnly);
return make_ref<GitRepoImpl>(path, options);
}

/**
Expand Down Expand Up @@ -1428,7 +1431,7 @@ namespace fetchers {
ref<GitRepo> Settings::getTarballCache() const
{
static auto repoDir = std::filesystem::path(getCacheDir()) / "tarball-cache";
return GitRepo::openRepo(repoDir, /*create=*/true, /*bare=*/true, /*packfilesOnly=*/true);
return GitRepo::openRepo(repoDir, {.create = true, .bare = true, .packfilesOnly = true});
}

} // namespace fetchers
Expand All @@ -1442,7 +1445,7 @@ GitRepo::WorkdirInfo GitRepo::getCachedWorkdirInfo(const std::filesystem::path &
if (i != cache->end())
return i->second;
}
auto workdirInfo = GitRepo::openRepo(path)->getWorkdirInfo();
auto workdirInfo = GitRepo::openRepo(path, {})->getWorkdirInfo();
_cache.lock()->emplace(path, workdirInfo);
return workdirInfo;
}
Expand Down
21 changes: 8 additions & 13 deletions src/libfetchers/git.cc
Original file line number Diff line number Diff line change
Expand Up @@ -637,11 +637,6 @@ struct GitInputScheme : InputScheme
url);
}

// If we don't check here for the path existence, then we can give libgit2 any directory
// and it will initialize them as git directories.
if (!pathExists(path)) {
throw Error("The path '%s' does not exist.", path);
}
repoInfo.location = std::filesystem::absolute(path);
} else {
if (url.scheme == "file")
Expand Down Expand Up @@ -703,7 +698,7 @@ struct GitInputScheme : InputScheme
if (auto res = cache->lookup(key))
return getIntAttr(*res, "lastModified");

auto lastModified = GitRepo::openRepo(repoDir)->getLastModified(rev);
auto lastModified = GitRepo::openRepo(repoDir, {})->getLastModified(rev);

cache->upsert(key, {{"lastModified", lastModified}});

Expand All @@ -726,7 +721,7 @@ struct GitInputScheme : InputScheme
Activity act(
*logger, lvlChatty, actUnknown, fmt("getting Git revision count of '%s'", repoInfo.locationToArg()));

auto revCount = GitRepo::openRepo(repoDir)->getRevCount(rev);
auto revCount = GitRepo::openRepo(repoDir, {})->getRevCount(rev);

cache->upsert(key, Attrs{{"revCount", revCount}});

Expand All @@ -737,7 +732,7 @@ struct GitInputScheme : InputScheme
{
auto head = std::visit(
overloaded{
[&](const std::filesystem::path & path) { return GitRepo::openRepo(path)->getWorkdirRef(); },
[&](const std::filesystem::path & path) { return GitRepo::openRepo(path, {})->getWorkdirRef(); },
[&](const ParsedURL & url) { return readHeadCached(url.to_string(), shallow); }},
repoInfo.location);
if (!head) {
Expand Down Expand Up @@ -795,7 +790,7 @@ struct GitInputScheme : InputScheme
if (auto repoPath = repoInfo.getPath()) {
repoDir = *repoPath;
if (!input.getRev())
input.attrs.insert_or_assign("rev", GitRepo::openRepo(repoDir)->resolveRef(ref).gitRev());
input.attrs.insert_or_assign("rev", GitRepo::openRepo(repoDir, {})->resolveRef(ref).gitRev());
} else {
auto repoUrl = std::get<ParsedURL>(repoInfo.location);
std::filesystem::path cacheDir = getCachePath(repoUrl.to_string(), shallow);
Expand All @@ -805,7 +800,7 @@ struct GitInputScheme : InputScheme
std::filesystem::create_directories(cacheDir.parent_path());
PathLocks cacheDirLock({cacheDir.string()});

auto repo = GitRepo::openRepo(cacheDir, true, true);
auto repo = GitRepo::openRepo(cacheDir, {.create = true, .bare = true});

// We need to set the origin so resolving submodule URLs works
repo->setRemote("origin", repoUrl.to_string());
Expand Down Expand Up @@ -876,7 +871,7 @@ struct GitInputScheme : InputScheme
// the remainder
}

auto repo = GitRepo::openRepo(repoDir);
auto repo = GitRepo::openRepo(repoDir, {});

auto isShallow = repo->isShallow();

Expand Down Expand Up @@ -963,7 +958,7 @@ struct GitInputScheme : InputScheme
for (auto & submodule : repoInfo.workdirInfo.submodules)
repoInfo.workdirInfo.files.insert(submodule.path);

auto repo = GitRepo::openRepo(repoPath, false, false);
auto repo = GitRepo::openRepo(repoPath, {});

auto exportIgnore = getExportIgnoreAttr(input);

Expand Down Expand Up @@ -1003,7 +998,7 @@ struct GitInputScheme : InputScheme
}

if (!repoInfo.workdirInfo.isDirty) {
auto repo = GitRepo::openRepo(repoPath);
auto repo = GitRepo::openRepo(repoPath, {});

if (auto ref = repo->getWorkdirRef())
input.attrs.insert_or_assign("ref", *ref);
Expand Down
10 changes: 8 additions & 2 deletions src/libfetchers/include/nix/fetchers/git-utils.hh
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@ struct GitRepo
{
virtual ~GitRepo() {}

static ref<GitRepo>
openRepo(const std::filesystem::path & path, bool create = false, bool bare = false, bool packfilesOnly = false);
struct Options
{
bool create = false;
bool bare = false;
bool packfilesOnly = false;
};

static ref<GitRepo> openRepo(const std::filesystem::path & path, Options options);

virtual uint64_t getRevCount(const Hash & rev) = 0;

Expand Down
Loading