aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/flake/flakeref.cc6
-rw-r--r--src/libfetchers/fetchers.cc8
-rw-r--r--src/libfetchers/fetchers.hh6
-rw-r--r--src/libfetchers/git.cc2
-rw-r--r--src/libfetchers/github.cc2
-rw-r--r--src/libfetchers/indirect.cc2
-rw-r--r--src/libfetchers/mercurial.cc2
-rw-r--r--src/libfetchers/path.cc2
-rw-r--r--src/libfetchers/tarball.cc18
-rw-r--r--tests/fetchTree-file.sh14
10 files changed, 37 insertions, 25 deletions
diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc
index 08adbe0c9..d3fa1d557 100644
--- a/src/libexpr/flake/flakeref.cc
+++ b/src/libexpr/flake/flakeref.cc
@@ -105,7 +105,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
};
return std::make_pair(
- FlakeRef(Input::fromURL(parsedURL), ""),
+ FlakeRef(Input::fromURL(parsedURL, isFlake), ""),
percentDecode(match.str(6)));
}
@@ -176,7 +176,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
parsedURL.query.insert_or_assign("shallow", "1");
return std::make_pair(
- FlakeRef(Input::fromURL(parsedURL), getOr(parsedURL.query, "dir", "")),
+ FlakeRef(Input::fromURL(parsedURL, isFlake), getOr(parsedURL.query, "dir", "")),
fragment);
}
@@ -204,7 +204,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
std::string fragment;
std::swap(fragment, parsedURL.fragment);
- auto input = Input::fromURL(parsedURL);
+ auto input = Input::fromURL(parsedURL, isFlake);
input.parent = baseDir;
return std::make_pair(
diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc
index f86c0604e..e683b9f80 100644
--- a/src/libfetchers/fetchers.cc
+++ b/src/libfetchers/fetchers.cc
@@ -13,9 +13,9 @@ void registerInputScheme(std::shared_ptr<InputScheme> && inputScheme)
inputSchemes->push_back(std::move(inputScheme));
}
-Input Input::fromURL(const std::string & url)
+Input Input::fromURL(const std::string & url, bool requireTree)
{
- return fromURL(parseURL(url));
+ return fromURL(parseURL(url), requireTree);
}
static void fixupInput(Input & input)
@@ -31,10 +31,10 @@ static void fixupInput(Input & input)
input.locked = true;
}
-Input Input::fromURL(const ParsedURL & url)
+Input Input::fromURL(const ParsedURL & url, bool requireTree)
{
for (auto & inputScheme : *inputSchemes) {
- auto res = inputScheme->inputFromURL(url);
+ auto res = inputScheme->inputFromURL(url, requireTree);
if (res) {
res->scheme = inputScheme;
fixupInput(*res);
diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh
index d0738f619..6e10e9513 100644
--- a/src/libfetchers/fetchers.hh
+++ b/src/libfetchers/fetchers.hh
@@ -44,9 +44,9 @@ struct Input
std::optional<Path> parent;
public:
- static Input fromURL(const std::string & url);
+ static Input fromURL(const std::string & url, bool requireTree = true);
- static Input fromURL(const ParsedURL & url);
+ static Input fromURL(const ParsedURL & url, bool requireTree = true);
static Input fromAttrs(Attrs && attrs);
@@ -129,7 +129,7 @@ struct InputScheme
virtual ~InputScheme()
{ }
- virtual std::optional<Input> inputFromURL(const ParsedURL & url) const = 0;
+ virtual std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const = 0;
virtual std::optional<Input> inputFromAttrs(const Attrs & attrs) const = 0;
diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc
index be5842d53..f8d89ab2f 100644
--- a/src/libfetchers/git.cc
+++ b/src/libfetchers/git.cc
@@ -256,7 +256,7 @@ std::pair<StorePath, Input> fetchFromWorkdir(ref<Store> store, Input & input, co
struct GitInputScheme : InputScheme
{
- std::optional<Input> inputFromURL(const ParsedURL & url) const override
+ std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
{
if (url.scheme != "git" &&
url.scheme != "git+http" &&
diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc
index 80598e7f8..291f457f0 100644
--- a/src/libfetchers/github.cc
+++ b/src/libfetchers/github.cc
@@ -30,7 +30,7 @@ struct GitArchiveInputScheme : InputScheme
virtual std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const = 0;
- std::optional<Input> inputFromURL(const ParsedURL & url) const override
+ std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
{
if (url.scheme != type()) return {};
diff --git a/src/libfetchers/indirect.cc b/src/libfetchers/indirect.cc
index b99504a16..4874a43ff 100644
--- a/src/libfetchers/indirect.cc
+++ b/src/libfetchers/indirect.cc
@@ -7,7 +7,7 @@ std::regex flakeRegex("[a-zA-Z][a-zA-Z0-9_-]*", std::regex::ECMAScript);
struct IndirectInputScheme : InputScheme
{
- std::optional<Input> inputFromURL(const ParsedURL & url) const override
+ std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
{
if (url.scheme != "flake") return {};
diff --git a/src/libfetchers/mercurial.cc b/src/libfetchers/mercurial.cc
index 86e8f81f4..51fd1ed42 100644
--- a/src/libfetchers/mercurial.cc
+++ b/src/libfetchers/mercurial.cc
@@ -43,7 +43,7 @@ static std::string runHg(const Strings & args, const std::optional<std::string>
struct MercurialInputScheme : InputScheme
{
- std::optional<Input> inputFromURL(const ParsedURL & url) const override
+ std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
{
if (url.scheme != "hg+http" &&
url.scheme != "hg+https" &&
diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc
index 61541e69d..01f1be978 100644
--- a/src/libfetchers/path.cc
+++ b/src/libfetchers/path.cc
@@ -6,7 +6,7 @@ namespace nix::fetchers {
struct PathInputScheme : InputScheme
{
- std::optional<Input> inputFromURL(const ParsedURL & url) const override
+ std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
{
if (url.scheme != "path") return {};
diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc
index a012234e0..107d38e92 100644
--- a/src/libfetchers/tarball.cc
+++ b/src/libfetchers/tarball.cc
@@ -194,11 +194,11 @@ struct CurlInputScheme : InputScheme
|| hasSuffix(path, ".tar.zst");
}
- virtual bool isValidURL(const ParsedURL & url) const = 0;
+ virtual bool isValidURL(const ParsedURL & url, bool requireTree) const = 0;
- std::optional<Input> inputFromURL(const ParsedURL & _url) const override
+ std::optional<Input> inputFromURL(const ParsedURL & _url, bool requireTree) const override
{
- if (!isValidURL(_url))
+ if (!isValidURL(_url, requireTree))
return std::nullopt;
Input input;
@@ -265,13 +265,13 @@ struct FileInputScheme : CurlInputScheme
{
const std::string inputType() const override { return "file"; }
- bool isValidURL(const ParsedURL & url) const override
+ bool isValidURL(const ParsedURL & url, bool requireTree) const override
{
auto parsedUrlScheme = parseUrlScheme(url.scheme);
return transportUrlSchemes.count(std::string(parsedUrlScheme.transport))
&& (parsedUrlScheme.application
- ? parsedUrlScheme.application.value() == inputType()
- : !hasTarballExtension(url.path));
+ ? parsedUrlScheme.application.value() == inputType()
+ : (!requireTree && !hasTarballExtension(url.path)));
}
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) override
@@ -285,14 +285,14 @@ struct TarballInputScheme : CurlInputScheme
{
const std::string inputType() const override { return "tarball"; }
- bool isValidURL(const ParsedURL & url) const override
+ bool isValidURL(const ParsedURL & url, bool requireTree) const override
{
auto parsedUrlScheme = parseUrlScheme(url.scheme);
return transportUrlSchemes.count(std::string(parsedUrlScheme.transport))
&& (parsedUrlScheme.application
- ? parsedUrlScheme.application.value() == inputType()
- : hasTarballExtension(url.path));
+ ? parsedUrlScheme.application.value() == inputType()
+ : (requireTree || hasTarballExtension(url.path)));
}
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
diff --git a/tests/fetchTree-file.sh b/tests/fetchTree-file.sh
index fe569cfb8..6395c133d 100644
--- a/tests/fetchTree-file.sh
+++ b/tests/fetchTree-file.sh
@@ -27,6 +27,7 @@ test_file_flake_input () {
mkdir inputs
echo foo > inputs/test_input_file
+ echo '{ outputs = { self }: { }; }' > inputs/flake.nix
tar cfa test_input.tar.gz inputs
cp test_input.tar.gz test_input_no_ext
input_tarball_hash="$(nix hash path test_input.tar.gz)"
@@ -50,6 +51,9 @@ test_file_flake_input () {
url = "file+file://$PWD/test_input.tar.gz";
flake = false;
};
+ inputs.flake_no_ext = {
+ url = "file://$PWD/test_input_no_ext";
+ };
outputs = { ... }: {};
}
EOF
@@ -58,7 +62,7 @@ EOF
nix eval --file - <<EOF
with (builtins.fromJSON (builtins.readFile ./flake.lock));
- # Url inputs whose extension doesn’t match a known archive format should
+ # Non-flake inputs whose extension doesn’t match a known archive format should
# not be unpacked by default
assert (nodes.no_ext_default_no_unpack.locked.type == "file");
assert (nodes.no_ext_default_no_unpack.locked.unpack or false == false);
@@ -75,8 +79,16 @@ EOF
# Explicitely passing the unpack parameter should enforce the desired behavior
assert (nodes.no_ext_explicit_unpack.locked.narHash == nodes.tarball_default_unpack.locked.narHash);
assert (nodes.tarball_explicit_no_unpack.locked.narHash == nodes.no_ext_default_no_unpack.locked.narHash);
+
+ # Flake inputs should always be tarballs
+ assert (nodes.flake_no_ext.locked.type == "tarball");
+
true
EOF
+
+ # Test tarball URLs on the command line.
+ [[ $(nix flake metadata --json file://$PWD/test_input_no_ext | jq -r .resolved.type) = tarball ]]
+
popd
[[ -z "${NIX_DAEMON_PACKAGE-}" ]] && return 0