Add support for tarball flake inputs
For example, $ nix flake info https://github.com/edolstra/dwarffs/archive/master.tar.gz Fixes #2929.
This commit is contained in:
parent
c39c2503f7
commit
1af7b94c1d
4 changed files with 110 additions and 1 deletions
|
@ -39,6 +39,10 @@ std::pair<Tree, std::shared_ptr<const Input>> Input::fetchTree(ref<Store> store)
|
|||
if (input->narHash)
|
||||
assert(input->narHash == tree.narHash);
|
||||
|
||||
if (narHash && narHash != input->narHash)
|
||||
throw Error("NAR hash mismatch in input '%s', expected '%s', got '%s'",
|
||||
to_string(), narHash->to_string(SRI), input->narHash->to_string(SRI));
|
||||
|
||||
return {std::move(tree), input};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ struct Tree
|
|||
struct Input : std::enable_shared_from_this<Input>
|
||||
{
|
||||
std::string type;
|
||||
std::optional<Hash> narHash;
|
||||
std::optional<Hash> narHash; // FIXME: implement
|
||||
|
||||
virtual ~Input() { }
|
||||
|
||||
|
|
91
src/libstore/fetchers/tarball.cc
Normal file
91
src/libstore/fetchers/tarball.cc
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include "fetchers.hh"
|
||||
#include "download.hh"
|
||||
#include "globals.hh"
|
||||
#include "parse.hh"
|
||||
#include "store-api.hh"
|
||||
|
||||
namespace nix::fetchers {
|
||||
|
||||
struct TarballInput : Input
|
||||
{
|
||||
ParsedURL url;
|
||||
std::optional<Hash> hash;
|
||||
|
||||
bool operator ==(const Input & other) const override
|
||||
{
|
||||
auto other2 = dynamic_cast<const TarballInput *>(&other);
|
||||
return
|
||||
other2
|
||||
&& to_string() == other2->to_string()
|
||||
&& hash == other2->hash;
|
||||
}
|
||||
|
||||
bool isImmutable() const override
|
||||
{
|
||||
return (bool) hash;
|
||||
}
|
||||
|
||||
std::string to_string() const override
|
||||
{
|
||||
auto url2(url);
|
||||
if (narHash)
|
||||
url2.query.insert_or_assign("narHash", narHash->to_string(SRI));
|
||||
return url2.to_string();
|
||||
}
|
||||
|
||||
std::pair<Tree, std::shared_ptr<const Input>> fetchTreeInternal(nix::ref<Store> store) const override
|
||||
{
|
||||
CachedDownloadRequest request(url.to_string());
|
||||
request.unpack = true;
|
||||
request.getLastModified = true;
|
||||
request.name = "source";
|
||||
|
||||
auto res = getDownloader()->downloadCached(store, request);
|
||||
|
||||
auto input = std::make_shared<TarballInput>(*this);
|
||||
|
||||
auto storePath = store->parseStorePath(res.storePath);
|
||||
|
||||
input->narHash = store->queryPathInfo(storePath)->narHash;
|
||||
|
||||
return {
|
||||
Tree {
|
||||
.actualPath = res.path,
|
||||
.storePath = std::move(storePath),
|
||||
.lastModified = *res.lastModified
|
||||
},
|
||||
input
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct TarballInputScheme : InputScheme
|
||||
{
|
||||
std::unique_ptr<Input> inputFromURL(const ParsedURL & url) override
|
||||
{
|
||||
if (url.scheme != "file" && url.scheme != "http" && url.scheme != "https") return nullptr;
|
||||
|
||||
if (!hasSuffix(url.path, ".zip")
|
||||
&& !hasSuffix(url.path, ".tar")
|
||||
&& !hasSuffix(url.path, ".tar.gz")
|
||||
&& !hasSuffix(url.path, ".tar.xz")
|
||||
&& !hasSuffix(url.path, ".tar.bz2"))
|
||||
return nullptr;
|
||||
|
||||
auto input = std::make_unique<TarballInput>();
|
||||
input->type = "tarball";
|
||||
input->url = url;
|
||||
|
||||
auto narHash = url.query.find("narHash");
|
||||
if (narHash != url.query.end()) {
|
||||
// FIXME: require SRI hash.
|
||||
input->narHash = Hash(narHash->second);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
};
|
||||
|
||||
static auto r1 = OnStartup([] { registerInputScheme(std::make_unique<TarballInputScheme>()); });
|
||||
|
||||
}
|
|
@ -573,3 +573,17 @@ nix flake info --flake-registry $registry --json hg+file://$flake5Dir
|
|||
[[ $(nix flake info --flake-registry $registry --json hg+file://$flake5Dir | jq -e -r .revCount) = 1 ]]
|
||||
|
||||
nix build -o $TEST_ROOT/result hg+file://$flake5Dir --no-registries --no-allow-dirty
|
||||
|
||||
# Test tarball flakes
|
||||
tar cfz $TEST_ROOT/flake.tar.gz -C $TEST_ROOT flake5
|
||||
|
||||
nix build -o $TEST_ROOT/result file://$TEST_ROOT/flake.tar.gz
|
||||
|
||||
# Building with a tarball URL containing a SRI hash should also work.
|
||||
url=$(nix flake info --json file://$TEST_ROOT/flake.tar.gz | jq -r .url)
|
||||
[[ $url =~ sha256- ]]
|
||||
|
||||
nix build -o $TEST_ROOT/result $url
|
||||
|
||||
# Building with an incorrect SRI hash should fail.
|
||||
nix build -o $TEST_ROOT/result "file://$TEST_ROOT/flake.tar.gz?narHash=sha256-qQ2Zz4DNHViCUrp6gTS7EE4+RMqFQtUfWF2UNUtJKS0=" 2>&1 | grep 'NAR hash mismatch'
|
||||
|
|
Loading…
Reference in a new issue