diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index 21d98089f..c40a903b9 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -68,7 +68,7 @@ static FlakeInput parseFlakeInput(EvalState & state, expectType(state, tAttrs, *value, pos); FlakeInput input { - .ref = parseFlakeRef(inputName) + .ref = FlakeRef::fromAttrs({{"type", "indirect"}, {"id", inputName}}) }; auto sInputs = state.symbols.create("inputs"); diff --git a/src/libstore/fetchers/git.cc b/src/libstore/fetchers/git.cc index 2a7ce5432..5d0448777 100644 --- a/src/libstore/fetchers/git.cc +++ b/src/libstore/fetchers/git.cc @@ -370,32 +370,39 @@ struct GitInputScheme : InputScheme url.scheme != "git+ssh" && url.scheme != "git+file") return nullptr; - auto input = std::make_unique(url); + auto url2(url); + // FIXME: strip git+ + url2.query.clear(); - input->url.query.clear(); + Input::Attrs attrs; + attrs.emplace("type", "git"); for (auto &[name, value] : url.query) { - if (name == "rev") { - if (!std::regex_match(value, revRegex)) - throw BadURL("Git URL '%s' contains an invalid commit hash", url.url); - input->rev = Hash(value, htSHA1); - } - else if (name == "ref") { - if (!std::regex_match(value, refRegex)) - throw BadURL("Git URL '%s' contains an invalid branch/tag name", url.url); - input->ref = value; - } - else input->url.query.insert_or_assign(name, value); + if (name == "rev" || name == "ref") + attrs.emplace(name, value); + else + url2.query.emplace(name, value); } - return input; + attrs.emplace("url", url2.to_string()); + + return inputFromAttrs(attrs); } std::unique_ptr inputFromAttrs(const Input::Attrs & attrs) override { if (maybeGetStrAttr(attrs, "type") != "git") return {}; + + for (auto & [name, value] : attrs) + if (name != "type" && name != "url" && name != "ref" && name != "rev") + throw Error("unsupported Git input attribute '%s'", name); + auto input = std::make_unique(parseURL(getStrAttr(attrs, "url"))); - input->ref = maybeGetStrAttr(attrs, "ref"); + if (auto ref = maybeGetStrAttr(attrs, "ref")) { + if (!std::regex_match(*ref, refRegex)) + throw BadURL("invalid Git branch/tag name '%s'", *ref); + input->ref = *ref; + } if (auto rev = maybeGetStrAttr(attrs, "rev")) input->rev = Hash(*rev, htSHA1); return input; diff --git a/src/libstore/fetchers/github.cc b/src/libstore/fetchers/github.cc index 13ac4e2f1..c8746b723 100644 --- a/src/libstore/fetchers/github.cc +++ b/src/libstore/fetchers/github.cc @@ -166,8 +166,6 @@ struct GitHubInputScheme : InputScheme for (auto &[name, value] : url.query) { if (name == "rev") { - if (!std::regex_match(value, revRegex)) - throw BadURL("GitHub URL '%s' contains an invalid commit hash", url.url); if (input->rev) throw BadURL("GitHub URL '%s' contains multiple commit hashes", url.url); input->rev = Hash(value, htSHA1); @@ -193,6 +191,11 @@ struct GitHubInputScheme : InputScheme std::unique_ptr inputFromAttrs(const Input::Attrs & attrs) override { if (maybeGetStrAttr(attrs, "type") != "github") return {}; + + for (auto & [name, value] : attrs) + if (name != "type" && name != "owner" && name != "repo" && name != "ref" && name != "rev") + throw Error("unsupported GitHub input attribute '%s'", name); + auto input = std::make_unique(); input->owner = getStrAttr(attrs, "owner"); input->repo = getStrAttr(attrs, "repo"); diff --git a/src/libstore/fetchers/indirect.cc b/src/libstore/fetchers/indirect.cc index d079b3ad3..016f5fb39 100644 --- a/src/libstore/fetchers/indirect.cc +++ b/src/libstore/fetchers/indirect.cc @@ -123,6 +123,11 @@ struct IndirectInputScheme : InputScheme std::unique_ptr inputFromAttrs(const Input::Attrs & attrs) override { if (maybeGetStrAttr(attrs, "type") != "indirect") return {}; + + for (auto & [name, value] : attrs) + if (name != "type" && name != "id" && name != "ref" && name != "rev") + throw Error("unsupported indirect input attribute '%s'", name); + auto input = std::make_unique(); input->id = getStrAttr(attrs, "id"); input->ref = maybeGetStrAttr(attrs, "ref"); diff --git a/src/libstore/fetchers/mercurial.cc b/src/libstore/fetchers/mercurial.cc index f0135d512..1bdab1dbf 100644 --- a/src/libstore/fetchers/mercurial.cc +++ b/src/libstore/fetchers/mercurial.cc @@ -264,32 +264,39 @@ struct MercurialInputScheme : InputScheme url.scheme != "hg+ssh" && url.scheme != "hg+file") return nullptr; - auto input = std::make_unique(url); + auto url2(url); + // FIXME: strip hg+ + url2.query.clear(); - input->url.query.clear(); + Input::Attrs attrs; + attrs.emplace("type", "hg"); for (auto &[name, value] : url.query) { - if (name == "rev") { - if (!std::regex_match(value, revRegex)) - throw BadURL("Mercurial URL '%s' contains an invalid commit hash", url.url); - input->rev = Hash(value, htSHA1); - } - else if (name == "ref") { - if (!std::regex_match(value, refRegex)) - throw BadURL("Mercurial URL '%s' contains an invalid branch/tag name", url.url); - input->ref = value; - } - else input->url.query.insert_or_assign(name, value); + if (name == "rev" || name == "ref") + attrs.emplace(name, value); + else + url2.query.emplace(name, value); } - return input; + attrs.emplace("url", url2.to_string()); + + return inputFromAttrs(attrs); } std::unique_ptr inputFromAttrs(const Input::Attrs & attrs) override { if (maybeGetStrAttr(attrs, "type") != "hg") return {}; + + for (auto & [name, value] : attrs) + if (name != "type" && name != "url" && name != "ref" && name != "rev") + throw Error("unsupported Mercurial input attribute '%s'", name); + auto input = std::make_unique(parseURL(getStrAttr(attrs, "url"))); - input->ref = maybeGetStrAttr(attrs, "ref"); + if (auto ref = maybeGetStrAttr(attrs, "ref")) { + if (!std::regex_match(*ref, refRegex)) + throw BadURL("invalid Mercurial branch/tag name '%s'", *ref); + input->ref = *ref; + } if (auto rev = maybeGetStrAttr(attrs, "rev")) input->rev = Hash(*rev, htSHA1); return input; diff --git a/src/libstore/fetchers/tarball.cc b/src/libstore/fetchers/tarball.cc index 21c785ada..1302299b3 100644 --- a/src/libstore/fetchers/tarball.cc +++ b/src/libstore/fetchers/tarball.cc @@ -110,6 +110,11 @@ struct TarballInputScheme : InputScheme std::unique_ptr inputFromAttrs(const Input::Attrs & attrs) override { if (maybeGetStrAttr(attrs, "type") != "tarball") return {}; + + for (auto & [name, value] : attrs) + if (name != "type" && name != "url" && name != "hash" && name != "narHash") + throw Error("unsupported tarball input attribute '%s'", name); + auto input = std::make_unique(parseURL(getStrAttr(attrs, "url"))); if (auto hash = maybeGetStrAttr(attrs, "hash")) // FIXME: require SRI hash. diff --git a/src/nix/installables.cc b/src/nix/installables.cc index 77a43ef2a..cf91be51b 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -450,7 +450,8 @@ std::vector> SourceExprCommand::parseInstallables( if (hasPrefix(s, "nixpkgs.")) { bool static warned; warnOnce(warned, "the syntax 'nixpkgs.' is deprecated; use 'nixpkgs:' instead"); - result.push_back(std::make_shared(*this, parseFlakeRef("flake:nixpkgs"), + result.push_back(std::make_shared(*this, + FlakeRef::fromAttrs({{"type", "indirect"}, {"id", "nixpkgs"}}), Strings{"legacyPackages." + settings.thisSystem.get() + "." + std::string(s, 8)}, Strings{})); }