aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/fetchers/mercurial.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/fetchers/mercurial.cc')
-rw-r--r--src/libstore/fetchers/mercurial.cc180
1 files changed, 92 insertions, 88 deletions
diff --git a/src/libstore/fetchers/mercurial.cc b/src/libstore/fetchers/mercurial.cc
index 6ab0add1d..a9c86f1b4 100644
--- a/src/libstore/fetchers/mercurial.cc
+++ b/src/libstore/fetchers/mercurial.cc
@@ -1,5 +1,6 @@
-#include "fetchers.hh"
-#include "parse.hh"
+#include "fetchers/fetchers.hh"
+#include "fetchers/cache.hh"
+#include "fetchers/parse.hh"
#include "globals.hh"
#include "tarfile.hh"
#include "store-api.hh"
@@ -7,8 +8,6 @@
#include <sys/time.h>
-#include <nlohmann/json.hpp>
-
using namespace std::string_literals;
namespace nix::fetchers {
@@ -163,51 +162,80 @@ struct MercurialInput : Input
if (!input->ref) input->ref = "default";
- Path cacheDir = fmt("%s/nix/hg/%s", getCacheDir(), hashString(htSHA256, actualUrl).to_string(Base32, false));
+ auto getImmutableAttrs = [&]()
+ {
+ return Attrs({
+ {"type", "hg"},
+ {"name", name},
+ {"rev", input->rev->gitRev()},
+ });
+ };
+
+ auto makeResult = [&](const Attrs & infoAttrs, StorePath && storePath)
+ -> std::pair<Tree, std::shared_ptr<const Input>>
+ {
+ input->rev = Hash(getStrAttr(infoAttrs, "rev"), htSHA1);
+ assert(!rev || rev == input->rev);
+ return {
+ Tree{
+ .actualPath = store->toRealPath(storePath),
+ .storePath = std::move(storePath),
+ .info = TreeInfo {
+ .revCount = getIntAttr(infoAttrs, "revCount"),
+ },
+ },
+ input
+ };
+ };
+
+ if (input->rev) {
+ if (auto res = getCache()->lookup(store, getImmutableAttrs()))
+ return makeResult(res->first, std::move(res->second));
+ }
assert(input->rev || input->ref);
auto revOrRef = input->rev ? input->rev->gitRev() : *input->ref;
- Path stampFile = fmt("%s/.hg/%s.stamp", cacheDir, hashString(htSHA512, revOrRef).to_string(Base32, false));
+ Attrs mutableAttrs({
+ {"type", "hg"},
+ {"name", name},
+ {"url", actualUrl},
+ {"ref", *input->ref},
+ });
+
+ if (auto res = getCache()->lookup(store, mutableAttrs))
+ return makeResult(res->first, std::move(res->second));
- /* If we haven't pulled this repo less than ‘tarball-ttl’ seconds,
- do so now. */
- time_t now = time(0);
- struct stat st;
- if (stat(stampFile.c_str(), &st) != 0 ||
- (uint64_t) st.st_mtime + settings.tarballTtl <= (uint64_t) now)
+ Path cacheDir = fmt("%s/nix/hg/%s", getCacheDir(), hashString(htSHA256, actualUrl).to_string(Base32, false));
+
+ /* If this is a commit hash that we already have, we don't
+ have to pull again. */
+ if (!(input->rev
+ && pathExists(cacheDir)
+ && runProgram(
+ RunOptions("hg", { "log", "-R", cacheDir, "-r", input->rev->gitRev(), "--template", "1" })
+ .killStderr(true)).second == "1"))
{
- /* Except that if this is a commit hash that we already have,
- we don't have to pull again. */
- if (!(input->rev
- && pathExists(cacheDir)
- && runProgram(
- RunOptions("hg", { "log", "-R", cacheDir, "-r", input->rev->gitRev(), "--template", "1" })
- .killStderr(true)).second == "1"))
- {
- Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", actualUrl));
-
- if (pathExists(cacheDir)) {
- try {
+ Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", actualUrl));
+
+ if (pathExists(cacheDir)) {
+ try {
+ runProgram("hg", true, { "pull", "-R", cacheDir, "--", actualUrl });
+ }
+ catch (ExecError & e) {
+ string transJournal = cacheDir + "/.hg/store/journal";
+ /* hg throws "abandoned transaction" error only if this file exists */
+ if (pathExists(transJournal)) {
+ runProgram("hg", true, { "recover", "-R", cacheDir });
runProgram("hg", true, { "pull", "-R", cacheDir, "--", actualUrl });
+ } else {
+ throw ExecError(e.status, fmt("'hg pull' %s", statusToString(e.status)));
}
- catch (ExecError & e) {
- string transJournal = cacheDir + "/.hg/store/journal";
- /* hg throws "abandoned transaction" error only if this file exists */
- if (pathExists(transJournal)) {
- runProgram("hg", true, { "recover", "-R", cacheDir });
- runProgram("hg", true, { "pull", "-R", cacheDir, "--", actualUrl });
- } else {
- throw ExecError(e.status, fmt("'hg pull' %s", statusToString(e.status)));
- }
- }
- } else {
- createDirs(dirOf(cacheDir));
- runProgram("hg", true, { "clone", "--noupdate", "--", actualUrl, cacheDir });
}
+ } else {
+ createDirs(dirOf(cacheDir));
+ runProgram("hg", true, { "clone", "--noupdate", "--", actualUrl, cacheDir });
}
-
- writeFile(stampFile, "");
}
auto tokens = tokenizeString<std::vector<std::string>>(
@@ -218,33 +246,8 @@ struct MercurialInput : Input
auto revCount = std::stoull(tokens[1]);
input->ref = tokens[2];
- std::string storeLinkName = hashString(htSHA512, name + std::string("\0"s) + input->rev->gitRev()).to_string(Base32, false);
- Path storeLink = fmt("%s/.hg/%s.link", cacheDir, storeLinkName);
-
- try {
- auto json = nlohmann::json::parse(readFile(storeLink));
-
- assert(json["name"] == name && json["rev"] == input->rev->gitRev());
-
- auto storePath = store->parseStorePath((std::string) json["storePath"]);
-
- if (store->isValidPath(storePath)) {
- printTalkative("using cached Mercurial store path '%s'", store->printStorePath(storePath));
- return {
- Tree {
- .actualPath = store->printStorePath(storePath),
- .storePath = std::move(storePath),
- .info = TreeInfo {
- .revCount = revCount,
- },
- },
- input
- };
- }
-
- } catch (SysError & e) {
- if (e.errNo != ENOENT) throw;
- }
+ if (auto res = getCache()->lookup(store, getImmutableAttrs()))
+ return makeResult(res->first, std::move(res->second));
Path tmpDir = createTempDir();
AutoDelete delTmpDir(tmpDir, true);
@@ -255,26 +258,27 @@ struct MercurialInput : Input
auto storePath = store->addToStore(name, tmpDir);
- nlohmann::json json;
- json["storePath"] = store->printStorePath(storePath);
- json["uri"] = actualUrl;
- json["name"] = name;
- json["branch"] = *input->ref;
- json["rev"] = input->rev->gitRev();
- json["revCount"] = revCount;
-
- writeFile(storeLink, json.dump());
-
- return {
- Tree {
- .actualPath = store->printStorePath(storePath),
- .storePath = std::move(storePath),
- .info = TreeInfo {
- .revCount = revCount
- }
- },
- input
- };
+ Attrs infoAttrs({
+ {"rev", input->rev->gitRev()},
+ {"revCount", revCount},
+ });
+
+ if (!this->rev)
+ getCache()->add(
+ store,
+ mutableAttrs,
+ infoAttrs,
+ storePath,
+ false);
+
+ getCache()->add(
+ store,
+ getImmutableAttrs(),
+ infoAttrs,
+ storePath,
+ true);
+
+ return makeResult(infoAttrs, std::move(storePath));
}
};
@@ -291,7 +295,7 @@ struct MercurialInputScheme : InputScheme
url2.scheme = std::string(url2.scheme, 3);
url2.query.clear();
- Input::Attrs attrs;
+ Attrs attrs;
attrs.emplace("type", "hg");
for (auto &[name, value] : url.query) {
@@ -306,7 +310,7 @@ struct MercurialInputScheme : InputScheme
return inputFromAttrs(attrs);
}
- std::unique_ptr<Input> inputFromAttrs(const Input::Attrs & attrs) override
+ std::unique_ptr<Input> inputFromAttrs(const Attrs & attrs) override
{
if (maybeGetStrAttr(attrs, "type") != "hg") return {};