diff --git a/src/hydra-eval-jobs/hydra-eval-jobs.cc b/src/hydra-eval-jobs/hydra-eval-jobs.cc index 3524fb69..1faccb9d 100644 --- a/src/hydra-eval-jobs/hydra-eval-jobs.cc +++ b/src/hydra-eval-jobs/hydra-eval-jobs.cc @@ -10,8 +10,8 @@ #include "util.hh" #include "json.hh" #include "get-drvs.hh" -#include "common-opts.hh" #include "globals.hh" +#include "common-eval-args.hh" using namespace nix; @@ -19,54 +19,8 @@ using namespace nix; static Path gcRootsDir; -typedef std::list > ValueList; -typedef std::map AutoArgs; - - static void findJobs(EvalState & state, JSONObject & top, - const AutoArgs & argsLeft, Value & v, const string & attrPath); - - -static void tryJobAlts(EvalState & state, JSONObject & top, - const AutoArgs & argsLeft, const string & attrPath, Value & fun, - Formals::Formals_::iterator cur, - Formals::Formals_::iterator last, - Bindings & actualArgs) // FIXME: should be const -{ - if (cur == last) { - Value v, * arg = state.allocValue(); - state.mkAttrs(*arg, 0); - arg->attrs = &actualArgs; - mkApp(v, fun, *arg); - findJobs(state, top, argsLeft, v, attrPath); - return; - } - - AutoArgs::const_iterator a = argsLeft.find(cur->name); - - Formals::Formals_::iterator next = cur; ++next; - - if (a == argsLeft.end()) { - if (!cur->def) - throw TypeError(format("job `%1%' requires an argument named `%2%'") - % attrPath % cur->name); - tryJobAlts(state, top, argsLeft, attrPath, fun, next, last, actualArgs); - return; - } - - int n = 0; - for (auto & i : a->second) { - Bindings & actualArgs2(*state.allocBindings(actualArgs.size() + 1)); // !!! inefficient - for (auto & j : actualArgs) - actualArgs2.push_back(j); - AutoArgs argsLeft2(argsLeft); - actualArgs2.push_back(Attr(cur->name, i)); - actualArgs2.sort(); // !!! inefficient - argsLeft2.erase(cur->name); - tryJobAlts(state, top, argsLeft2, attrPath, fun, next, last, actualArgs2); - ++n; - } -} + Bindings & autoArgs, Value & v, const string & attrPath); static string queryMetaStrings(EvalState & state, DrvInfo & drv, const string & name) @@ -96,13 +50,14 @@ static string queryMetaStrings(EvalState & state, DrvInfo & drv, const string & static void findJobsWrapped(EvalState & state, JSONObject & top, - const AutoArgs & argsLeft, Value & v, const string & attrPath) + Bindings & autoArgs, Value & vIn, const string & attrPath) { debug(format("at path `%1%'") % attrPath); checkInterrupt(); - state.forceValue(v); + Value v; + state.autoCallFunction(autoArgs, vIn, v); if (v.type == tAttrs) { @@ -166,20 +121,12 @@ static void findJobsWrapped(EvalState & state, JSONObject & top, else { if (!state.isDerivation(v)) { for (auto & i : *v.attrs) - findJobs(state, top, argsLeft, *i.value, + findJobs(state, top, autoArgs, *i.value, (attrPath.empty() ? "" : attrPath + ".") + (string) i.name); } } } - else if (v.type == tLambda && v.lambda.fun->matchAttrs) { - Bindings & tmp(*state.allocBindings(0)); - tryJobAlts(state, top, argsLeft, attrPath, v, - v.lambda.fun->formals->formals.begin(), - v.lambda.fun->formals->formals.end(), - tmp); - } - else if (v.type == tNull) { // allow null values, meaning 'do nothing' } @@ -190,10 +137,10 @@ static void findJobsWrapped(EvalState & state, JSONObject & top, static void findJobs(EvalState & state, JSONObject & top, - const AutoArgs & argsLeft, Value & v, const string & attrPath) + Bindings & autoArgs, Value & v, const string & attrPath) { try { - findJobsWrapped(state, top, argsLeft, v, attrPath); + findJobsWrapped(state, top, autoArgs, v, attrPath); } catch (EvalError & e) { { auto res = top.object(attrPath); @@ -213,24 +160,15 @@ int main(int argc, char * * argv) initNix(); initGC(); - Strings searchPath; Path releaseExpr; - std::map autoArgs_; - parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { - if (*arg == "--arg" || *arg == "--argstr") { - /* This is like --arg in nix-instantiate, except that it - supports multiple versions for the same argument. - That is, autoArgs is a mapping from variable names to - *lists* of values. */ - auto what = *arg; - string name = getArg(what, arg, end); - string value = getArg(what, arg, end); - autoArgs_[name].push_back((what == "--arg" ? 'E' : 'S') + value); - } - else if (parseSearchPathArg(arg, end, searchPath)) - ; - else if (*arg == "--gc-roots-dir") + struct MyArgs : LegacyArgs, MixEvalArgs + { + using LegacyArgs::LegacyArgs; + }; + + MyArgs myArgs(baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) { + if (*arg == "--gc-roots-dir") gcRootsDir = getArg(*arg, arg, end); else if (*arg == "--dry-run") settings.readOnlyMode = true; @@ -241,43 +179,22 @@ int main(int argc, char * * argv) return true; }); + myArgs.parseCmdline(argvToStrings(argc, argv)); + /* FIXME: The build hook in conjunction with import-from-derivation is causing "unexpected EOF" during eval */ - settings.useBuildHook = false; + settings.builders = ""; /* Prevent access to paths outside of the Nix search path and to the environment. */ - settings.set("restrict-eval", "true"); + settings.restrictEval = true; if (releaseExpr == "") throw UsageError("no expression specified"); if (gcRootsDir == "") printMsg(lvlError, "warning: `--gc-roots-dir' not specified"); - EvalState state(searchPath, openStore()); + EvalState state(myArgs.searchPath, openStore()); - AutoArgs autoArgs; - Value * inputsSet = state.allocValue(); - state.mkAttrs(*inputsSet, autoArgs_.size()); - for (auto & i : autoArgs_) { - Symbol inputName = state.symbols.create(i.first); - bool first = true; - for (auto & j : i.second) { - Value * v = state.allocValue(); - if (j[0] == 'E') - state.eval(state.parseExprFromString(string(j, 1), absPath(".")), *v); - else - mkString(*v, string(j, 1)); - autoArgs[inputName].push_back(v); - if (first) { - inputsSet->attrs->push_back(Attr(inputName, v)); - first = false; - } - } - } - Symbol sInputs = state.symbols.create("inputs"); - if (autoArgs.find(sInputs) == autoArgs.end()) { - inputsSet->attrs->sort(); - autoArgs[sInputs].push_back(inputsSet); - } + Bindings & autoArgs = *myArgs.getAutoArgs(state); Value v; state.evalFile(releaseExpr, v); diff --git a/src/script/hydra-eval-jobset b/src/script/hydra-eval-jobset index 0641c9d5..16d7ae55 100755 --- a/src/script/hydra-eval-jobset +++ b/src/script/hydra-eval-jobset @@ -303,29 +303,33 @@ sub inputsToArgs { push @res, "-I", "$input=$inputInfo->{$input}->[0]->{storePath}" if scalar @{$inputInfo->{$input}} == 1 && defined $inputInfo->{$input}->[0]->{storePath}; - foreach my $alt (@{$inputInfo->{$input}}) { - if ($alt->{type} eq "string") { - push @res, "--argstr", $input, $alt->{value}; - } - elsif ($alt->{type} eq "boolean") { - push @res, "--arg", $input, booleanToString($exprType, $alt->{value}); - } - elsif ($alt->{type} eq "nix") { - die "input type ‘nix’ only supported for Nix-based jobsets\n" unless $exprType eq "nix"; - push @res, "--arg", $input, $alt->{value}; - } - elsif ($alt->{type} eq "eval") { - die "input type ‘eval’ only supported for Nix-based jobsets\n" unless $exprType eq "nix"; - my $s = "{ "; - # FIXME: escape $_. But dots should not be escaped. - $s .= "$_ = builtins.storePath ${\$alt->{jobs}->{$_}}; " - foreach keys %{$alt->{jobs}}; - $s .= "}"; - push @res, "--arg", $input, $s; - } - else { - push @res, "--arg", $input, buildInputToString($exprType, $alt); - } + + die "multiple jobset input alternatives are no longer supported" + if scalar @{$inputInfo->{$input}} != 1; + + my $alt = $inputInfo->{$input}->[0]; + + if ($alt->{type} eq "string") { + push @res, "--argstr", $input, $alt->{value}; + } + elsif ($alt->{type} eq "boolean") { + push @res, "--arg", $input, booleanToString($exprType, $alt->{value}); + } + elsif ($alt->{type} eq "nix") { + die "input type ‘nix’ only supported for Nix-based jobsets\n" unless $exprType eq "nix"; + push @res, "--arg", $input, $alt->{value}; + } + elsif ($alt->{type} eq "eval") { + die "input type ‘eval’ only supported for Nix-based jobsets\n" unless $exprType eq "nix"; + my $s = "{ "; + # FIXME: escape $_. But dots should not be escaped. + $s .= "$_ = builtins.storePath ${\$alt->{jobs}->{$_}}; " + foreach keys %{$alt->{jobs}}; + $s .= "}"; + push @res, "--arg", $input, $s; + } + else { + push @res, "--arg", $input, buildInputToString($exprType, $alt); } }