diff --git a/doc/manual/command-ref/nix-prefetch-url.xml b/doc/manual/command-ref/nix-prefetch-url.xml
index 0f24bef39..9cbaa42a1 100644
--- a/doc/manual/command-ref/nix-prefetch-url.xml
+++ b/doc/manual/command-ref/nix-prefetch-url.xml
@@ -20,6 +20,7 @@
nix-prefetch-url
hashAlgo
+
url
hash
diff --git a/src/nix-prefetch-url/nix-prefetch-url.cc b/src/nix-prefetch-url/nix-prefetch-url.cc
index cb6078fca..112d303e0 100644
--- a/src/nix-prefetch-url/nix-prefetch-url.cc
+++ b/src/nix-prefetch-url/nix-prefetch-url.cc
@@ -5,6 +5,7 @@
#include "eval.hh"
#include "eval-inline.hh"
#include "common-opts.hh"
+#include "attr-path.hh"
#include
@@ -49,6 +50,9 @@ int main(int argc, char * * argv)
std::vector args;
Strings searchPath;
bool printPath = getEnv("PRINT_PATH") != "";
+ bool fromExpr = false;
+ string attrPath;
+ std::map autoArgs_;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
if (*arg == "--help")
@@ -63,6 +67,12 @@ int main(int argc, char * * argv)
}
else if (*arg == "--print-path")
printPath = true;
+ else if (*arg == "--attr" || *arg == "-A") {
+ fromExpr = true;
+ attrPath = getArg(*arg, arg, end);
+ }
+ else if (parseAutoArgs(arg, end, autoArgs_))
+ ;
else if (parseSearchPathArg(arg, end, searchPath))
;
else if (*arg != "" && arg->at(0) == '-')
@@ -72,15 +82,37 @@ int main(int argc, char * * argv)
return true;
});
- if (args.size() < 1 || args.size() > 2)
- throw UsageError("nix-prefetch-url expects one argument");
+ if (args.size() > 2)
+ throw UsageError("too many arguments");
store = openStore();
-
EvalState state(searchPath);
+ Bindings & autoArgs(*evalAutoArgs(state, autoArgs_));
+
+ /* If -A is given, get the URI from the specified Nix
+ expression. */
+ string uri;
+ if (!fromExpr) {
+ if (args.empty())
+ throw UsageError("you must specify a URI");
+ uri = args[0];
+ } else {
+ Path path = resolveExprPath(lookupFileArg(state, args.empty() ? "." : args[0]));
+ Value vRoot;
+ state.evalFile(path, vRoot);
+ Value & v(*findAlongAttrPath(state, attrPath, autoArgs, vRoot));
+ state.forceAttrs(v);
+ auto urls = v.attrs->find(state.symbols.create("urls"));
+ if (urls == v.attrs->end())
+ throw Error("attribute set does not contain a ‘urls’ attribute");
+ state.forceList(*urls->value);
+ if (urls->value->listSize() < 1)
+ throw Error("‘urls’ list is empty");
+ uri = state.forceString(*urls->value->listElems()[0]);
+ }
+
/* Figure out a name in the Nix store. */
- auto uri = args[0];
auto name = baseNameOf(uri);
if (name.empty())
throw Error(format("cannot figure out file name for ‘%1%’") % uri);