diff --git a/src/libfetchers-tests/git-utils.cc b/src/libfetchers-tests/git-utils.cc index 762e39ad6..cdd920e54 100644 --- a/src/libfetchers-tests/git-utils.cc +++ b/src/libfetchers-tests/git-utils.cc @@ -48,7 +48,7 @@ public: ref openRepo() { - return GitRepo::openRepo(tmpDir, true, false); + return GitRepo::openRepo(tmpDir, {.create = true}); } std::string getRepoName() const diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index fecceefff..ddc3184f2 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -234,7 +234,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this /** 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, @@ -255,18 +255,18 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this */ 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.bare); 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 @@ -295,7 +295,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this 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); } @@ -366,7 +366,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this { // TODO: as an optimization, it would be nice to include `this` in the pool. return Pool(std::numeric_limits::max(), [this]() -> ref { - return make_ref(path, false, bare); + return make_ref(path, options); }); } @@ -712,9 +712,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this } }; -ref GitRepo::openRepo(const std::filesystem::path & path, bool create, bool bare, bool packfilesOnly) +ref GitRepo::openRepo(const std::filesystem::path & path, GitRepo::Options options) { - return make_ref(path, create, bare, packfilesOnly); + return make_ref(path, options); } /** @@ -1428,7 +1428,7 @@ namespace fetchers { ref 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 @@ -1442,7 +1442,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; } diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 4f5247861..72fd95e76 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -639,6 +639,7 @@ struct GitInputScheme : InputScheme // 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. + // FIXME if (!pathExists(path)) { throw Error("The path '%s' does not exist.", path); } @@ -703,7 +704,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}}); @@ -726,7 +727,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}}); @@ -737,7 +738,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) { @@ -795,7 +796,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(repoInfo.location); std::filesystem::path cacheDir = getCachePath(repoUrl.to_string(), shallow); @@ -805,7 +806,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()); @@ -876,7 +877,7 @@ struct GitInputScheme : InputScheme // the remainder } - auto repo = GitRepo::openRepo(repoDir); + auto repo = GitRepo::openRepo(repoDir, {}); auto isShallow = repo->isShallow(); @@ -963,7 +964,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); @@ -1003,7 +1004,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); diff --git a/src/libfetchers/include/nix/fetchers/git-utils.hh b/src/libfetchers/include/nix/fetchers/git-utils.hh index 5c79f256e..24a7b8008 100644 --- a/src/libfetchers/include/nix/fetchers/git-utils.hh +++ b/src/libfetchers/include/nix/fetchers/git-utils.hh @@ -32,8 +32,14 @@ struct GitRepo { virtual ~GitRepo() {} - static ref - 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 openRepo(const std::filesystem::path & path, Options options); virtual uint64_t getRevCount(const Hash & rev) = 0;