diff options
Diffstat (limited to 'src/libfetchers/git.cc')
-rw-r--r-- | src/libfetchers/git.cc | 44 |
1 files changed, 19 insertions, 25 deletions
diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 8468d2afc..c0beca2f2 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -6,6 +6,8 @@ #include "url-parts.hh" #include "pathlocks.hh" +#include "fetch-settings.hh" + #include <sys/time.h> #include <sys/wait.h> @@ -51,7 +53,7 @@ struct GitInputScheme : InputScheme for (auto &[name, value] : url.query) { if (name == "rev" || name == "ref") attrs.emplace(name, value); - else if (name == "shallow") + else if (name == "shallow" || name == "submodules") attrs.emplace(name, Explicit<bool> { value == "1" }); else url2.query.emplace(name, value); @@ -172,7 +174,7 @@ struct GitInputScheme : InputScheme return {isLocal, isLocal ? url.path : url.base}; } - std::pair<Tree, Input> fetch(ref<Store> store, const Input & _input) override + std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override { Input input(_input); @@ -187,7 +189,7 @@ struct GitInputScheme : InputScheme if (submodules) cacheType += "-submodules"; if (allRefs) cacheType += "-all-refs"; - auto getImmutableAttrs = [&]() + auto getLockedAttrs = [&]() { return Attrs({ {"type", cacheType}, @@ -197,21 +199,18 @@ struct GitInputScheme : InputScheme }; auto makeResult = [&](const Attrs & infoAttrs, StorePath && storePath) - -> std::pair<Tree, Input> + -> std::pair<StorePath, Input> { assert(input.getRev()); assert(!_input.getRev() || _input.getRev() == input.getRev()); if (!shallow) input.attrs.insert_or_assign("revCount", getIntAttr(infoAttrs, "revCount")); input.attrs.insert_or_assign("lastModified", getIntAttr(infoAttrs, "lastModified")); - return { - Tree(store->toRealPath(storePath), std::move(storePath)), - input - }; + return {std::move(storePath), input}; }; if (input.getRev()) { - if (auto res = getCache()->lookup(store, getImmutableAttrs())) + if (auto res = getCache()->lookup(store, getLockedAttrs())) return makeResult(res->first, std::move(res->second)); } @@ -249,10 +248,10 @@ struct GitInputScheme : InputScheme /* This is an unclean working tree. So copy all tracked files. */ - if (!settings.allowDirty) + if (!fetchSettings.allowDirty) throw Error("Git tree '%s' is dirty", actualUrl); - if (settings.warnDirty) + if (fetchSettings.warnDirty) warn("Git tree '%s' is dirty", actualUrl); auto gitOpts = Strings({ "-C", actualUrl, "ls-files", "-z" }); @@ -285,16 +284,13 @@ struct GitInputScheme : InputScheme "lastModified", haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0); - return { - Tree(store->toRealPath(storePath), std::move(storePath)), - input - }; + return {std::move(storePath), input}; } } if (!input.getRef()) input.attrs.insert_or_assign("ref", isLocal ? readHead(actualUrl) : "master"); - Attrs mutableAttrs({ + Attrs unlockedAttrs({ {"type", cacheType}, {"name", name}, {"url", actualUrl}, @@ -313,7 +309,7 @@ struct GitInputScheme : InputScheme } else { - if (auto res = getCache()->lookup(store, mutableAttrs)) { + if (auto res = getCache()->lookup(store, unlockedAttrs)) { auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1); if (!input.getRev() || input.getRev() == rev2) { input.attrs.insert_or_assign("rev", rev2.gitRev()); @@ -324,17 +320,13 @@ struct GitInputScheme : InputScheme Path cacheDir = getCacheDir() + "/nix/gitv3/" + hashString(htSHA256, actualUrl).to_string(Base32, false); repoDir = cacheDir; - Path cacheDirLock = cacheDir + ".lock"; createDirs(dirOf(cacheDir)); - AutoCloseFD lock = openLockFile(cacheDirLock, true); - lockFile(lock.get(), ltWrite, true); + PathLocks cacheDirLock({cacheDir + ".lock"}); if (!pathExists(cacheDir)) { runProgram("git", true, { "-c", "init.defaultBranch=" + gitInitialBranch, "init", "--bare", repoDir }); } - deleteLockFile(cacheDirLock, lock.get()); - Path localRefFile = input.getRef()->compare(0, 5, "refs/") == 0 ? cacheDir + "/" + *input.getRef() @@ -399,6 +391,8 @@ struct GitInputScheme : InputScheme if (!input.getRev()) input.attrs.insert_or_assign("rev", Hash::parseAny(chomp(readFile(localRefFile)), htSHA1).gitRev()); + + // cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder } bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "rev-parse", "--is-shallow-repository" })) == "true"; @@ -412,7 +406,7 @@ struct GitInputScheme : InputScheme /* Now that we know the ref, check again whether we have it in the store. */ - if (auto res = getCache()->lookup(store, getImmutableAttrs())) + if (auto res = getCache()->lookup(store, getLockedAttrs())) return makeResult(res->first, std::move(res->second)); Path tmpDir = createTempDir(); @@ -484,14 +478,14 @@ struct GitInputScheme : InputScheme if (!_input.getRev()) getCache()->add( store, - mutableAttrs, + unlockedAttrs, infoAttrs, storePath, false); getCache()->add( store, - getImmutableAttrs(), + getLockedAttrs(), infoAttrs, storePath, true); |