aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/fetchers
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/fetchers')
-rw-r--r--src/libstore/fetchers/attrs.cc25
-rw-r--r--src/libstore/fetchers/attrs.hh13
-rw-r--r--src/libstore/fetchers/git.cc16
-rw-r--r--src/libstore/fetchers/mercurial.cc2
4 files changed, 49 insertions, 7 deletions
diff --git a/src/libstore/fetchers/attrs.cc b/src/libstore/fetchers/attrs.cc
index 83b6d9164..40c02de42 100644
--- a/src/libstore/fetchers/attrs.cc
+++ b/src/libstore/fetchers/attrs.cc
@@ -14,6 +14,8 @@ Attrs jsonToAttrs(const nlohmann::json & json)
attrs.emplace(i.key(), i.value().get<int64_t>());
else if (i.value().is_string())
attrs.emplace(i.key(), i.value().get<std::string>());
+ else if (i.value().is_boolean())
+ attrs.emplace(i.key(), i.value().get<bool>());
else
throw Error("unsupported input attribute type in lock file");
}
@@ -29,6 +31,8 @@ nlohmann::json attrsToJson(const Attrs & attrs)
json[attr.first] = *v;
} else if (auto v = std::get_if<std::string>(&attr.second)) {
json[attr.first] = *v;
+ } else if (auto v = std::get_if<Explicit<bool>>(&attr.second)) {
+ json[attr.first] = v->t;
} else abort();
}
return json;
@@ -40,7 +44,7 @@ std::optional<std::string> maybeGetStrAttr(const Attrs & attrs, const std::strin
if (i == attrs.end()) return {};
if (auto v = std::get_if<std::string>(&i->second))
return *v;
- throw Error("input attribute '%s' is not a string", name);
+ throw Error("input attribute '%s' is not a string %s", name, attrsToJson(attrs).dump());
}
std::string getStrAttr(const Attrs & attrs, const std::string & name)
@@ -57,7 +61,7 @@ std::optional<int64_t> maybeGetIntAttr(const Attrs & attrs, const std::string &
if (i == attrs.end()) return {};
if (auto v = std::get_if<int64_t>(&i->second))
return *v;
- throw Error("input attribute '%s' is not a string", name);
+ throw Error("input attribute '%s' is not an integer", name);
}
int64_t getIntAttr(const Attrs & attrs, const std::string & name)
@@ -68,4 +72,21 @@ int64_t getIntAttr(const Attrs & attrs, const std::string & name)
return *s;
}
+std::optional<bool> maybeGetBoolAttr(const Attrs & attrs, const std::string & name)
+{
+ auto i = attrs.find(name);
+ if (i == attrs.end()) return {};
+ if (auto v = std::get_if<int64_t>(&i->second))
+ return *v;
+ throw Error("input attribute '%s' is not a Boolean", name);
+}
+
+bool getBoolAttr(const Attrs & attrs, const std::string & name)
+{
+ auto s = maybeGetBoolAttr(attrs, name);
+ if (!s)
+ throw Error("input attribute '%s' is missing", name);
+ return *s;
+}
+
}
diff --git a/src/libstore/fetchers/attrs.hh b/src/libstore/fetchers/attrs.hh
index b7f98d71b..2c9e772d2 100644
--- a/src/libstore/fetchers/attrs.hh
+++ b/src/libstore/fetchers/attrs.hh
@@ -8,7 +8,14 @@
namespace nix::fetchers {
-typedef std::variant<std::string, int64_t> Attr;
+/* Wrap bools to prevent string literals (i.e. 'char *') from being
+ cast to a bool in Attr. */
+template<typename T>
+struct Explicit {
+ T t;
+};
+
+typedef std::variant<std::string, int64_t, Explicit<bool>> Attr;
typedef std::map<std::string, Attr> Attrs;
Attrs jsonToAttrs(const nlohmann::json & json);
@@ -23,4 +30,8 @@ std::optional<int64_t> maybeGetIntAttr(const Attrs & attrs, const std::string &
int64_t getIntAttr(const Attrs & attrs, const std::string & name);
+std::optional<bool> maybeGetBoolAttr(const Attrs & attrs, const std::string & name);
+
+bool getBoolAttr(const Attrs & attrs, const std::string & name);
+
}
diff --git a/src/libstore/fetchers/git.cc b/src/libstore/fetchers/git.cc
index 179a5fb83..c5d4f019c 100644
--- a/src/libstore/fetchers/git.cc
+++ b/src/libstore/fetchers/git.cc
@@ -83,6 +83,7 @@ struct GitInput : Input
ParsedURL url;
std::optional<std::string> ref;
std::optional<Hash> rev;
+ bool shallow = false;
GitInput(const ParsedURL & url) : url(url)
{ }
@@ -114,6 +115,7 @@ struct GitInput : Input
if (url2.scheme != "git") url2.scheme = "git+" + url2.scheme;
if (rev) url2.query.insert_or_assign("rev", rev->gitRev());
if (ref) url2.query.insert_or_assign("ref", *ref);
+ if (shallow) url2.query.insert_or_assign("shallow", "1");
return url2.to_string();
}
@@ -125,6 +127,8 @@ struct GitInput : Input
attrs.emplace("ref", *ref);
if (rev)
attrs.emplace("rev", rev->gitRev());
+ if (shallow)
+ attrs.emplace("shallow", true);
return attrs;
}
@@ -361,9 +365,12 @@ struct GitInput : Input
bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "rev-parse", "--is-shallow-repository" })) == "true";
+ if (isShallow && !shallow)
+ throw Error("'%s' is a shallow Git repository, but a non-shallow repository is needed", actualUrl);
+
if (auto tree = lookupGitInfo(store, name, *input->rev)) {
assert(*input->rev == tree->first);
- if (isShallow) tree->second.info.revCount.reset();
+ if (shallow) tree->second.info.revCount.reset();
return {std::move(tree->second), input};
}
@@ -393,7 +400,7 @@ struct GitInput : Input
.storePath = std::move(storePath),
.info = TreeInfo {
.revCount =
- !isShallow
+ !shallow
? std::optional(std::stoull(runProgram("git", true, { "-C", repoDir, "rev-list", "--count", input->rev->gitRev() })))
: std::nullopt,
.lastModified = lastModified
@@ -440,7 +447,7 @@ struct GitInputScheme : InputScheme
if (maybeGetStrAttr(attrs, "type") != "git") return {};
for (auto & [name, value] : attrs)
- if (name != "type" && name != "url" && name != "ref" && name != "rev")
+ if (name != "type" && name != "url" && name != "ref" && name != "rev" && name != "shallow")
throw Error("unsupported Git input attribute '%s'", name);
auto input = std::make_unique<GitInput>(parseURL(getStrAttr(attrs, "url")));
@@ -451,6 +458,9 @@ struct GitInputScheme : InputScheme
}
if (auto rev = maybeGetStrAttr(attrs, "rev"))
input->rev = Hash(*rev, htSHA1);
+
+ input->shallow = maybeGetBoolAttr(attrs, "shallow").value_or(false);
+
return input;
}
};
diff --git a/src/libstore/fetchers/mercurial.cc b/src/libstore/fetchers/mercurial.cc
index a9c86f1b4..3a767ef17 100644
--- a/src/libstore/fetchers/mercurial.cc
+++ b/src/libstore/fetchers/mercurial.cc
@@ -260,7 +260,7 @@ struct MercurialInput : Input
Attrs infoAttrs({
{"rev", input->rev->gitRev()},
- {"revCount", revCount},
+ {"revCount", (int64_t) revCount},
});
if (!this->rev)