Skip to content

Commit

Permalink
Backport libfetchers from the flakes branch
Browse files Browse the repository at this point in the history
This provides a pluggable mechanism for defining new fetchers. It adds
a builtin function 'fetchTree' that generalizes existing fetchers like
'fetchGit', 'fetchMercurial' and 'fetchTarball'. 'fetchTree' takes a
set of attributes, e.g.

  fetchTree {
    type = "git";
    url = "https://example.org/repo.git";
    ref = "some-branch";
    rev = "abcdef...";
  }

The existing fetchers are just wrappers around this. Note that the
input attributes to fetchTree are the same as flake input
specifications and flake lock file entries.

All fetchers share a common cache stored in
~/.cache/nix/fetcher-cache-v1.sqlite. This replaces the ad hoc caching
mechanisms in fetchGit and download.cc (e.g. ~/.cache/nix/{tarballs,git-revs*}).

This also adds support for Git worktrees (c169ea5).
  • Loading branch information
edolstra committed Mar 30, 2020
1 parent 367577d commit 5512bdd
Show file tree
Hide file tree
Showing 35 changed files with 2,328 additions and 647 deletions.
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -4,6 +4,7 @@ makefiles = \
nix-rust/local.mk \
src/libutil/local.mk \
src/libstore/local.mk \
src/libfetchers/local.mk \
src/libmain/local.mk \
src/libexpr/local.mk \
src/nix/local.mk \
Expand Down
8 changes: 5 additions & 3 deletions src/libexpr/common-eval-args.cc
Expand Up @@ -3,6 +3,8 @@
#include "download.hh"
#include "util.hh"
#include "eval.hh"
#include "fetchers.hh"
#include "store-api.hh"

namespace nix {

Expand Down Expand Up @@ -46,9 +48,9 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
Path lookupFileArg(EvalState & state, string s)
{
if (isUri(s)) {
CachedDownloadRequest request(s);
request.unpack = true;
return getDownloader()->downloadCached(state.store, request).path;
return state.store->toRealPath(
fetchers::downloadTarball(
state.store, resolveUri(s), "source", false).storePath);
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
Path p = s.substr(1, s.size() - 2);
return state.findFile(p);
Expand Down
4 changes: 2 additions & 2 deletions src/libexpr/local.mk
Expand Up @@ -6,9 +6,9 @@ libexpr_DIR := $(d)

libexpr_SOURCES := $(wildcard $(d)/*.cc) $(wildcard $(d)/primops/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc

libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libmain -I src/libexpr
libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libmain -I src/libexpr

libexpr_LIBS = libutil libstore libnixrust
libexpr_LIBS = libutil libstore libfetchers libnixrust

libexpr_LDFLAGS =
ifneq ($(OS), FreeBSD)
Expand Down
6 changes: 3 additions & 3 deletions src/libexpr/parser.y
Expand Up @@ -545,6 +545,7 @@ formal

#include "eval.hh"
#include "download.hh"
#include "fetchers.hh"
#include "store-api.hh"


Expand Down Expand Up @@ -687,9 +688,8 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl

if (isUri(elem.second)) {
try {
CachedDownloadRequest request(elem.second);
request.unpack = true;
res = { true, getDownloader()->downloadCached(store, request).path };
res = { true, store->toRealPath(fetchers::downloadTarball(
store, resolveUri(elem.second), "source", false).storePath) };
} catch (DownloadError & e) {
printError(format("warning: Nix search path entry '%1%' cannot be downloaded, ignoring") % elem.second);
res = { false, "" };
Expand Down
67 changes: 0 additions & 67 deletions src/libexpr/primops.cc
@@ -1,6 +1,5 @@
#include "archive.hh"
#include "derivations.hh"
#include "download.hh"
#include "eval-inline.hh"
#include "eval.hh"
#include "globals.hh"
Expand Down Expand Up @@ -2045,68 +2044,6 @@ static void prim_splitVersion(EvalState & state, const Pos & pos, Value * * args
}


/*************************************************************
* Networking
*************************************************************/


void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
const string & who, bool unpack, const std::string & defaultName)
{
CachedDownloadRequest request("");
request.unpack = unpack;
request.name = defaultName;

state.forceValue(*args[0]);

if (args[0]->type == tAttrs) {

state.forceAttrs(*args[0], pos);

for (auto & attr : *args[0]->attrs) {
string n(attr.name);
if (n == "url")
request.uri = state.forceStringNoCtx(*attr.value, *attr.pos);
else if (n == "sha256")
request.expectedHash = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
else if (n == "name")
request.name = state.forceStringNoCtx(*attr.value, *attr.pos);
else
throw EvalError(format("unsupported argument '%1%' to '%2%', at %3%") % attr.name % who % attr.pos);
}

if (request.uri.empty())
throw EvalError(format("'url' argument required, at %1%") % pos);

} else
request.uri = state.forceStringNoCtx(*args[0], pos);

state.checkURI(request.uri);

if (evalSettings.pureEval && !request.expectedHash)
throw Error("in pure evaluation mode, '%s' requires a 'sha256' argument", who);

auto res = getDownloader()->downloadCached(state.store, request);

if (state.allowedPaths)
state.allowedPaths->insert(res.path);

mkString(v, res.storePath, PathSet({res.storePath}));
}


static void prim_fetchurl(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
fetch(state, pos, args, v, "fetchurl", false, "");
}


static void prim_fetchTarball(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
fetch(state, pos, args, v, "fetchTarball", true, "source");
}


/*************************************************************
* Primop registration
*************************************************************/
Expand Down Expand Up @@ -2289,10 +2226,6 @@ void EvalState::createBaseEnv()
addPrimOp("derivationStrict", 1, prim_derivationStrict);
addPrimOp("placeholder", 1, prim_placeholder);

// Networking
addPrimOp("__fetchurl", 1, prim_fetchurl);
addPrimOp("fetchTarball", 1, prim_fetchTarball);

/* Add a wrapper around the derivation primop that computes the
`drvPath' and `outPath' attributes lazily. */
string path = canonPath(settings.nixDataDir + "/nix/corepkgs/derivation.nix", true);
Expand Down
1 change: 1 addition & 0 deletions src/libexpr/primops.hh
Expand Up @@ -20,6 +20,7 @@ struct RegisterPrimOp
them. */
/* Load a ValueInitializer from a DSO and return whatever it initializes */
void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value & v);

/* Execute a program and parse its output */
void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value & v);

Expand Down

0 comments on commit 5512bdd

Please sign in to comment.