about summary refs log tree commit diff
path: root/src/libexpr/primops
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/primops')
-rw-r--r--src/libexpr/primops/fetchMercurial.cc28
1 files changed, 19 insertions, 9 deletions
diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc
index 391ce45a0a98..e68d1a2a5539 100644
--- a/src/libexpr/primops/fetchMercurial.cc
+++ b/src/libexpr/primops/fetchMercurial.cc
@@ -22,6 +22,8 @@ struct HgInfo
     uint64_t revCount = 0;
 };
 
+std::regex commitHashRegex("^[0-9a-fA-F]{40}$");
+
 HgInfo exportMercurial(ref<Store> store, const std::string & uri,
     std::string rev, const std::string & name)
 {
@@ -66,20 +68,28 @@ HgInfo exportMercurial(ref<Store> store, const std::string & uri,
     Path stampFile = fmt("%s/.hg/%s.stamp", cacheDir, hashString(htSHA512, rev).to_string(Base32, false));
 
     /* If we haven't pulled this repo less than ‘tarball-ttl’ seconds,
-       do so now. FIXME: don't do this if "rev" is a hash and we
-       fetched it previously */
+       do so now. */
     time_t now = time(0);
     struct stat st;
     if (stat(stampFile.c_str(), &st) != 0 ||
         st.st_mtime < now - settings.tarballTtl)
     {
-        Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", uri));
-
-        if (pathExists(cacheDir)) {
-            runProgram("hg", true, { "pull", "-R", cacheDir, "--", uri });
-        } else {
-            createDirs(dirOf(cacheDir));
-            runProgram("hg", true, { "clone", "--noupdate", "--", uri, cacheDir });
+        /* Except that if this is a commit hash that we already have,
+           we don't have to pull again. */
+        if (!(std::regex_match(rev, commitHashRegex)
+                && pathExists(cacheDir)
+                && runProgram(
+                    RunOptions("hg", { "log", "-R", cacheDir, "-r", rev, "--template", "1" })
+                    .killStderr(true)).second == "1"))
+        {
+            Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", uri));
+
+            if (pathExists(cacheDir)) {
+                runProgram("hg", true, { "pull", "-R", cacheDir, "--", uri });
+            } else {
+                createDirs(dirOf(cacheDir));
+                runProgram("hg", true, { "clone", "--noupdate", "--", uri, cacheDir });
+            }
         }
 
         writeFile(stampFile, "");