aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-01-28 13:11:02 +0100
committerEelco Dolstra <edolstra@gmail.com>2020-01-28 13:11:02 +0100
commit1af7b94c1d4655e8d10529c257ce044294c33137 (patch)
treeb5e630fdd070011c0ffe7a27a0f95e06c2164f67 /src/libstore
parentc39c2503f721406e655ee6700cafd7f1ddc65894 (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.cc4
-rw-r--r--src/libstore/fetchers/fetchers.hh2
-rw-r--r--src/libstore/fetchers/tarball.cc91
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>()); });
+
+}