aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/primops/fetchTree.cc61
-rw-r--r--tests/tarball.sh6
2 files changed, 67 insertions, 0 deletions
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
new file mode 100644
index 000000000..ccb0cacd5
--- /dev/null
+++ b/src/libexpr/primops/fetchTree.cc
@@ -0,0 +1,61 @@
+#include "primops.hh"
+#include "eval-inline.hh"
+#include "store-api.hh"
+#include "fetchers/fetchers.hh"
+#include "fetchers/registry.hh"
+
+namespace nix {
+
+static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+ std::shared_ptr<const fetchers::Input> input;
+ PathSet context;
+
+ state.forceValue(*args[0]);
+
+ if (args[0]->type == tAttrs) {
+ state.forceAttrs(*args[0], pos);
+
+ fetchers::Input::Attrs attrs;
+
+ for (auto & attr : *args[0]->attrs) {
+ state.forceValue(*attr.value);
+ if (attr.value->type == tString)
+ attrs.emplace(attr.name, attr.value->string.s);
+ else
+ throw Error("unsupported attribute type");
+ }
+
+ if (!attrs.count("type"))
+ throw Error("attribute 'type' is missing in call to 'fetchTree', at %s", pos);
+
+ input = fetchers::inputFromAttrs(attrs);
+ } else
+ input = fetchers::inputFromURL(state.coerceToString(pos, *args[0], context, false, false));
+
+ if (!evalSettings.pureEval && !input->isDirect())
+ input = lookupInRegistries(state.store, input);
+
+ if (evalSettings.pureEval && !input->isImmutable())
+ throw Error("in pure evaluation mode, 'fetchTree' requires an immutable input");
+
+ auto [tree, input2] = input->fetchTree(state.store);
+
+ state.mkAttrs(v, 8);
+ auto storePath = state.store->printStorePath(tree.storePath);
+ mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));
+ if (input2->getRev()) {
+ mkString(*state.allocAttr(v, state.symbols.create("rev")), input2->getRev()->gitRev());
+ mkString(*state.allocAttr(v, state.symbols.create("shortRev")), input2->getRev()->gitShortRev());
+ }
+ if (tree.info.revCount)
+ mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *tree.info.revCount);
+ v.attrs->sort();
+
+ if (state.allowedPaths)
+ state.allowedPaths->insert(tree.actualPath);
+}
+
+static RegisterPrimOp r("fetchTree", 1, prim_fetchTree);
+
+}
diff --git a/tests/tarball.sh b/tests/tarball.sh
index 8adb8d72f..7c8896b2e 100644
--- a/tests/tarball.sh
+++ b/tests/tarball.sh
@@ -10,6 +10,8 @@ mkdir -p $tarroot
cp dependencies.nix $tarroot/default.nix
cp config.nix dependencies.builder*.sh $tarroot/
+hash=$(nix hash-path $tarroot)
+
test_tarball() {
local ext="$1"
local compressor="$2"
@@ -25,6 +27,10 @@ test_tarball() {
nix-build -o $TEST_ROOT/result -E "import (fetchTarball file://$tarball)"
+ nix-build -o $TEST_ROOT/result -E "import (fetchTree file://$tarball)"
+ nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; })"
+ nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })"
+
nix-instantiate --eval -E '1 + 2' -I fnord=file://no-such-tarball.tar$ext
nix-instantiate --eval -E 'with <fnord/xyzzy>; 1 + 2' -I fnord=file://no-such-tarball$ext
(! nix-instantiate --eval -E '<fnord/xyzzy> 1' -I fnord=file://no-such-tarball$ext)