Merge pull request #8769 from edolstra/generalize-tarball-urls
Don't require .tar/.zip extension for tarball flakerefs
This commit is contained in:
commit
eb1302670e
10 changed files with 37 additions and 25 deletions
|
@ -105,7 +105,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
||||||
};
|
};
|
||||||
|
|
||||||
return std::make_pair(
|
return std::make_pair(
|
||||||
FlakeRef(Input::fromURL(parsedURL), ""),
|
FlakeRef(Input::fromURL(parsedURL, isFlake), ""),
|
||||||
percentDecode(match.str(6)));
|
percentDecode(match.str(6)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
||||||
parsedURL.query.insert_or_assign("shallow", "1");
|
parsedURL.query.insert_or_assign("shallow", "1");
|
||||||
|
|
||||||
return std::make_pair(
|
return std::make_pair(
|
||||||
FlakeRef(Input::fromURL(parsedURL), getOr(parsedURL.query, "dir", "")),
|
FlakeRef(Input::fromURL(parsedURL, isFlake), getOr(parsedURL.query, "dir", "")),
|
||||||
fragment);
|
fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
||||||
std::string fragment;
|
std::string fragment;
|
||||||
std::swap(fragment, parsedURL.fragment);
|
std::swap(fragment, parsedURL.fragment);
|
||||||
|
|
||||||
auto input = Input::fromURL(parsedURL);
|
auto input = Input::fromURL(parsedURL, isFlake);
|
||||||
input.parent = baseDir;
|
input.parent = baseDir;
|
||||||
|
|
||||||
return std::make_pair(
|
return std::make_pair(
|
||||||
|
|
|
@ -13,9 +13,9 @@ void registerInputScheme(std::shared_ptr<InputScheme> && inputScheme)
|
||||||
inputSchemes->push_back(std::move(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)
|
static void fixupInput(Input & input)
|
||||||
|
@ -31,10 +31,10 @@ static void fixupInput(Input & input)
|
||||||
input.locked = true;
|
input.locked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Input Input::fromURL(const ParsedURL & url)
|
Input Input::fromURL(const ParsedURL & url, bool requireTree)
|
||||||
{
|
{
|
||||||
for (auto & inputScheme : *inputSchemes) {
|
for (auto & inputScheme : *inputSchemes) {
|
||||||
auto res = inputScheme->inputFromURL(url);
|
auto res = inputScheme->inputFromURL(url, requireTree);
|
||||||
if (res) {
|
if (res) {
|
||||||
res->scheme = inputScheme;
|
res->scheme = inputScheme;
|
||||||
fixupInput(*res);
|
fixupInput(*res);
|
||||||
|
|
|
@ -44,9 +44,9 @@ struct Input
|
||||||
std::optional<Path> parent;
|
std::optional<Path> parent;
|
||||||
|
|
||||||
public:
|
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);
|
static Input fromAttrs(Attrs && attrs);
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ struct InputScheme
|
||||||
virtual ~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;
|
virtual std::optional<Input> inputFromAttrs(const Attrs & attrs) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -256,7 +256,7 @@ std::pair<StorePath, Input> fetchFromWorkdir(ref<Store> store, Input & input, co
|
||||||
|
|
||||||
struct GitInputScheme : InputScheme
|
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" &&
|
if (url.scheme != "git" &&
|
||||||
url.scheme != "git+http" &&
|
url.scheme != "git+http" &&
|
||||||
|
|
|
@ -30,7 +30,7 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
|
|
||||||
virtual std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const = 0;
|
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 {};
|
if (url.scheme != type()) return {};
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ std::regex flakeRegex("[a-zA-Z][a-zA-Z0-9_-]*", std::regex::ECMAScript);
|
||||||
|
|
||||||
struct IndirectInputScheme : InputScheme
|
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 {};
|
if (url.scheme != "flake") return {};
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ static std::string runHg(const Strings & args, const std::optional<std::string>
|
||||||
|
|
||||||
struct MercurialInputScheme : InputScheme
|
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" &&
|
if (url.scheme != "hg+http" &&
|
||||||
url.scheme != "hg+https" &&
|
url.scheme != "hg+https" &&
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace nix::fetchers {
|
||||||
|
|
||||||
struct PathInputScheme : InputScheme
|
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 {};
|
if (url.scheme != "path") return {};
|
||||||
|
|
||||||
|
|
|
@ -194,11 +194,11 @@ struct CurlInputScheme : InputScheme
|
||||||
|| hasSuffix(path, ".tar.zst");
|
|| 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;
|
return std::nullopt;
|
||||||
|
|
||||||
Input input;
|
Input input;
|
||||||
|
@ -265,13 +265,13 @@ struct FileInputScheme : CurlInputScheme
|
||||||
{
|
{
|
||||||
const std::string inputType() const override { return "file"; }
|
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);
|
auto parsedUrlScheme = parseUrlScheme(url.scheme);
|
||||||
return transportUrlSchemes.count(std::string(parsedUrlScheme.transport))
|
return transportUrlSchemes.count(std::string(parsedUrlScheme.transport))
|
||||||
&& (parsedUrlScheme.application
|
&& (parsedUrlScheme.application
|
||||||
? parsedUrlScheme.application.value() == inputType()
|
? parsedUrlScheme.application.value() == inputType()
|
||||||
: !hasTarballExtension(url.path));
|
: (!requireTree && !hasTarballExtension(url.path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) override
|
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"; }
|
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);
|
auto parsedUrlScheme = parseUrlScheme(url.scheme);
|
||||||
|
|
||||||
return transportUrlSchemes.count(std::string(parsedUrlScheme.transport))
|
return transportUrlSchemes.count(std::string(parsedUrlScheme.transport))
|
||||||
&& (parsedUrlScheme.application
|
&& (parsedUrlScheme.application
|
||||||
? parsedUrlScheme.application.value() == inputType()
|
? parsedUrlScheme.application.value() == inputType()
|
||||||
: hasTarballExtension(url.path));
|
: (requireTree || hasTarballExtension(url.path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
|
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
|
||||||
|
|
|
@ -27,6 +27,7 @@ test_file_flake_input () {
|
||||||
|
|
||||||
mkdir inputs
|
mkdir inputs
|
||||||
echo foo > inputs/test_input_file
|
echo foo > inputs/test_input_file
|
||||||
|
echo '{ outputs = { self }: { }; }' > inputs/flake.nix
|
||||||
tar cfa test_input.tar.gz inputs
|
tar cfa test_input.tar.gz inputs
|
||||||
cp test_input.tar.gz test_input_no_ext
|
cp test_input.tar.gz test_input_no_ext
|
||||||
input_tarball_hash="$(nix hash path test_input.tar.gz)"
|
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";
|
url = "file+file://$PWD/test_input.tar.gz";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
inputs.flake_no_ext = {
|
||||||
|
url = "file://$PWD/test_input_no_ext";
|
||||||
|
};
|
||||||
outputs = { ... }: {};
|
outputs = { ... }: {};
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
@ -58,7 +62,7 @@ EOF
|
||||||
nix eval --file - <<EOF
|
nix eval --file - <<EOF
|
||||||
with (builtins.fromJSON (builtins.readFile ./flake.lock));
|
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
|
# not be unpacked by default
|
||||||
assert (nodes.no_ext_default_no_unpack.locked.type == "file");
|
assert (nodes.no_ext_default_no_unpack.locked.type == "file");
|
||||||
assert (nodes.no_ext_default_no_unpack.locked.unpack or false == false);
|
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
|
# 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.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);
|
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
|
true
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Test tarball URLs on the command line.
|
||||||
|
[[ $(nix flake metadata --json file://$PWD/test_input_no_ext | jq -r .resolved.type) = tarball ]]
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
[[ -z "${NIX_DAEMON_PACKAGE-}" ]] && return 0
|
[[ -z "${NIX_DAEMON_PACKAGE-}" ]] && return 0
|
||||||
|
|
Loading…
Reference in a new issue