about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorShea Levy <shea@shealevy.com>2017-12-05T16·16-0500
committerShea Levy <shea@shealevy.com>2017-12-05T16·16-0500
commit11a7f8ce14afbdc60b9acf424d941ccda1adc141 (patch)
treefbd99244f4fe0c346d26b770580cb37a993cbb4a /src
parent7f2c324ed18cba4004ff89dfd84cf2df979b2571 (diff)
parenteedbc4e06c017d84814b4c1fad8c6b6db958f3da (diff)
Merge branch 'fetchGit-fast-revision-update'
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/primops/fetchGit.cc59
1 files changed, 35 insertions, 24 deletions
diff --git a/src/libexpr/primops/fetchGit.cc b/src/libexpr/primops/fetchGit.cc
index fd3e84c292c3..e92e0638031f 100644
--- a/src/libexpr/primops/fetchGit.cc
+++ b/src/libexpr/primops/fetchGit.cc
@@ -89,32 +89,43 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
 
     Path localRefFile = cacheDir + "/refs/heads/" + localRef;
 
-    /* If the local ref is older than ‘tarball-ttl’ seconds, do a git
-       fetch to update the local ref to the remote ref. */
+    bool doFetch;
     time_t now = time(0);
-    struct stat st;
-    if (stat(localRefFile.c_str(), &st) != 0 ||
-        st.st_mtime <= now - settings.tarballTtl)
-    {
-        if (rev == "" ||
-            chomp(runProgram(
-                RunOptions("git", { "-C", cacheDir, "cat-file", "-t", rev })
-                .killStderr(true)).second) != "commit")
-        {
-            Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Git repository '%s'", uri));
-
-            // FIXME: git stderr messes up our progress indicator, so
-            // we're using --quiet for now. Should process its stderr.
-            runProgram("git", true, { "-C", cacheDir, "fetch", "--quiet", "--force", "--", uri, *ref + ":" + localRef });
-
-            struct timeval times[2];
-            times[0].tv_sec = now;
-            times[0].tv_usec = 0;
-            times[1].tv_sec = now;
-            times[1].tv_usec = 0;
-
-            utimes(localRefFile.c_str(), times);
+    /* If a rev was specified, we need to fetch if it's not in the
+       repo. */
+    if (rev != "") {
+        try {
+            runProgram("git", true, { "-C", cacheDir, "cat-file", "-e", rev });
+            doFetch = false;
+        } catch (ExecError & e) {
+            if (WIFEXITED(e.status)) {
+                doFetch = true;
+            } else {
+                throw;
+            }
         }
+    } else {
+        /* If the local ref is older than ‘tarball-ttl’ seconds, do a
+           git fetch to update the local ref to the remote ref. */
+        struct stat st;
+        doFetch = stat(localRefFile.c_str(), &st) != 0 ||
+            st.st_mtime <= now - settings.tarballTtl;
+    }
+    if (doFetch)
+    {
+        Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Git repository '%s'", uri));
+
+        // FIXME: git stderr messes up our progress indicator, so
+        // we're using --quiet for now. Should process its stderr.
+        runProgram("git", true, { "-C", cacheDir, "fetch", "--quiet", "--force", "--", uri, *ref + ":" + localRef });
+
+        struct timeval times[2];
+        times[0].tv_sec = now;
+        times[0].tv_usec = 0;
+        times[1].tv_sec = now;
+        times[1].tv_usec = 0;
+
+        utimes(localRefFile.c_str(), times);
     }
 
     // FIXME: check whether rev is an ancestor of ref.