diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc index eeaccb24c..0e99ca0e5 100644 --- a/src/libstore/builtins/buildenv.cc +++ b/src/libstore/builtins/buildenv.cc @@ -1,4 +1,5 @@ #include "nix/store/builtins/buildenv.hh" +#include "nix/store/builtins.hh" #include "nix/store/derivations.hh" #include "nix/util/signals.hh" @@ -166,17 +167,15 @@ void buildProfile(const Path & out, Packages && pkgs) debug("created %d symlinks in user environment", state.symlinks); } -void builtinBuildenv( - const BasicDerivation & drv, - const std::map & outputs) +static void builtinBuildenv(const BuiltinBuilderContext & ctx) { auto getAttr = [&](const std::string & name) { - auto i = drv.env.find(name); - if (i == drv.env.end()) throw Error("attribute '%s' missing", name); + auto i = ctx.drv.env.find(name); + if (i == ctx.drv.env.end()) throw Error("attribute '%s' missing", name); return i->second; }; - auto out = outputs.at("out"); + auto out = ctx.outputs.at("out"); createDirs(out); /* Convert the stuff we get from the environment back into a @@ -203,4 +202,6 @@ void builtinBuildenv( createSymlink(getAttr("manifest"), out + "/manifest.nix"); } +static RegisterBuiltinBuilder registerBuildenv("buildenv", builtinBuildenv); + } diff --git a/src/libstore/builtins/fetchurl.cc b/src/libstore/builtins/fetchurl.cc index 82f268d80..18fa75558 100644 --- a/src/libstore/builtins/fetchurl.cc +++ b/src/libstore/builtins/fetchurl.cc @@ -6,33 +6,29 @@ namespace nix { -void builtinFetchurl( - const BasicDerivation & drv, - const std::map & outputs, - const std::string & netrcData, - const std::string & caFileData) +static void builtinFetchurl(const BuiltinBuilderContext & ctx) { /* Make the host's netrc data available. Too bad curl requires this to be stored in a file. It would be nice if we could just pass a pointer to the data. */ - if (netrcData != "") { + if (ctx.netrcData != "") { settings.netrcFile = "netrc"; - writeFile(settings.netrcFile, netrcData, 0600); + writeFile(settings.netrcFile, ctx.netrcData, 0600); } settings.caFile = "ca-certificates.crt"; - writeFile(settings.caFile, caFileData, 0600); + writeFile(settings.caFile, ctx.caFileData, 0600); - auto out = get(drv.outputs, "out"); + auto out = get(ctx.drv.outputs, "out"); if (!out) throw Error("'builtin:fetchurl' requires an 'out' output"); - if (!(drv.type().isFixed() || drv.type().isImpure())) + if (!(ctx.drv.type().isFixed() || ctx.drv.type().isImpure())) throw Error("'builtin:fetchurl' must be a fixed-output or impure derivation"); - auto storePath = outputs.at("out"); - auto mainUrl = drv.env.at("url"); - bool unpack = getOr(drv.env, "unpack", "") == "1"; + auto storePath = ctx.outputs.at("out"); + auto mainUrl = ctx.drv.env.at("url"); + bool unpack = getOr(ctx.drv.env, "unpack", "") == "1"; /* Note: have to use a fresh fileTransfer here because we're in a forked process. */ @@ -56,8 +52,8 @@ void builtinFetchurl( else writeFile(storePath, *source); - auto executable = drv.env.find("executable"); - if (executable != drv.env.end() && executable->second == "1") { + auto executable = ctx.drv.env.find("executable"); + if (executable != ctx.drv.env.end() && executable->second == "1") { if (chmod(storePath.c_str(), 0755) == -1) throw SysError("making '%1%' executable", storePath); } @@ -79,4 +75,6 @@ void builtinFetchurl( fetch(mainUrl); } +static RegisterBuiltinBuilder registerFetchurl("fetchurl", builtinFetchurl); + } diff --git a/src/libstore/builtins/unpack-channel.cc b/src/libstore/builtins/unpack-channel.cc index e03f3076b..dd6b8bb71 100644 --- a/src/libstore/builtins/unpack-channel.cc +++ b/src/libstore/builtins/unpack-channel.cc @@ -3,17 +3,15 @@ namespace nix { -void builtinUnpackChannel( - const BasicDerivation & drv, - const std::map & outputs) +static void builtinUnpackChannel(const BuiltinBuilderContext & ctx) { auto getAttr = [&](const std::string & name) -> const std::string & { - auto i = drv.env.find(name); - if (i == drv.env.end()) throw Error("attribute '%s' missing", name); + auto i = ctx.drv.env.find(name); + if (i == ctx.drv.env.end()) throw Error("attribute '%s' missing", name); return i->second; }; - std::filesystem::path out{outputs.at("out")}; + std::filesystem::path out{ctx.outputs.at("out")}; auto & channelName = getAttr("channelName"); auto & src = getAttr("src"); @@ -42,4 +40,6 @@ void builtinUnpackChannel( } } +static RegisterBuiltinBuilder registerUnpackChannel("unpack-channel", builtinUnpackChannel); + } diff --git a/src/libstore/include/nix/store/builtins.hh b/src/libstore/include/nix/store/builtins.hh index 004e9ef64..096c8af7b 100644 --- a/src/libstore/include/nix/store/builtins.hh +++ b/src/libstore/include/nix/store/builtins.hh @@ -5,15 +5,30 @@ namespace nix { -// TODO: make pluggable. -void builtinFetchurl( - const BasicDerivation & drv, - const std::map & outputs, - const std::string & netrcData, - const std::string & caFileData); +struct BuiltinBuilderContext +{ + const BasicDerivation & drv; + std::map outputs; + std::string netrcData; + std::string caFileData; + Path tmpDirInSandbox; +}; -void builtinUnpackChannel( - const BasicDerivation & drv, - const std::map & outputs); +using BuiltinBuilder = std::function; + +struct RegisterBuiltinBuilder +{ + typedef std::map BuiltinBuilders; + + static BuiltinBuilders & builtinBuilders() { + static BuiltinBuilders builders; + return builders; + } + + RegisterBuiltinBuilder(const std::string & name, BuiltinBuilder && fun) + { + builtinBuilders().insert_or_assign(name, std::move(fun)); + } +}; } diff --git a/src/libstore/include/nix/store/builtins/buildenv.hh b/src/libstore/include/nix/store/builtins/buildenv.hh index a0a262037..163666c0b 100644 --- a/src/libstore/include/nix/store/builtins/buildenv.hh +++ b/src/libstore/include/nix/store/builtins/buildenv.hh @@ -45,8 +45,4 @@ typedef std::vector Packages; void buildProfile(const Path & out, Packages && pkgs); -void builtinBuildenv( - const BasicDerivation & drv, - const std::map & outputs); - } diff --git a/src/libstore/unix/build/derivation-builder.cc b/src/libstore/unix/build/derivation-builder.cc index 59c0be91c..d8a539fe2 100644 --- a/src/libstore/unix/build/derivation-builder.cc +++ b/src/libstore/unix/build/derivation-builder.cc @@ -1861,15 +1861,18 @@ void DerivationBuilderImpl::runChild() /* Make the contents of netrc and the CA certificate bundle available to builtin:fetchurl (which may run under a different uid and/or in a sandbox). */ - std::string netrcData; - std::string caFileData; + BuiltinBuilderContext ctx{ + .drv = drv, + .tmpDirInSandbox = tmpDirInSandbox, + }; + if (drv.isBuiltin() && drv.builder == "builtin:fetchurl") { try { - netrcData = readFile(settings.netrcFile); + ctx.netrcData = readFile(settings.netrcFile); } catch (SystemError &) { } try { - caFileData = readFile(settings.caFile); + ctx.caFileData = readFile(settings.caFile); } catch (SystemError &) { } } @@ -2290,19 +2293,16 @@ void DerivationBuilderImpl::runChild() try { logger = makeJSONLogger(getStandardError()); - std::map outputs; for (auto & e : drv.outputs) - outputs.insert_or_assign(e.first, + ctx.outputs.insert_or_assign(e.first, store.printStorePath(scratchOutputs.at(e.first))); - if (drv.builder == "builtin:fetchurl") - builtinFetchurl(drv, outputs, netrcData, caFileData); - else if (drv.builder == "builtin:buildenv") - builtinBuildenv(drv, outputs); - else if (drv.builder == "builtin:unpack-channel") - builtinUnpackChannel(drv, outputs); + std::string builtinName = drv.builder.substr(8); + assert(RegisterBuiltinBuilder::builtinBuilders); + if (auto builtin = get(RegisterBuiltinBuilder::builtinBuilders(), builtinName)) + (*builtin)(ctx); else - throw Error("unsupported builtin builder '%1%'", drv.builder.substr(8)); + throw Error("unsupported builtin builder '%1%'", builtinName); _exit(0); } catch (std::exception & e) { writeFull(STDERR_FILENO, e.what() + std::string("\n"));