diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2020-01-28 13:11:02 +0100 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2020-01-28 13:11:02 +0100 |
commit | 1af7b94c1d4655e8d10529c257ce044294c33137 (patch) | |
tree | b5e630fdd070011c0ffe7a27a0f95e06c2164f67 /src/libstore | |
parent | c39c2503f721406e655ee6700cafd7f1ddc65894 (diff) |
Add support for tarball flake inputs
For example,
$ nix flake info https://github.com/edolstra/dwarffs/archive/master.tar.gz
Fixes #2929.
Diffstat (limited to 'src/libstore')
-rw-r--r-- | src/libstore/fetchers/fetchers.cc | 4 | ||||
-rw-r--r-- | src/libstore/fetchers/fetchers.hh | 2 | ||||
-rw-r--r-- | src/libstore/fetchers/tarball.cc | 91 |
3 files changed, 96 insertions, 1 deletions
diff --git a/src/libstore/fetchers/fetchers.cc b/src/libstore/fetchers/fetchers.cc index 7f82d5af0..efc18dbb8 100644 --- a/src/libstore/fetchers/fetchers.cc +++ b/src/libstore/fetchers/fetchers.cc @@ -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}; } diff --git a/src/libstore/fetchers/fetchers.hh b/src/libstore/fetchers/fetchers.hh index 1f3be8c2b..ccc1683ba 100644 --- a/src/libstore/fetchers/fetchers.hh +++ b/src/libstore/fetchers/fetchers.hh @@ -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() { } diff --git a/src/libstore/fetchers/tarball.cc b/src/libstore/fetchers/tarball.cc new file mode 100644 index 000000000..e82066089 --- /dev/null +++ b/src/libstore/fetchers/tarball.cc @@ -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>()); }); + +} |