From e5662ba6525c27248d57d8265e9c6c3a46f95c7e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 5 Aug 2020 21:26:17 +0200 Subject: Add a flag to start the REPL on evaluation errors This allows interactively inspecting the state of the evaluator at the point of failure. Example: $ nix eval path:///home/eelco/Dev/nix/flake2#modules.hello-closure._final --start-repl-on-eval-errors error: --- TypeError -------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix at: (20:53) in file: /nix/store/4264z41dxfdiqr95svmpnxxxwhfplhy0-source/flake.nix 19| 20| _final = builtins.foldl' (xs: mod: xs // (mod._module.config { config = _final; })) _defaults _allModules; | ^ 21| }; attempt to call something which is not a function but a set Starting REPL to allow you to inspect the current state of the evaluator. The following extra variables are in scope: arg, fun Welcome to Nix version 2.4. Type :? for help. nix-repl> fun error: --- EvalError -------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix at: (150:28) in file: /nix/store/4264z41dxfdiqr95svmpnxxxwhfplhy0-source/flake.nix 149| 150| tarballClosure = (module { | ^ 151| extends = [ self.modules.derivation ]; attribute 'derivation' missing nix-repl> :t fun a set nix-repl> builtins.attrNames fun [ "tarballClosure" ] nix-repl> --- src/nix/command.cc | 24 +++++++++++++++++ src/nix/command.hh | 8 ++++++ src/nix/installables.cc | 7 ----- src/nix/repl.cc | 71 +++++++++++++++++++++++++++++++++---------------- 4 files changed, 80 insertions(+), 30 deletions(-) (limited to 'src/nix') diff --git a/src/nix/command.cc b/src/nix/command.cc index af36dda89..8b69948b6 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -31,6 +31,30 @@ void StoreCommand::run() run(getStore()); } +EvalCommand::EvalCommand() +{ + addFlag({ + .longName = "start-repl-on-eval-errors", + .description = "start an interactive environment if evaluation fails", + .handler = {&startReplOnEvalErrors, true}, + }); +} + +extern std::function & env)> debuggerHook; + +ref EvalCommand::getEvalState() +{ + if (!evalState) { + evalState = std::make_shared(searchPath, getStore()); + if (startReplOnEvalErrors) + debuggerHook = [evalState{ref(evalState)}](const Error & error, const std::map & env) { + printError("%s\n\n" ANSI_BOLD "Starting REPL to allow you to inspect the current state of the evaluator.\n" ANSI_NORMAL, error.what()); + runRepl(evalState, env); + }; + } + return ref(evalState); +} + StorePathsCommand::StorePathsCommand(bool recursive) : recursive(recursive) { diff --git a/src/nix/command.hh b/src/nix/command.hh index bc46a2028..fe1cd2799 100644 --- a/src/nix/command.hh +++ b/src/nix/command.hh @@ -36,8 +36,12 @@ private: struct EvalCommand : virtual StoreCommand, MixEvalArgs { + bool startReplOnEvalErrors = false; + ref getEvalState(); + EvalCommand(); + std::shared_ptr evalState; }; @@ -251,4 +255,8 @@ void printClosureDiff( const StorePath & afterPath, std::string_view indent); +void runRepl( + ref evalState, + const std::map & extraEnv); + } diff --git a/src/nix/installables.cc b/src/nix/installables.cc index 59b52ce95..926cac2f8 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -234,13 +234,6 @@ void completeFlakeRefWithFragment( completeFlakeRef(evalState->store, prefix); } -ref EvalCommand::getEvalState() -{ - if (!evalState) - evalState = std::make_shared(searchPath, getStore()); - return ref(evalState); -} - void completeFlakeRef(ref store, std::string_view prefix) { if (prefix == "") diff --git a/src/nix/repl.cc b/src/nix/repl.cc index fb9050d0d..8409c7574 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -41,7 +41,7 @@ namespace nix { struct NixRepl : gc { string curDir; - std::unique_ptr state; + ref state; Bindings * autoArgs; Strings loadedFiles; @@ -54,7 +54,7 @@ struct NixRepl : gc const Path historyFile; - NixRepl(const Strings & searchPath, nix::ref store); + NixRepl(ref state); ~NixRepl(); void mainLoop(const std::vector & files); StringSet completePrefix(string prefix); @@ -65,13 +65,13 @@ struct NixRepl : gc void initEnv(); void reloadFiles(); void addAttrsToScope(Value & attrs); - void addVarToScope(const Symbol & name, Value & v); + void addVarToScope(const Symbol & name, Value * v); Expr * parseString(string s); void evalString(string s, Value & v); typedef set ValuesSeen; - std::ostream & printValue(std::ostream & str, Value & v, unsigned int maxDepth); - std::ostream & printValue(std::ostream & str, Value & v, unsigned int maxDepth, ValuesSeen & seen); + std::ostream & printValue(std::ostream & str, Value & v, unsigned int maxDepth); + std::ostream & printValue(std::ostream & str, Value & v, unsigned int maxDepth, ValuesSeen & seen); }; @@ -84,8 +84,8 @@ string removeWhitespace(string s) } -NixRepl::NixRepl(const Strings & searchPath, nix::ref store) - : state(std::make_unique(searchPath, store)) +NixRepl::NixRepl(ref state) + : state(state) , staticEnv(false, &state->staticBaseEnv) , historyFile(getDataDir() + "/nix/repl-history") { @@ -176,11 +176,13 @@ void NixRepl::mainLoop(const std::vector & files) string error = ANSI_RED "error:" ANSI_NORMAL " "; std::cout << "Welcome to Nix version " << nixVersion << ". Type :? for help." << std::endl << std::endl; - for (auto & i : files) - loadedFiles.push_back(i); + if (!files.empty()) { + for (auto & i : files) + loadedFiles.push_back(i); - reloadFiles(); - if (!loadedFiles.empty()) std::cout << std::endl; + reloadFiles(); + if (!loadedFiles.empty()) std::cout << std::endl; + } // Allow nix-repl specific settings in .inputrc rl_readline_name = "nix-repl"; @@ -516,10 +518,10 @@ bool NixRepl::processLine(string line) isVarName(name = removeWhitespace(string(line, 0, p)))) { Expr * e = parseString(string(line, p + 1)); - Value & v(*state->allocValue()); - v.type = tThunk; - v.thunk.env = env; - v.thunk.expr = e; + auto v = state->allocValue(); + v->type = tThunk; + v->thunk.env = env; + v->thunk.expr = e; addVarToScope(state->symbols.create(name), v); } else { Value v; @@ -577,17 +579,17 @@ void NixRepl::addAttrsToScope(Value & attrs) { state->forceAttrs(attrs); for (auto & i : *attrs.attrs) - addVarToScope(i.name, *i.value); + addVarToScope(i.name, i.value); std::cout << format("Added %1% variables.") % attrs.attrs->size() << std::endl; } -void NixRepl::addVarToScope(const Symbol & name, Value & v) +void NixRepl::addVarToScope(const Symbol & name, Value * v) { if (displ >= envSize) throw Error("environment full; cannot add more variables"); staticEnv.vars[name] = displ; - env->values[displ++] = &v; + env->values[displ++] = v; varNames.insert((string) name); } @@ -754,6 +756,26 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m return str; } +void runRepl( + ref evalState, + const std::map & extraEnv) +{ + auto repl = std::make_unique(evalState); + + repl->initEnv(); + + std::set names; + + for (auto & [name, value] : extraEnv) { + names.insert(ANSI_BOLD + name + ANSI_NORMAL); + repl->addVarToScope(repl->state->symbols.create(name), value); + } + + printError("The following extra variables are in scope: %s\n", concatStringsSep(", ", names)); + + repl->mainLoop({}); +} + struct CmdRepl : StoreCommand, MixEvalArgs { std::vector files; @@ -775,17 +797,20 @@ struct CmdRepl : StoreCommand, MixEvalArgs Examples examples() override { return { - Example{ - "Display all special commands within the REPL:", - "nix repl\n nix-repl> :?" - } + { + "Display all special commands within the REPL:", + "nix repl\n nix-repl> :?" + } }; } void run(ref store) override { evalSettings.pureEval = false; - auto repl = std::make_unique(searchPath, openStore()); + + auto evalState = make_ref(searchPath, store); + + auto repl = std::make_unique(evalState); repl->autoArgs = getAutoArgs(*repl->state); repl->mainLoop(files); } -- cgit v1.2.3 From e486996cef871337ef14991e709d7f2cc6611e4e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 1 Feb 2021 15:50:58 +0100 Subject: Rename to --debugger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Domen Kožar --- src/nix/command.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/command.cc b/src/nix/command.cc index 8b69948b6..c2bd5b13c 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -34,7 +34,7 @@ void StoreCommand::run() EvalCommand::EvalCommand() { addFlag({ - .longName = "start-repl-on-eval-errors", + .longName = "debugger", .description = "start an interactive environment if evaluation fails", .handler = {&startReplOnEvalErrors, true}, }); -- cgit v1.2.3 From 8499f32fb2e7fdf09e97d0beb1fe78bef5900d93 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 12 Feb 2021 21:51:36 +0000 Subject: New "indexed" installable syntax: `!` Being conservative and only doing a single output name for now. --- src/nix/nix.md | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index d10de7c01..22cc9d476 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -94,6 +94,16 @@ the Nix store. Here are the recognised types of installables: If you want to operate on the store derivation itself, pass the `--derivation` flag. +* **Indexed store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv!out` + + Store derivations can be indexed with a specific output name. This + allows finer control versus just specifying a derivation (without + `--derivation`) and getting all the outputs. + + This is especially useful for (currently unstable) floating content + addressed derivations, which do not have precomputed output paths that + can be used instead. + * **Nix attributes**: `--file /path/to/nixpkgs hello` When the `-f` / `--file` *path* option is given, installables are -- cgit v1.2.3 From 57c2dd5d8581f37392df369493b00794b619304e Mon Sep 17 00:00:00 2001 From: Ben Burdette Date: Wed, 28 Apr 2021 09:55:08 -0600 Subject: fixes --- src/nix/repl.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index bb067e935..b1f250e73 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -537,8 +537,8 @@ bool NixRepl::processLine(string line) isVarName(name = removeWhitespace(string(line, 0, p)))) { Expr * e = parseString(string(line, p + 1)); - Value & v(*state->allocValue()); - v.mkThunk(env, e); + Value *v = new Value(*state->allocValue()); + v->mkThunk(env, e); addVarToScope(state->symbols.create(name), v); } else { Value v; -- cgit v1.2.3 From f32c687f03e9764e55831d894b719fdf0104cf25 Mon Sep 17 00:00:00 2001 From: Ben Burdette Date: Wed, 28 Apr 2021 15:50:11 -0600 Subject: move repl.cc to libcmd for linkage --- src/nix/repl.cc | 832 -------------------------------------------------------- 1 file changed, 832 deletions(-) delete mode 100644 src/nix/repl.cc (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc deleted file mode 100644 index b1f250e73..000000000 --- a/src/nix/repl.cc +++ /dev/null @@ -1,832 +0,0 @@ -#include -#include -#include -#include - -#include - -#ifdef READLINE -#include -#include -#else -// editline < 1.15.2 don't wrap their API for C++ usage -// (added in https://github.com/troglobit/editline/commit/91398ceb3427b730995357e9d120539fb9bb7461). -// This results in linker errors due to to name-mangling of editline C symbols. -// For compatibility with these versions, we wrap the API here -// (wrapping multiple times on newer versions is no problem). -extern "C" { -#include -} -#endif - -#include "ansicolor.hh" -#include "shared.hh" -#include "eval.hh" -#include "eval-inline.hh" -#include "attr-path.hh" -#include "store-api.hh" -#include "common-eval-args.hh" -#include "get-drvs.hh" -#include "derivations.hh" -#include "affinity.hh" -#include "globals.hh" -#include "command.hh" -#include "finally.hh" -#include "markdown.hh" - -#if HAVE_BOEHMGC -#define GC_INCLUDE_NEW -#include -#endif - -namespace nix { - -struct NixRepl - #if HAVE_BOEHMGC - : gc - #endif -{ - string curDir; - ref state; - Bindings * autoArgs; - - Strings loadedFiles; - - const static int envSize = 32768; - StaticEnv staticEnv; - Env * env; - int displ; - StringSet varNames; - - const Path historyFile; - - NixRepl(ref state); - ~NixRepl(); - void mainLoop(const std::vector & files); - StringSet completePrefix(string prefix); - bool getLine(string & input, const std::string &prompt); - StorePath getDerivationPath(Value & v); - bool processLine(string line); - void loadFile(const Path & path); - void initEnv(); - void reloadFiles(); - void addAttrsToScope(Value & attrs); - void addVarToScope(const Symbol & name, Value * v); - Expr * parseString(string s); - void evalString(string s, Value & v); - - typedef set ValuesSeen; - std::ostream & printValue(std::ostream & str, Value & v, unsigned int maxDepth); - std::ostream & printValue(std::ostream & str, Value & v, unsigned int maxDepth, ValuesSeen & seen); -}; - - -string removeWhitespace(string s) -{ - s = chomp(s); - size_t n = s.find_first_not_of(" \n\r\t"); - if (n != string::npos) s = string(s, n); - return s; -} - - -NixRepl::NixRepl(ref state) - : state(state) - , staticEnv(false, &state->staticBaseEnv) - , historyFile(getDataDir() + "/nix/repl-history") -{ - curDir = absPath("."); -} - - -NixRepl::~NixRepl() -{ - write_history(historyFile.c_str()); -} - -static NixRepl * curRepl; // ugly - -static char * completionCallback(char * s, int *match) { - auto possible = curRepl->completePrefix(s); - if (possible.size() == 1) { - *match = 1; - auto *res = strdup(possible.begin()->c_str() + strlen(s)); - if (!res) throw Error("allocation failure"); - return res; - } else if (possible.size() > 1) { - auto checkAllHaveSameAt = [&](size_t pos) { - auto &first = *possible.begin(); - for (auto &p : possible) { - if (p.size() <= pos || p[pos] != first[pos]) - return false; - } - return true; - }; - size_t start = strlen(s); - size_t len = 0; - while (checkAllHaveSameAt(start + len)) ++len; - if (len > 0) { - *match = 1; - auto *res = strdup(std::string(*possible.begin(), start, len).c_str()); - if (!res) throw Error("allocation failure"); - return res; - } - } - - *match = 0; - return nullptr; -} - -static int listPossibleCallback(char *s, char ***avp) { - auto possible = curRepl->completePrefix(s); - - if (possible.size() > (INT_MAX / sizeof(char*))) - throw Error("too many completions"); - - int ac = 0; - char **vp = nullptr; - - auto check = [&](auto *p) { - if (!p) { - if (vp) { - while (--ac >= 0) - free(vp[ac]); - free(vp); - } - throw Error("allocation failure"); - } - return p; - }; - - vp = check((char **)malloc(possible.size() * sizeof(char*))); - - for (auto & p : possible) - vp[ac++] = check(strdup(p.c_str())); - - *avp = vp; - - return ac; -} - -namespace { - // Used to communicate to NixRepl::getLine whether a signal occurred in ::readline. - volatile sig_atomic_t g_signal_received = 0; - - void sigintHandler(int signo) { - g_signal_received = signo; - } -} - -void NixRepl::mainLoop(const std::vector & files) -{ - string error = ANSI_RED "error:" ANSI_NORMAL " "; - std::cout << "Welcome to Nix version " << nixVersion << ". Type :? for help." << std::endl << std::endl; - - if (!files.empty()) { - for (auto & i : files) - loadedFiles.push_back(i); - - reloadFiles(); - if (!loadedFiles.empty()) std::cout << std::endl; - } - - // Allow nix-repl specific settings in .inputrc - rl_readline_name = "nix-repl"; - createDirs(dirOf(historyFile)); -#ifndef READLINE - el_hist_size = 1000; -#endif - read_history(historyFile.c_str()); - curRepl = this; -#ifndef READLINE - rl_set_complete_func(completionCallback); - rl_set_list_possib_func(listPossibleCallback); -#endif - - std::string input; - - while (true) { - // When continuing input from previous lines, don't print a prompt, just align to the same - // number of chars as the prompt. - if (!getLine(input, input.empty() ? "nix-repl> " : " ")) - break; - - try { - if (!removeWhitespace(input).empty() && !processLine(input)) return; - } catch (ParseError & e) { - if (e.msg().find("unexpected end of file") != std::string::npos) { - // For parse errors on incomplete input, we continue waiting for the next line of - // input without clearing the input so far. - continue; - } else { - printMsg(lvlError, e.msg()); - } - } catch (Error & e) { - printMsg(lvlError, e.msg()); - } catch (Interrupted & e) { - printMsg(lvlError, e.msg()); - } - - // We handled the current input fully, so we should clear it - // and read brand new input. - input.clear(); - std::cout << std::endl; - } -} - - -bool NixRepl::getLine(string & input, const std::string &prompt) -{ - struct sigaction act, old; - sigset_t savedSignalMask, set; - - auto setupSignals = [&]() { - act.sa_handler = sigintHandler; - sigfillset(&act.sa_mask); - act.sa_flags = 0; - if (sigaction(SIGINT, &act, &old)) - throw SysError("installing handler for SIGINT"); - - sigemptyset(&set); - sigaddset(&set, SIGINT); - if (sigprocmask(SIG_UNBLOCK, &set, &savedSignalMask)) - throw SysError("unblocking SIGINT"); - }; - auto restoreSignals = [&]() { - if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr)) - throw SysError("restoring signals"); - - if (sigaction(SIGINT, &old, 0)) - throw SysError("restoring handler for SIGINT"); - }; - - setupSignals(); - char * s = readline(prompt.c_str()); - Finally doFree([&]() { free(s); }); - restoreSignals(); - - if (g_signal_received) { - g_signal_received = 0; - input.clear(); - return true; - } - - if (!s) - return false; - input += s; - input += '\n'; - return true; -} - - -StringSet NixRepl::completePrefix(string prefix) -{ - StringSet completions; - - size_t start = prefix.find_last_of(" \n\r\t(){}[]"); - std::string prev, cur; - if (start == std::string::npos) { - prev = ""; - cur = prefix; - } else { - prev = std::string(prefix, 0, start + 1); - cur = std::string(prefix, start + 1); - } - - size_t slash, dot; - - if ((slash = cur.rfind('/')) != string::npos) { - try { - auto dir = std::string(cur, 0, slash); - auto prefix2 = std::string(cur, slash + 1); - for (auto & entry : readDirectory(dir == "" ? "/" : dir)) { - if (entry.name[0] != '.' && hasPrefix(entry.name, prefix2)) - completions.insert(prev + dir + "/" + entry.name); - } - } catch (Error &) { - } - } else if ((dot = cur.rfind('.')) == string::npos) { - /* This is a variable name; look it up in the current scope. */ - StringSet::iterator i = varNames.lower_bound(cur); - while (i != varNames.end()) { - if (string(*i, 0, cur.size()) != cur) break; - completions.insert(prev + *i); - i++; - } - } else { - try { - /* This is an expression that should evaluate to an - attribute set. Evaluate it to get the names of the - attributes. */ - string expr(cur, 0, dot); - string cur2 = string(cur, dot + 1); - - Expr * e = parseString(expr); - Value v; - e->eval(*state, *env, v); - state->forceAttrs(v); - - for (auto & i : *v.attrs) { - string name = i.name; - if (string(name, 0, cur2.size()) != cur2) continue; - completions.insert(prev + expr + "." + name); - } - - } catch (ParseError & e) { - // Quietly ignore parse errors. - } catch (EvalError & e) { - // Quietly ignore evaluation errors. - } catch (UndefinedVarError & e) { - // Quietly ignore undefined variable errors. - } - } - - return completions; -} - - -bool isVarName(const string & s) -{ - if (s.size() == 0) return false; - char c = s[0]; - if ((c >= '0' && c <= '9') || c == '-' || c == '\'') return false; - for (auto & i : s) - if (!((i >= 'a' && i <= 'z') || - (i >= 'A' && i <= 'Z') || - (i >= '0' && i <= '9') || - i == '_' || i == '-' || i == '\'')) - return false; - return true; -} - - -StorePath NixRepl::getDerivationPath(Value & v) { - auto drvInfo = getDerivation(*state, v, false); - if (!drvInfo) - throw Error("expression does not evaluate to a derivation, so I can't build it"); - Path drvPathRaw = drvInfo->queryDrvPath(); - if (drvPathRaw == "") - throw Error("expression did not evaluate to a valid derivation (no drv path)"); - StorePath drvPath = state->store->parseStorePath(drvPathRaw); - if (!state->store->isValidPath(drvPath)) - throw Error("expression did not evaluate to a valid derivation (invalid drv path)"); - return drvPath; -} - - -bool NixRepl::processLine(string line) -{ - if (line == "") return true; - - string command, arg; - - if (line[0] == ':') { - size_t p = line.find_first_of(" \n\r\t"); - command = string(line, 0, p); - if (p != string::npos) arg = removeWhitespace(string(line, p)); - } else { - arg = line; - } - - if (command == ":?" || command == ":help") { - // FIXME: convert to Markdown, include in the 'nix repl' manpage. - std::cout - << "The following commands are available:\n" - << "\n" - << " Evaluate and print expression\n" - << " = Bind expression to variable\n" - << " :a Add attributes from resulting set to scope\n" - << " :b Build derivation\n" - << " :e Open the derivation in $EDITOR\n" - << " :i Build derivation, then install result into current profile\n" - << " :l Load Nix expression and add it to scope\n" - << " :p Evaluate and print expression recursively\n" - << " :q Exit nix-repl\n" - << " :r Reload all files\n" - << " :s Build dependencies of derivation, then start nix-shell\n" - << " :t Describe result of evaluation\n" - << " :u Build derivation, then start nix-shell\n" - << " :doc Show documentation of a builtin function\n"; - } - - else if (command == ":a" || command == ":add") { - Value v; - evalString(arg, v); - addAttrsToScope(v); - } - - else if (command == ":l" || command == ":load") { - state->resetFileCache(); - loadFile(arg); - } - - else if (command == ":r" || command == ":reload") { - state->resetFileCache(); - reloadFiles(); - } - - else if (command == ":e" || command == ":edit") { - Value v; - evalString(arg, v); - - Pos pos; - - if (v.type() == nPath || v.type() == nString) { - PathSet context; - auto filename = state->coerceToString(noPos, v, context); - pos.file = state->symbols.create(filename); - } else if (v.isLambda()) { - pos = v.lambda.fun->pos; - } else { - // assume it's a derivation - pos = findDerivationFilename(*state, v, arg); - } - - // Open in EDITOR - auto args = editorFor(pos); - auto editor = args.front(); - args.pop_front(); - runProgram(editor, true, args); - - // Reload right after exiting the editor - state->resetFileCache(); - reloadFiles(); - } - - else if (command == ":t") { - Value v; - evalString(arg, v); - std::cout << showType(v) << std::endl; - - } else if (command == ":u") { - Value v, f, result; - evalString(arg, v); - evalString("drv: (import {}).runCommand \"shell\" { buildInputs = [ drv ]; } \"\"", f); - state->callFunction(f, v, result, Pos()); - - StorePath drvPath = getDerivationPath(result); - runProgram(settings.nixBinDir + "/nix-shell", true, {state->store->printStorePath(drvPath)}); - } - - else if (command == ":b" || command == ":i" || command == ":s") { - Value v; - evalString(arg, v); - StorePath drvPath = getDerivationPath(v); - Path drvPathRaw = state->store->printStorePath(drvPath); - - if (command == ":b") { - /* We could do the build in this process using buildPaths(), - but doing it in a child makes it easier to recover from - problems / SIGINT. */ - try { - runProgram(settings.nixBinDir + "/nix", true, {"build", "--no-link", drvPathRaw}); - auto drv = state->store->readDerivation(drvPath); - std::cout << std::endl << "this derivation produced the following outputs:" << std::endl; - for (auto & i : drv.outputsAndOptPaths(*state->store)) - std::cout << fmt(" %s -> %s\n", i.first, state->store->printStorePath(*i.second.second)); - } catch (ExecError &) { - } - } else if (command == ":i") { - runProgram(settings.nixBinDir + "/nix-env", true, {"-i", drvPathRaw}); - } else { - runProgram(settings.nixBinDir + "/nix-shell", true, {drvPathRaw}); - } - } - - else if (command == ":p" || command == ":print") { - Value v; - evalString(arg, v); - printValue(std::cout, v, 1000000000) << std::endl; - } - - else if (command == ":q" || command == ":quit") - return false; - - else if (command == ":doc") { - Value v; - evalString(arg, v); - if (auto doc = state->getDoc(v)) { - std::string markdown; - - if (!doc->args.empty() && doc->name) { - auto args = doc->args; - for (auto & arg : args) - arg = "*" + arg + "*"; - - markdown += - "**Synopsis:** `builtins." + (std::string) (*doc->name) + "` " - + concatStringsSep(" ", args) + "\n\n"; - } - - markdown += trim(stripIndentation(doc->doc)); - - std::cout << renderMarkdownToTerminal(markdown); - } else - throw Error("value does not have documentation"); - } - - else if (command != "") - throw Error("unknown command '%1%'", command); - - else { - size_t p = line.find('='); - string name; - if (p != string::npos && - p < line.size() && - line[p + 1] != '=' && - isVarName(name = removeWhitespace(string(line, 0, p)))) - { - Expr * e = parseString(string(line, p + 1)); - Value *v = new Value(*state->allocValue()); - v->mkThunk(env, e); - addVarToScope(state->symbols.create(name), v); - } else { - Value v; - evalString(line, v); - printValue(std::cout, v, 1) << std::endl; - } - } - - return true; -} - - -void NixRepl::loadFile(const Path & path) -{ - loadedFiles.remove(path); - loadedFiles.push_back(path); - Value v, v2; - state->evalFile(lookupFileArg(*state, path), v); - state->autoCallFunction(*autoArgs, v, v2); - addAttrsToScope(v2); -} - - -void NixRepl::initEnv() -{ - env = &state->allocEnv(envSize); - env->up = &state->baseEnv; - displ = 0; - staticEnv.vars.clear(); - - varNames.clear(); - for (auto & i : state->staticBaseEnv.vars) - varNames.insert(i.first); -} - - -void NixRepl::reloadFiles() -{ - initEnv(); - - Strings old = loadedFiles; - loadedFiles.clear(); - - bool first = true; - for (auto & i : old) { - if (!first) std::cout << std::endl; - first = false; - std::cout << format("Loading '%1%'...") % i << std::endl; - loadFile(i); - } -} - - -void NixRepl::addAttrsToScope(Value & attrs) -{ - state->forceAttrs(attrs); - for (auto & i : *attrs.attrs) - addVarToScope(i.name, i.value); - std::cout << format("Added %1% variables.") % attrs.attrs->size() << std::endl; -} - - -void NixRepl::addVarToScope(const Symbol & name, Value * v) -{ - if (displ >= envSize) - throw Error("environment full; cannot add more variables"); - staticEnv.vars[name] = displ; - env->values[displ++] = v; - varNames.insert((string) name); -} - - -Expr * NixRepl::parseString(string s) -{ - Expr * e = state->parseExprFromString(s, curDir, staticEnv); - return e; -} - - -void NixRepl::evalString(string s, Value & v) -{ - Expr * e = parseString(s); - e->eval(*state, *env, v); - state->forceValue(v); -} - - -std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int maxDepth) -{ - ValuesSeen seen; - return printValue(str, v, maxDepth, seen); -} - - -std::ostream & printStringValue(std::ostream & str, const char * string) { - str << "\""; - for (const char * i = string; *i; i++) - if (*i == '\"' || *i == '\\') str << "\\" << *i; - else if (*i == '\n') str << "\\n"; - else if (*i == '\r') str << "\\r"; - else if (*i == '\t') str << "\\t"; - else str << *i; - str << "\""; - return str; -} - - -// FIXME: lot of cut&paste from Nix's eval.cc. -std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int maxDepth, ValuesSeen & seen) -{ - str.flush(); - checkInterrupt(); - - state->forceValue(v); - - switch (v.type()) { - - case nInt: - str << ANSI_CYAN << v.integer << ANSI_NORMAL; - break; - - case nBool: - str << ANSI_CYAN << (v.boolean ? "true" : "false") << ANSI_NORMAL; - break; - - case nString: - str << ANSI_YELLOW; - printStringValue(str, v.string.s); - str << ANSI_NORMAL; - break; - - case nPath: - str << ANSI_GREEN << v.path << ANSI_NORMAL; // !!! escaping? - break; - - case nNull: - str << ANSI_CYAN "null" ANSI_NORMAL; - break; - - case nAttrs: { - seen.insert(&v); - - bool isDrv = state->isDerivation(v); - - if (isDrv) { - str << "«derivation "; - Bindings::iterator i = v.attrs->find(state->sDrvPath); - PathSet context; - Path drvPath = i != v.attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "???"; - str << drvPath << "»"; - } - - else if (maxDepth > 0) { - str << "{ "; - - typedef std::map Sorted; - Sorted sorted; - for (auto & i : *v.attrs) - sorted[i.name] = i.value; - - for (auto & i : sorted) { - if (isVarName(i.first)) - str << i.first; - else - printStringValue(str, i.first.c_str()); - str << " = "; - if (seen.find(i.second) != seen.end()) - str << "«repeated»"; - else - try { - printValue(str, *i.second, maxDepth - 1, seen); - } catch (AssertionError & e) { - str << ANSI_RED "«error: " << e.msg() << "»" ANSI_NORMAL; - } - str << "; "; - } - - str << "}"; - } else - str << "{ ... }"; - - break; - } - - case nList: - seen.insert(&v); - - str << "[ "; - if (maxDepth > 0) - for (unsigned int n = 0; n < v.listSize(); ++n) { - if (seen.find(v.listElems()[n]) != seen.end()) - str << "«repeated»"; - else - try { - printValue(str, *v.listElems()[n], maxDepth - 1, seen); - } catch (AssertionError & e) { - str << ANSI_RED "«error: " << e.msg() << "»" ANSI_NORMAL; - } - str << " "; - } - else - str << "... "; - str << "]"; - break; - - case nFunction: - if (v.isLambda()) { - std::ostringstream s; - s << v.lambda.fun->pos; - str << ANSI_BLUE "«lambda @ " << filterANSIEscapes(s.str()) << "»" ANSI_NORMAL; - } else if (v.isPrimOp()) { - str << ANSI_MAGENTA "«primop»" ANSI_NORMAL; - } else if (v.isPrimOpApp()) { - str << ANSI_BLUE "«primop-app»" ANSI_NORMAL; - } else { - abort(); - } - break; - - case nFloat: - str << v.fpoint; - break; - - default: - str << ANSI_RED "«unknown»" ANSI_NORMAL; - break; - } - - return str; -} - -void runRepl( - ref evalState, - const std::map & extraEnv) -{ - auto repl = std::make_unique(evalState); - - repl->initEnv(); - - std::set names; - - for (auto & [name, value] : extraEnv) { - names.insert(ANSI_BOLD + name + ANSI_NORMAL); - repl->addVarToScope(repl->state->symbols.create(name), value); - } - - printError("The following extra variables are in scope: %s\n", concatStringsSep(", ", names)); - - repl->mainLoop({}); -} - -struct CmdRepl : StoreCommand, MixEvalArgs -{ - std::vector files; - - CmdRepl() - { - expectArgs({ - .label = "files", - .handler = {&files}, - .completer = completePath - }); - } - - std::string description() override - { - return "start an interactive environment for evaluating Nix expressions"; - } - - std::string doc() override - { - return - #include "repl.md" - ; - } - - void run(ref store) override - { - evalSettings.pureEval = false; - - auto evalState = make_ref(searchPath, store); - - auto repl = std::make_unique(evalState); - repl->autoArgs = getAutoArgs(*repl->state); - repl->mainLoop(files); - } -}; - -static auto rCmdRepl = registerCommand("repl"); - -} -- cgit v1.2.3 From 89264d20e63effa8d10f84a5f989d962f5df36f5 Mon Sep 17 00:00:00 2001 From: Ben Burdette Date: Fri, 6 Aug 2021 11:09:27 -0600 Subject: move valmap to hh; add to env --- src/nix/flake.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 62a413e27..6af052008 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -408,6 +408,7 @@ struct CmdFlakeCheck : FlakeCommand if (auto attr = v.attrs->get(state->symbols.create("description"))) state->forceStringNoCtx(*attr->value, *attr->pos); + // state->forceStringNoCtx(std::optional(v.attrs), *attr->value, *attr->pos); else throw Error("template '%s' lacks attribute 'description'", attrPath); -- cgit v1.2.3 From e54f17eb46bc487abc38e70dfc2f1c617fb59d32 Mon Sep 17 00:00:00 2001 From: Ben Burdette Date: Fri, 22 Oct 2021 14:27:04 -0600 Subject: remove more debug code --- src/nix/flake.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 6af052008..62a413e27 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -408,7 +408,6 @@ struct CmdFlakeCheck : FlakeCommand if (auto attr = v.attrs->get(state->symbols.create("description"))) state->forceStringNoCtx(*attr->value, *attr->pos); - // state->forceStringNoCtx(std::optional(v.attrs), *attr->value, *attr->pos); else throw Error("template '%s' lacks attribute 'description'", attrPath); -- cgit v1.2.3 From be1f0697468bd6c0f2be4f7e058270c161098e9f Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Fri, 4 Mar 2022 05:04:47 +0100 Subject: Add error context for most basic coercions --- src/nix/bundle.cc | 2 +- src/nix/flake.cc | 46 +++++++++++++++++++++++----------------------- src/nix/main.cc | 2 +- src/nix/prefetch.cc | 16 ++++++++-------- src/nix/repl.cc | 4 ++-- src/nix/upgrade-nix.cc | 2 +- 6 files changed, 36 insertions(+), 36 deletions(-) (limited to 'src/nix') diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc index 7ed558dee..aa074edc2 100644 --- a/src/nix/bundle.cc +++ b/src/nix/bundle.cc @@ -111,7 +111,7 @@ struct CmdBundle : InstallableCommand if (!outLink) { auto &attr = vRes->attrs->need(evalState->sName); - outLink = evalState->forceStringNoCtx(*attr.value,*attr.pos); + outLink = evalState->forceStringNoCtx(*attr.value, *attr.pos, ""); } // TODO: will crash if not a localFSStore? diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 144f8f886..703c3beb2 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -126,12 +126,12 @@ static void enumerateOutputs(EvalState & state, Value & vFlake, std::function callback) { auto pos = vFlake.determinePos(noPos); - state.forceAttrs(vFlake, pos); + state.forceAttrs(vFlake, pos, "While evaluating a flake to get its outputs"); auto aOutputs = vFlake.attrs->get(state.symbols.create("outputs")); assert(aOutputs); - state.forceAttrs(*aOutputs->value, pos); + state.forceAttrs(*aOutputs->value, pos, "While evaluating the outputs of a flake"); auto sHydraJobs = state.symbols.create("hydraJobs"); @@ -401,13 +401,13 @@ struct CmdFlakeCheck : FlakeCommand checkHydraJobs = [&](const std::string & attrPath, Value & v, const Pos & pos) { try { - state->forceAttrs(v, pos); + state->forceAttrs(v, pos, ""); if (state->isDerivation(v)) throw Error("jobset should not be a derivation at top-level"); for (auto & attr : *v.attrs) { - state->forceAttrs(*attr.value, *attr.pos); + state->forceAttrs(*attr.value, *attr.pos, ""); auto attrPath2 = attrPath + "." + (std::string) attr.name; if (state->isDerivation(*attr.value)) { Activity act(*logger, lvlChatty, actUnknown, @@ -429,7 +429,7 @@ struct CmdFlakeCheck : FlakeCommand fmt("checking NixOS configuration '%s'", attrPath)); Bindings & bindings(*state->allocBindings(0)); auto vToplevel = findAlongAttrPath(*state, "config.system.build.toplevel", bindings, v).first; - state->forceAttrs(*vToplevel, pos); + state->forceValue(*vToplevel, pos); if (!state->isDerivation(*vToplevel)) throw Error("attribute 'config.system.build.toplevel' is not a derivation"); } catch (Error & e) { @@ -443,7 +443,7 @@ struct CmdFlakeCheck : FlakeCommand Activity act(*logger, lvlChatty, actUnknown, fmt("checking template '%s'", attrPath)); - state->forceAttrs(v, pos); + state->forceAttrs(v, pos, ""); if (auto attr = v.attrs->get(state->symbols.create("path"))) { if (attr->name == state->symbols.create("path")) { @@ -457,7 +457,7 @@ struct CmdFlakeCheck : FlakeCommand throw Error("template '%s' lacks attribute 'path'", attrPath); if (auto attr = v.attrs->get(state->symbols.create("description"))) - state->forceStringNoCtx(*attr->value, *attr->pos); + state->forceStringNoCtx(*attr->value, *attr->pos, ""); else throw Error("template '%s' lacks attribute 'description'", attrPath); @@ -513,10 +513,10 @@ struct CmdFlakeCheck : FlakeCommand warn("flake output attribute '%s' is deprecated; use '%s' instead", name, replacement); if (name == "checks") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) { checkSystemName(attr.name, *attr.pos); - state->forceAttrs(*attr.value, *attr.pos); + state->forceAttrs(*attr.value, *attr.pos, ""); for (auto & attr2 : *attr.value->attrs) { auto drvPath = checkDerivation( fmt("%s.%s.%s", name, attr.name, attr2.name), @@ -528,10 +528,10 @@ struct CmdFlakeCheck : FlakeCommand } else if (name == "packages" || name == "devShells") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) { checkSystemName(attr.name, *attr.pos); - state->forceAttrs(*attr.value, *attr.pos); + state->forceAttrs(*attr.value, *attr.pos, ""); for (auto & attr2 : *attr.value->attrs) checkDerivation( fmt("%s.%s.%s", name, attr.name, attr2.name), @@ -540,10 +540,10 @@ struct CmdFlakeCheck : FlakeCommand } else if (name == "apps") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) { checkSystemName(attr.name, *attr.pos); - state->forceAttrs(*attr.value, *attr.pos); + state->forceAttrs(*attr.value, *attr.pos, ""); for (auto & attr2 : *attr.value->attrs) checkApp( fmt("%s.%s.%s", name, attr.name, attr2.name), @@ -552,7 +552,7 @@ struct CmdFlakeCheck : FlakeCommand } else if (name == "defaultPackage" || name == "devShell") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) { checkSystemName(attr.name, *attr.pos); checkDerivation( @@ -562,7 +562,7 @@ struct CmdFlakeCheck : FlakeCommand } else if (name == "defaultApp") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) { checkSystemName(attr.name, *attr.pos); checkApp( @@ -572,7 +572,7 @@ struct CmdFlakeCheck : FlakeCommand } else if (name == "legacyPackages") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) { checkSystemName(attr.name, *attr.pos); // FIXME: do getDerivations? @@ -583,7 +583,7 @@ struct CmdFlakeCheck : FlakeCommand checkOverlay(name, vOutput, pos); else if (name == "overlays") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) checkOverlay(fmt("%s.%s", name, attr.name), *attr.value, *attr.pos); @@ -593,14 +593,14 @@ struct CmdFlakeCheck : FlakeCommand checkModule(name, vOutput, pos); else if (name == "nixosModules") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) checkModule(fmt("%s.%s", name, attr.name), *attr.value, *attr.pos); } else if (name == "nixosConfigurations") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) checkNixOSConfiguration(fmt("%s.%s", name, attr.name), *attr.value, *attr.pos); @@ -613,14 +613,14 @@ struct CmdFlakeCheck : FlakeCommand checkTemplate(name, vOutput, pos); else if (name == "templates") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) checkTemplate(fmt("%s.%s", name, attr.name), *attr.value, *attr.pos); } else if (name == "defaultBundler") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) { checkSystemName(attr.name, *attr.pos); checkBundler( @@ -630,10 +630,10 @@ struct CmdFlakeCheck : FlakeCommand } else if (name == "bundlers") { - state->forceAttrs(vOutput, pos); + state->forceAttrs(vOutput, pos, ""); for (auto & attr : *vOutput.attrs) { checkSystemName(attr.name, *attr.pos); - state->forceAttrs(*attr.value, *attr.pos); + state->forceAttrs(*attr.value, *attr.pos, ""); for (auto & attr2 : *attr.value->attrs) { checkBundler( fmt("%s.%s.%s", name, attr.name, attr2.name), diff --git a/src/nix/main.cc b/src/nix/main.cc index b923f2535..0c6286686 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -196,7 +196,7 @@ static void showHelp(std::vector subcommand, MultiCommand & topleve if (!attr) throw UsageError("Nix has no subcommand '%s'", concatStringsSep("", subcommand)); - auto markdown = state.forceString(*attr->value); + auto markdown = state.forceString(*attr->value, noPos, "While evaluating the lowdown help text"); RunPager pager; std::cout << renderMarkdownToTerminal(markdown) << "\n"; diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index f2dd44ba4..4376da896 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -28,17 +28,17 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url) Value vMirrors; // FIXME: use nixpkgs flake state.eval(state.parseExprFromString("import ", "."), vMirrors); - state.forceAttrs(vMirrors, noPos); + state.forceAttrs(vMirrors, noPos, "While evaluating the set of all mirrors"); auto mirrorList = vMirrors.attrs->find(state.symbols.create(mirrorName)); if (mirrorList == vMirrors.attrs->end()) throw Error("unknown mirror name '%s'", mirrorName); - state.forceList(*mirrorList->value, noPos); + state.forceList(*mirrorList->value, noPos, "While evaluating this mirror configuration"); if (mirrorList->value->listSize() < 1) throw Error("mirror URL '%s' did not expand to anything", url); - std::string mirror(state.forceString(*mirrorList->value->listElems()[0])); + std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "While evaluating the first available mirror")); return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1); } @@ -196,27 +196,27 @@ static int main_nix_prefetch_url(int argc, char * * argv) Value vRoot; state->evalFile(path, vRoot); Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot).first); - state->forceAttrs(v, noPos); + state->forceAttrs(v, noPos, "While evaluating the source attribute to prefetch"); /* Extract the URL. */ auto & attr = v.attrs->need(state->symbols.create("urls")); - state->forceList(*attr.value, noPos); + state->forceList(*attr.value, noPos, "While evaluating the urls to prefetch"); if (attr.value->listSize() < 1) throw Error("'urls' list is empty"); - url = state->forceString(*attr.value->listElems()[0]); + url = state->forceString(*attr.value->listElems()[0], noPos, "While evaluating the first url from the urls list"); /* Extract the hash mode. */ auto attr2 = v.attrs->get(state->symbols.create("outputHashMode")); if (!attr2) printInfo("warning: this does not look like a fetchurl call"); else - unpack = state->forceString(*attr2->value) == "recursive"; + unpack = state->forceString(*attr2->value, noPos, "While evaluating the outputHashMode of the source to prefetch") == "recursive"; /* Extract the name. */ if (!name) { auto attr3 = v.attrs->get(state->symbols.create("name")); if (!attr3) - name = state->forceString(*attr3->value); + name = state->forceString(*attr3->value, noPos, "While evaluating the name of the source to prefetch"); } } diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 3a51a13e6..7011ff939 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -342,7 +342,7 @@ StringSet NixRepl::completePrefix(const std::string & prefix) Expr * e = parseString(expr); Value v; e->eval(*state, *env, v); - state->forceAttrs(v, noPos); + state->forceAttrs(v, noPos, "nevermind, it is ignored anyway"); for (auto & i : *v.attrs) { std::string name = i.name; @@ -675,7 +675,7 @@ void NixRepl::reloadFiles() void NixRepl::addAttrsToScope(Value & attrs) { - state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }); + state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "While evaluating an attribute set to be merged in the global scope"); if (displ + attrs.attrs->size() >= envSize) throw Error("environment full; cannot add more variables"); diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 17a5a77ee..1f433a199 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -144,7 +144,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand Bindings & bindings(*state->allocBindings(0)); auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v).first; - return store->parseStorePath(state->forceString(*v2)); + return store->parseStorePath(state->forceString(*v2, noPos, "While evaluating the path tho latest nix version")); } }; -- cgit v1.2.3 From 3a5855353e5dc2986c38bb66eaff5538dea70da1 Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Fri, 4 Mar 2022 21:47:58 +0100 Subject: Add detailed error mesage for coerceTo{String,Path} --- src/nix/bundle.cc | 4 ++-- src/nix/eval.cc | 2 +- src/nix/flake.cc | 2 +- src/nix/repl.cc | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nix') diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc index aa074edc2..9ff66899e 100644 --- a/src/nix/bundle.cc +++ b/src/nix/bundle.cc @@ -97,13 +97,13 @@ struct CmdBundle : InstallableCommand throw Error("the bundler '%s' does not produce a derivation", bundler.what()); PathSet context2; - auto drvPath = evalState->coerceToStorePath(*attr1->pos, *attr1->value, context2); + auto drvPath = evalState->coerceToStorePath(*attr1->pos, *attr1->value, context2, ""); auto attr2 = vRes->attrs->get(evalState->sOutPath); if (!attr2) throw Error("the bundler '%s' does not produce a derivation", bundler.what()); - auto outPath = evalState->coerceToStorePath(*attr2->pos, *attr2->value, context2); + auto outPath = evalState->coerceToStorePath(*attr2->pos, *attr2->value, context2, ""); store->buildPaths({ DerivedPath::Built { drvPath } }); diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 8cd04d5fe..8ee3ba45b 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -107,7 +107,7 @@ struct CmdEval : MixJSON, InstallableCommand else if (raw) { stopProgressBar(); - std::cout << *state->coerceToString(noPos, *v, context); + std::cout << *state->coerceToString(noPos, *v, context, "While generating the eval command output"); } else if (json) { diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 703c3beb2..356f89713 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -448,7 +448,7 @@ struct CmdFlakeCheck : FlakeCommand if (auto attr = v.attrs->get(state->symbols.create("path"))) { if (attr->name == state->symbols.create("path")) { PathSet context; - auto path = state->coerceToPath(*attr->pos, *attr->value, context); + auto path = state->coerceToPath(*attr->pos, *attr->value, context, ""); if (!store->isInStore(path)) throw Error("template '%s' has a bad 'path' attribute"); // TODO: recursively check the flake in 'path'. diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 7011ff939..0cb68552c 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -461,7 +461,7 @@ bool NixRepl::processLine(std::string line) if (v.type() == nPath || v.type() == nString) { PathSet context; - auto filename = state->coerceToString(noPos, v, context); + auto filename = state->coerceToString(noPos, v, context, "While evaluating the filename to edit"); pos.file = state->symbols.create(*filename); } else if (v.isLambda()) { pos = v.lambda.fun->pos; @@ -780,7 +780,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m Bindings::iterator i = v.attrs->find(state->sDrvPath); PathSet context; if (i != v.attrs->end()) - str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context)); + str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context, "While evaluating the drvPath of a derivation")); else str << "???"; str << "»"; -- cgit v1.2.3 From 13c4dc65327c9654c47e6d80c0f4e1797b999f97 Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Mon, 7 Mar 2022 11:33:03 +0100 Subject: more fixes --- src/nix/eval.cc | 2 +- src/nix/flake.cc | 4 ++-- src/nix/main.cc | 2 +- src/nix/prefetch.cc | 16 ++++++++-------- src/nix/repl.cc | 8 ++++---- src/nix/upgrade-nix.cc | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src/nix') diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 8ee3ba45b..1d66d457c 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -107,7 +107,7 @@ struct CmdEval : MixJSON, InstallableCommand else if (raw) { stopProgressBar(); - std::cout << *state->coerceToString(noPos, *v, context, "While generating the eval command output"); + std::cout << *state->coerceToString(noPos, *v, context, "While generating the eval command output: "); } else if (json) { diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 356f89713..9ba6e5be1 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -126,12 +126,12 @@ static void enumerateOutputs(EvalState & state, Value & vFlake, std::function callback) { auto pos = vFlake.determinePos(noPos); - state.forceAttrs(vFlake, pos, "While evaluating a flake to get its outputs"); + state.forceAttrs(vFlake, pos, "While evaluating a flake to get its outputs: "); auto aOutputs = vFlake.attrs->get(state.symbols.create("outputs")); assert(aOutputs); - state.forceAttrs(*aOutputs->value, pos, "While evaluating the outputs of a flake"); + state.forceAttrs(*aOutputs->value, pos, "While evaluating the outputs of a flake: "); auto sHydraJobs = state.symbols.create("hydraJobs"); diff --git a/src/nix/main.cc b/src/nix/main.cc index 0c6286686..3ba7ce8b6 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -196,7 +196,7 @@ static void showHelp(std::vector subcommand, MultiCommand & topleve if (!attr) throw UsageError("Nix has no subcommand '%s'", concatStringsSep("", subcommand)); - auto markdown = state.forceString(*attr->value, noPos, "While evaluating the lowdown help text"); + auto markdown = state.forceString(*attr->value, noPos, "While evaluating the lowdown help text: "); RunPager pager; std::cout << renderMarkdownToTerminal(markdown) << "\n"; diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index 4376da896..a4a8ab605 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -28,17 +28,17 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url) Value vMirrors; // FIXME: use nixpkgs flake state.eval(state.parseExprFromString("import ", "."), vMirrors); - state.forceAttrs(vMirrors, noPos, "While evaluating the set of all mirrors"); + state.forceAttrs(vMirrors, noPos, "While evaluating the set of all mirrors: "); auto mirrorList = vMirrors.attrs->find(state.symbols.create(mirrorName)); if (mirrorList == vMirrors.attrs->end()) throw Error("unknown mirror name '%s'", mirrorName); - state.forceList(*mirrorList->value, noPos, "While evaluating this mirror configuration"); + state.forceList(*mirrorList->value, noPos, "While evaluating this mirror configuration: "); if (mirrorList->value->listSize() < 1) throw Error("mirror URL '%s' did not expand to anything", url); - std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "While evaluating the first available mirror")); + std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "While evaluating the first available mirror: ")); return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1); } @@ -196,27 +196,27 @@ static int main_nix_prefetch_url(int argc, char * * argv) Value vRoot; state->evalFile(path, vRoot); Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot).first); - state->forceAttrs(v, noPos, "While evaluating the source attribute to prefetch"); + state->forceAttrs(v, noPos, "While evaluating the source attribute to prefetch: "); /* Extract the URL. */ auto & attr = v.attrs->need(state->symbols.create("urls")); - state->forceList(*attr.value, noPos, "While evaluating the urls to prefetch"); + state->forceList(*attr.value, noPos, "While evaluating the urls to prefetch: "); if (attr.value->listSize() < 1) throw Error("'urls' list is empty"); - url = state->forceString(*attr.value->listElems()[0], noPos, "While evaluating the first url from the urls list"); + url = state->forceString(*attr.value->listElems()[0], noPos, "While evaluating the first url from the urls list: "); /* Extract the hash mode. */ auto attr2 = v.attrs->get(state->symbols.create("outputHashMode")); if (!attr2) printInfo("warning: this does not look like a fetchurl call"); else - unpack = state->forceString(*attr2->value, noPos, "While evaluating the outputHashMode of the source to prefetch") == "recursive"; + unpack = state->forceString(*attr2->value, noPos, "While evaluating the outputHashMode of the source to prefetch: ") == "recursive"; /* Extract the name. */ if (!name) { auto attr3 = v.attrs->get(state->symbols.create("name")); if (!attr3) - name = state->forceString(*attr3->value, noPos, "While evaluating the name of the source to prefetch"); + name = state->forceString(*attr3->value, noPos, "While evaluating the name of the source to prefetch: "); } } diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 0cb68552c..038ed4911 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -342,7 +342,7 @@ StringSet NixRepl::completePrefix(const std::string & prefix) Expr * e = parseString(expr); Value v; e->eval(*state, *env, v); - state->forceAttrs(v, noPos, "nevermind, it is ignored anyway"); + state->forceAttrs(v, noPos, "nevermind, it is ignored anyway: "); for (auto & i : *v.attrs) { std::string name = i.name; @@ -461,7 +461,7 @@ bool NixRepl::processLine(std::string line) if (v.type() == nPath || v.type() == nString) { PathSet context; - auto filename = state->coerceToString(noPos, v, context, "While evaluating the filename to edit"); + auto filename = state->coerceToString(noPos, v, context, "While evaluating the filename to edit: "); pos.file = state->symbols.create(*filename); } else if (v.isLambda()) { pos = v.lambda.fun->pos; @@ -675,7 +675,7 @@ void NixRepl::reloadFiles() void NixRepl::addAttrsToScope(Value & attrs) { - state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "While evaluating an attribute set to be merged in the global scope"); + state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "While evaluating an attribute set to be merged in the global scope: "); if (displ + attrs.attrs->size() >= envSize) throw Error("environment full; cannot add more variables"); @@ -780,7 +780,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m Bindings::iterator i = v.attrs->find(state->sDrvPath); PathSet context; if (i != v.attrs->end()) - str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context, "While evaluating the drvPath of a derivation")); + str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context, "While evaluating the drvPath of a derivation: ")); else str << "???"; str << "»"; diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 1f433a199..ae314a7c6 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -144,7 +144,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand Bindings & bindings(*state->allocBindings(0)); auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v).first; - return store->parseStorePath(state->forceString(*v2, noPos, "While evaluating the path tho latest nix version")); + return store->parseStorePath(state->forceString(*v2, noPos, "While evaluating the path tho latest nix version: ")); } }; -- cgit v1.2.3 From 1942fed6d9cee95775046c5ad3d253ab2e8ab210 Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Fri, 18 Mar 2022 01:10:04 +0100 Subject: Revert extra colon at end os strings --- src/nix/eval.cc | 2 +- src/nix/flake.cc | 4 ++-- src/nix/main.cc | 2 +- src/nix/prefetch.cc | 16 ++++++++-------- src/nix/repl.cc | 8 ++++---- src/nix/upgrade-nix.cc | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src/nix') diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 1d66d457c..8ee3ba45b 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -107,7 +107,7 @@ struct CmdEval : MixJSON, InstallableCommand else if (raw) { stopProgressBar(); - std::cout << *state->coerceToString(noPos, *v, context, "While generating the eval command output: "); + std::cout << *state->coerceToString(noPos, *v, context, "While generating the eval command output"); } else if (json) { diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 9ba6e5be1..356f89713 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -126,12 +126,12 @@ static void enumerateOutputs(EvalState & state, Value & vFlake, std::function callback) { auto pos = vFlake.determinePos(noPos); - state.forceAttrs(vFlake, pos, "While evaluating a flake to get its outputs: "); + state.forceAttrs(vFlake, pos, "While evaluating a flake to get its outputs"); auto aOutputs = vFlake.attrs->get(state.symbols.create("outputs")); assert(aOutputs); - state.forceAttrs(*aOutputs->value, pos, "While evaluating the outputs of a flake: "); + state.forceAttrs(*aOutputs->value, pos, "While evaluating the outputs of a flake"); auto sHydraJobs = state.symbols.create("hydraJobs"); diff --git a/src/nix/main.cc b/src/nix/main.cc index 3ba7ce8b6..0c6286686 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -196,7 +196,7 @@ static void showHelp(std::vector subcommand, MultiCommand & topleve if (!attr) throw UsageError("Nix has no subcommand '%s'", concatStringsSep("", subcommand)); - auto markdown = state.forceString(*attr->value, noPos, "While evaluating the lowdown help text: "); + auto markdown = state.forceString(*attr->value, noPos, "While evaluating the lowdown help text"); RunPager pager; std::cout << renderMarkdownToTerminal(markdown) << "\n"; diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index a4a8ab605..4376da896 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -28,17 +28,17 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url) Value vMirrors; // FIXME: use nixpkgs flake state.eval(state.parseExprFromString("import ", "."), vMirrors); - state.forceAttrs(vMirrors, noPos, "While evaluating the set of all mirrors: "); + state.forceAttrs(vMirrors, noPos, "While evaluating the set of all mirrors"); auto mirrorList = vMirrors.attrs->find(state.symbols.create(mirrorName)); if (mirrorList == vMirrors.attrs->end()) throw Error("unknown mirror name '%s'", mirrorName); - state.forceList(*mirrorList->value, noPos, "While evaluating this mirror configuration: "); + state.forceList(*mirrorList->value, noPos, "While evaluating this mirror configuration"); if (mirrorList->value->listSize() < 1) throw Error("mirror URL '%s' did not expand to anything", url); - std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "While evaluating the first available mirror: ")); + std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "While evaluating the first available mirror")); return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1); } @@ -196,27 +196,27 @@ static int main_nix_prefetch_url(int argc, char * * argv) Value vRoot; state->evalFile(path, vRoot); Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot).first); - state->forceAttrs(v, noPos, "While evaluating the source attribute to prefetch: "); + state->forceAttrs(v, noPos, "While evaluating the source attribute to prefetch"); /* Extract the URL. */ auto & attr = v.attrs->need(state->symbols.create("urls")); - state->forceList(*attr.value, noPos, "While evaluating the urls to prefetch: "); + state->forceList(*attr.value, noPos, "While evaluating the urls to prefetch"); if (attr.value->listSize() < 1) throw Error("'urls' list is empty"); - url = state->forceString(*attr.value->listElems()[0], noPos, "While evaluating the first url from the urls list: "); + url = state->forceString(*attr.value->listElems()[0], noPos, "While evaluating the first url from the urls list"); /* Extract the hash mode. */ auto attr2 = v.attrs->get(state->symbols.create("outputHashMode")); if (!attr2) printInfo("warning: this does not look like a fetchurl call"); else - unpack = state->forceString(*attr2->value, noPos, "While evaluating the outputHashMode of the source to prefetch: ") == "recursive"; + unpack = state->forceString(*attr2->value, noPos, "While evaluating the outputHashMode of the source to prefetch") == "recursive"; /* Extract the name. */ if (!name) { auto attr3 = v.attrs->get(state->symbols.create("name")); if (!attr3) - name = state->forceString(*attr3->value, noPos, "While evaluating the name of the source to prefetch: "); + name = state->forceString(*attr3->value, noPos, "While evaluating the name of the source to prefetch"); } } diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 038ed4911..0cb68552c 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -342,7 +342,7 @@ StringSet NixRepl::completePrefix(const std::string & prefix) Expr * e = parseString(expr); Value v; e->eval(*state, *env, v); - state->forceAttrs(v, noPos, "nevermind, it is ignored anyway: "); + state->forceAttrs(v, noPos, "nevermind, it is ignored anyway"); for (auto & i : *v.attrs) { std::string name = i.name; @@ -461,7 +461,7 @@ bool NixRepl::processLine(std::string line) if (v.type() == nPath || v.type() == nString) { PathSet context; - auto filename = state->coerceToString(noPos, v, context, "While evaluating the filename to edit: "); + auto filename = state->coerceToString(noPos, v, context, "While evaluating the filename to edit"); pos.file = state->symbols.create(*filename); } else if (v.isLambda()) { pos = v.lambda.fun->pos; @@ -675,7 +675,7 @@ void NixRepl::reloadFiles() void NixRepl::addAttrsToScope(Value & attrs) { - state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "While evaluating an attribute set to be merged in the global scope: "); + state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "While evaluating an attribute set to be merged in the global scope"); if (displ + attrs.attrs->size() >= envSize) throw Error("environment full; cannot add more variables"); @@ -780,7 +780,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m Bindings::iterator i = v.attrs->find(state->sDrvPath); PathSet context; if (i != v.attrs->end()) - str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context, "While evaluating the drvPath of a derivation: ")); + str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context, "While evaluating the drvPath of a derivation")); else str << "???"; str << "»"; diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index ae314a7c6..1f433a199 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -144,7 +144,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand Bindings & bindings(*state->allocBindings(0)); auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v).first; - return store->parseStorePath(state->forceString(*v2, noPos, "While evaluating the path tho latest nix version: ")); + return store->parseStorePath(state->forceString(*v2, noPos, "While evaluating the path tho latest nix version")); } }; -- cgit v1.2.3 From fda2224b591c2667d18fb815f117f48b45a54cb1 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 7 Apr 2022 19:45:38 +0000 Subject: Add release notes mark experimental --- src/nix/nix.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 4919763c4..691aa137b 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -132,6 +132,8 @@ the Nix store. Here are the recognised types of installables: * **Indexed store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv!out` + *(Experimental, part of by the `computed-derivations` experimental feature.)* + Store derivations can be indexed with a specific output name. This allows finer control versus just specifying a derivation (without `--derivation`) and getting all the outputs. -- cgit v1.2.3 From 75b62e52600a44b42693944b50638bf580a2c86e Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 18 Jun 2020 17:54:16 +0000 Subject: Avoid `fmt` when constructor already does it There is a correctnes issue here, but #3724 will fix that. This is just a cleanup for brevity's sake. --- src/nix/repl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 1f9d4fb4e..ec8a57a8e 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -119,7 +119,7 @@ std::string runNix(Path program, const Strings & args, }); if (!statusOk(res.first)) - throw ExecError(res.first, fmt("program '%1%' %2%", program, statusToString(res.first))); + throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first)); return res.second; } -- cgit v1.2.3 From 0e2b01b14e77dfb9a6f1748dec353273f91d1609 Mon Sep 17 00:00:00 2001 From: ckie Date: Mon, 18 Apr 2022 20:21:47 +0300 Subject: nix repl: make symlinks with the :bl command Requested by ppepino on the Matrix: https://matrix.to/#/!KqkRjyTEzAGRiZFBYT:nixos.org/$Tb32BS3rVE2BSULAX4sPm0h6CDewX2hClOTGzTC7gwM?via=nixos.org&via=matrix.org&via=nixos.dev This adds a new command, :bl, which works like :b but also creates a GC root symlink to the various derivation outputs. ckie@cookiemonster ~/git/nix -> ./outputs/out/bin/nix repl Welcome to Nix 2.6.0. Type :? for help. nix-repl> :l Added 16118 variables. nix-repl> :b runCommand "hello" {} "echo hi > $out" This derivation produced the following outputs: ./repl-result-out -> /nix/store/kidqq2acdpi05c4a9mlbg2baikmzik44-hello [1 built, 0.0 MiB DL] ckie@cookiemonster ~/git/nix -> cat ./repl-result-out hi --- src/nix/repl.cc | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 1f9d4fb4e..b055698b3 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -33,6 +33,7 @@ extern "C" { #include "command.hh" #include "finally.hh" #include "markdown.hh" +#include "local-fs-store.hh" #if HAVE_BOEHMGC #define GC_INCLUDE_NEW @@ -419,7 +420,8 @@ bool NixRepl::processLine(std::string line) << " Evaluate and print expression\n" << " = Bind expression to variable\n" << " :a Add attributes from resulting set to scope\n" - << " :b Build derivation\n" + << " :b Build a derivation\n" + << " :bl Build a derivation, creating GC roots in the working directory\n" << " :e Open package or function in $EDITOR\n" << " :i Build derivation, then install result into current profile\n" << " :l Load Nix expression and add it to scope\n" @@ -502,18 +504,26 @@ bool NixRepl::processLine(std::string line) runNix("nix-shell", {state->store->printStorePath(drvPath)}); } - else if (command == ":b" || command == ":i" || command == ":s" || command == ":log") { + else if (command == ":b" || command == ":bl" || command == ":i" || command == ":s" || command == ":log") { Value v; evalString(arg, v); StorePath drvPath = getDerivationPath(v); Path drvPathRaw = state->store->printStorePath(drvPath); - if (command == ":b") { + if (command == ":b" || command == ":bl") { state->store->buildPaths({DerivedPath::Built{drvPath}}); auto drv = state->store->readDerivation(drvPath); logger->cout("\nThis derivation produced the following outputs:"); - for (auto & [outputName, outputPath] : state->store->queryDerivationOutputMap(drvPath)) - logger->cout(" %s -> %s", outputName, state->store->printStorePath(outputPath)); + for (auto & [outputName, outputPath] : state->store->queryDerivationOutputMap(drvPath)) { + auto localStore = state->store.dynamic_pointer_cast(); + if (localStore && command == ":bl") { + std::string symlink = "repl-result-" + outputName; + localStore->addPermRoot(outputPath, absPath(symlink)); + logger->cout(" ./%s -> %s", symlink, state->store->printStorePath(outputPath)); + } else { + logger->cout(" %s -> %s", outputName, state->store->printStorePath(outputPath)); + } + } } else if (command == ":i") { runNix("nix-env", {"-i", drvPathRaw}); } else if (command == ":log") { -- cgit v1.2.3 From 51cfea8bb05d3f284534b2486cc29bb0ebf17ade Mon Sep 17 00:00:00 2001 From: Artturin Date: Sat, 19 Mar 2022 20:16:05 +0200 Subject: nix build: add --print-out-paths flag has the same functionality as default nix-build $ nix-build . -A "bash" -A "bash.dev" -A "tinycc" /nix/store/4nmqxajzaf60yjribkgvj5j54x9yvr1r-bash-5.1-p12 /nix/store/c49i1ggnr5cc8gxmk9xm0cn961z104dn-bash-5.1-p12-dev /nix/store/dbapb08862ajgaax3621fz8hly9fdah3-tcc-0.9.27+date=2022-01-11 $ nix-build . -A "bash" /nix/store/4nmqxajzaf60yjribkgvj5j54x9yvr1r-bash-5.1-p12 $ $HOME/nixgits/nix/result/bin/nix build "nixpkgs#bash" "nixpkgs#bash.dev" "nixpkgs#tinycc" --print-out-paths /nix/store/4nmqxajzaf60yjribkgvj5j54x9yvr1r-bash-5.1-p12 /nix/store/c49i1ggnr5cc8gxmk9xm0cn961z104dn-bash-5.1-p12-dev /nix/store/dbapb08862ajgaax3621fz8hly9fdah3-tcc-0.9.27+date=2022-01-11 $ $HOME/nixgits/nix/result/bin/nix build "nixpkgs#bash" --print-out-paths /nix/store/4nmqxajzaf60yjribkgvj5j54x9yvr1r-bash-5.1-p12 --- src/nix/build.cc | 24 ++++++++++++++++++++++++ src/nix/build.md | 7 +++++++ 2 files changed, 31 insertions(+) (limited to 'src/nix') diff --git a/src/nix/build.cc b/src/nix/build.cc index 840c7ca38..9c648d28e 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -4,6 +4,7 @@ #include "shared.hh" #include "store-api.hh" #include "local-fs-store.hh" +#include "progress-bar.hh" #include @@ -12,6 +13,7 @@ using namespace nix; struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile { Path outLink = "result"; + bool printOutputPaths = false; BuildMode buildMode = bmNormal; CmdBuild() @@ -31,6 +33,12 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile .handler = {&outLink, Path("")}, }); + addFlag({ + .longName = "print-out-paths", + .description = "Print the resulting output paths", + .handler = {&printOutputPaths, true}, + }); + addFlag({ .longName = "rebuild", .description = "Rebuild an already built package and compare the result to the existing store paths.", @@ -93,6 +101,22 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile }, buildable.raw()); } + if (printOutputPaths) { + stopProgressBar(); + for (auto & buildable : buildables) { + std::visit(overloaded { + [&](const BuiltPath::Opaque & bo) { + std::cout << store->printStorePath(bo.path) << std::endl; + }, + [&](const BuiltPath::Built & bfd) { + for (auto & output : bfd.outputs) { + std::cout << store->printStorePath(output.second) << std::endl; + } + }, + }, buildable.raw()); + } + } + updateProfile(buildables); } }; diff --git a/src/nix/build.md b/src/nix/build.md index 20138b7e0..6a79f308c 100644 --- a/src/nix/build.md +++ b/src/nix/build.md @@ -25,6 +25,13 @@ R""( lrwxrwxrwx 1 … result-1 -> /nix/store/rkfrm0z6x6jmi7d3gsmma4j53h15mg33-cowsay-3.03+dfsg2 ``` +* Build GNU Hello and print the resulting store path. + + ```console + # nix build nixpkgs#hello --print-out-paths + /nix/store/v5sv61sszx301i0x6xysaqzla09nksnd-hello-2.10 + ``` + * Build a specific output: ```console -- cgit v1.2.3 From f05e1f6fbb8a760f23a7af16b065078df6588acf Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 21 Apr 2022 11:58:40 +0200 Subject: Move hiliteMatches into a separate header This is mostly so that we don't #include everywhere (which adds quite a bit of compilation time). --- src/nix/search.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/search.cc b/src/nix/search.cc index e96a85ea2..e284de95c 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -9,7 +9,7 @@ #include "shared.hh" #include "eval-cache.hh" #include "attr-path.hh" -#include "fmt.hh" +#include "hilite.hh" #include #include -- cgit v1.2.3 From 38de79fcf7e00187107e638036c010911d1b675b Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 4 Mar 2022 19:47:32 +0100 Subject: remove Bindings::need a future commit will remove the ability to convert the symbol type used in bindings to strings. since we only have two users we can inline the error check. --- src/nix/bundle.cc | 6 ++++-- src/nix/prefetch.cc | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src/nix') diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc index 81fb8464a..ee91e8ed0 100644 --- a/src/nix/bundle.cc +++ b/src/nix/bundle.cc @@ -110,8 +110,10 @@ struct CmdBundle : InstallableCommand auto outPathS = store->printStorePath(outPath); if (!outLink) { - auto &attr = vRes->attrs->need(evalState->sName); - outLink = evalState->forceStringNoCtx(*attr.value,*attr.pos); + auto * attr = vRes->attrs->get(evalState->sName); + if (!attr) + throw Error("attribute 'name' missing"); + outLink = evalState->forceStringNoCtx(*attr->value, *attr->pos); } // TODO: will crash if not a localFSStore? diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index f2dd44ba4..ce3288dc1 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -199,11 +199,13 @@ static int main_nix_prefetch_url(int argc, char * * argv) state->forceAttrs(v, noPos); /* Extract the URL. */ - auto & attr = v.attrs->need(state->symbols.create("urls")); - state->forceList(*attr.value, noPos); - if (attr.value->listSize() < 1) + auto * attr = v.attrs->get(state->symbols.create("urls")); + if (!attr) + throw Error("attribute 'urls' missing"); + state->forceList(*attr->value, noPos); + if (attr->value->listSize() < 1) throw Error("'urls' list is empty"); - url = state->forceString(*attr.value->listElems()[0]); + url = state->forceString(*attr->value->listElems()[0]); /* Extract the hash mode. */ auto attr2 = v.attrs->get(state->symbols.create("outputHashMode")); -- cgit v1.2.3 From 39df15fb8e766c0a4fa2fda83784fb8a478a766c Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 4 Mar 2022 20:54:50 +0100 Subject: don't use full Pos for findPackageFilename/editorFor only file and line of the returned position were ever used, it wasn't actually used a position. as such we may as well use a path+int pair for only those two values and remove a use of Pos that would not work well with a position table. --- src/nix/edit.cc | 16 ++++++++-------- src/nix/repl.cc | 26 +++++++++++++------------- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src/nix') diff --git a/src/nix/edit.cc b/src/nix/edit.cc index fc48db0d7..ffe79af89 100644 --- a/src/nix/edit.cc +++ b/src/nix/edit.cc @@ -30,17 +30,17 @@ struct CmdEdit : InstallableCommand auto [v, pos] = installable->toValue(*state); - try { - pos = findPackageFilename(*state, *v, installable->what()); - } catch (NoPositionInfo &) { - } - - if (pos == noPos) - throw Error("cannot find position information for '%s", installable->what()); + const auto [file, line] = [&] { + try { + return findPackageFilename(*state, *v, installable->what()); + } catch (NoPositionInfo &) { + throw Error("cannot find position information for '%s", installable->what()); + } + }(); stopProgressBar(); - auto args = editorFor(pos); + auto args = editorFor(file, line); restoreProcessContext(); diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 0eb037858..391255ce9 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -461,21 +461,21 @@ bool NixRepl::processLine(std::string line) Value v; evalString(arg, v); - Pos pos; - - if (v.type() == nPath || v.type() == nString) { - PathSet context; - auto filename = state->coerceToString(noPos, v, context); - pos.file = state->symbols.create(*filename); - } else if (v.isLambda()) { - pos = v.lambda.fun->pos; - } else { - // assume it's a derivation - pos = findPackageFilename(*state, v, arg); - } + const auto [file, line] = [&] () -> std::pair { + if (v.type() == nPath || v.type() == nString) { + PathSet context; + auto filename = state->coerceToString(noPos, v, context); + return {state->symbols.create(*filename), 0}; + } else if (v.isLambda()) { + return {v.lambda.fun->pos.file, v.lambda.fun->pos.line}; + } else { + // assume it's a derivation + return findPackageFilename(*state, v, arg); + } + }(); // Open in EDITOR - auto args = editorFor(pos); + auto args = editorFor(file, line); auto editor = args.front(); args.pop_front(); -- cgit v1.2.3 From 6526d1676ba5a645f65d751e7529ccd273579017 Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 4 Mar 2022 19:31:59 +0100 Subject: replace most Pos objects/ptrs with indexes into a position table Pos objects are somewhat wasteful as they duplicate the origin file name and input type for each object. on files that produce more than one Pos when parsed this a sizeable waste of memory (one pointer per Pos). the same goes for ptr on 64 bit machines: parsing enough source to require 8 bytes to locate a position would need at least 8GB of input and 64GB of expression memory. it's not likely that we'll hit that any time soon, so we can use a uint32_t index to locate positions instead. --- src/nix/bundle.cc | 6 +-- src/nix/edit.cc | 4 +- src/nix/eval.cc | 12 +++--- src/nix/flake.cc | 118 ++++++++++++++++++++++++++++-------------------------- src/nix/repl.cc | 9 +++-- 5 files changed, 79 insertions(+), 70 deletions(-) (limited to 'src/nix') diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc index ee91e8ed0..2421adf4e 100644 --- a/src/nix/bundle.cc +++ b/src/nix/bundle.cc @@ -97,13 +97,13 @@ struct CmdBundle : InstallableCommand throw Error("the bundler '%s' does not produce a derivation", bundler.what()); PathSet context2; - auto drvPath = evalState->coerceToStorePath(*attr1->pos, *attr1->value, context2); + auto drvPath = evalState->coerceToStorePath(attr1->pos, *attr1->value, context2); auto attr2 = vRes->attrs->get(evalState->sOutPath); if (!attr2) throw Error("the bundler '%s' does not produce a derivation", bundler.what()); - auto outPath = evalState->coerceToStorePath(*attr2->pos, *attr2->value, context2); + auto outPath = evalState->coerceToStorePath(attr2->pos, *attr2->value, context2); store->buildPaths({ DerivedPath::Built { drvPath } }); @@ -113,7 +113,7 @@ struct CmdBundle : InstallableCommand auto * attr = vRes->attrs->get(evalState->sName); if (!attr) throw Error("attribute 'name' missing"); - outLink = evalState->forceStringNoCtx(*attr->value, *attr->pos); + outLink = evalState->forceStringNoCtx(*attr->value, attr->pos); } // TODO: will crash if not a localFSStore? diff --git a/src/nix/edit.cc b/src/nix/edit.cc index ffe79af89..76a134b1f 100644 --- a/src/nix/edit.cc +++ b/src/nix/edit.cc @@ -28,9 +28,9 @@ struct CmdEdit : InstallableCommand { auto state = getEvalState(); - auto [v, pos] = installable->toValue(*state); - const auto [file, line] = [&] { + auto [v, pos] = installable->toValue(*state); + try { return findPackageFilename(*state, *v, installable->what()); } catch (NoPositionInfo &) { diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 733b93661..81474c2d3 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -77,9 +77,9 @@ struct CmdEval : MixJSON, InstallableCommand if (pathExists(*writeTo)) throw Error("path '%s' already exists", *writeTo); - std::function recurse; + std::function recurse; - recurse = [&](Value & v, const Pos & pos, const Path & path) + recurse = [&](Value & v, const PosIdx pos, const Path & path) { state->forceValue(v, pos); if (v.type() == nString) @@ -92,14 +92,16 @@ struct CmdEval : MixJSON, InstallableCommand try { if (attr.name == "." || attr.name == "..") throw Error("invalid file name '%s'", attr.name); - recurse(*attr.value, *attr.pos, path + "/" + std::string(attr.name)); + recurse(*attr.value, attr.pos, path + "/" + std::string(attr.name)); } catch (Error & e) { - e.addTrace(*attr.pos, hintfmt("while evaluating the attribute '%s'", attr.name)); + e.addTrace( + state->positions[attr.pos], + hintfmt("while evaluating the attribute '%s'", attr.name)); throw; } } else - throw TypeError("value at '%s' is not a string or an attribute set", pos); + throw TypeError("value at '%s' is not a string or an attribute set", state->positions[pos]); }; recurse(*v, pos, *writeTo); diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 04b23ed0f..23e5cd24e 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -123,7 +123,7 @@ struct CmdFlakeLock : FlakeCommand }; static void enumerateOutputs(EvalState & state, Value & vFlake, - std::function callback) + std::function callback) { auto pos = vFlake.determinePos(noPos); state.forceAttrs(vFlake, pos); @@ -139,11 +139,11 @@ static void enumerateOutputs(EvalState & state, Value & vFlake, else. This way we can disable IFD for hydraJobs and then enable it for other outputs. */ if (auto attr = aOutputs->value->attrs->get(sHydraJobs)) - callback(attr->name, *attr->value, *attr->pos); + callback(attr->name, *attr->value, attr->pos); for (auto & attr : *aOutputs->value->attrs) { if (attr.name != sHydraJobs) - callback(attr.name, *attr.value, *attr.pos); + callback(attr.name, *attr.value, attr.pos); } } @@ -315,13 +315,17 @@ struct CmdFlakeCheck : FlakeCommand // FIXME: rewrite to use EvalCache. - auto checkSystemName = [&](const std::string & system, const Pos & pos) { + auto resolve = [&] (PosIdx p) { + return state->positions[p]; + }; + + auto checkSystemName = [&](const std::string & system, const PosIdx pos) { // FIXME: what's the format of "system"? if (system.find('-') == std::string::npos) - reportError(Error("'%s' is not a valid system type, at %s", system, pos)); + reportError(Error("'%s' is not a valid system type, at %s", system, resolve(pos))); }; - auto checkDerivation = [&](const std::string & attrPath, Value & v, const Pos & pos) -> std::optional { + auto checkDerivation = [&](const std::string & attrPath, Value & v, const PosIdx pos) -> std::optional { try { auto drvInfo = getDerivation(*state, v, false); if (!drvInfo) @@ -329,7 +333,7 @@ struct CmdFlakeCheck : FlakeCommand // FIXME: check meta attributes return drvInfo->queryDrvPath(); } catch (Error & e) { - e.addTrace(pos, hintfmt("while checking the derivation '%s'", attrPath)); + e.addTrace(resolve(pos), hintfmt("while checking the derivation '%s'", attrPath)); reportError(e); } return std::nullopt; @@ -337,7 +341,7 @@ struct CmdFlakeCheck : FlakeCommand std::vector drvPaths; - auto checkApp = [&](const std::string & attrPath, Value & v, const Pos & pos) { + auto checkApp = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { #if 0 // FIXME @@ -348,12 +352,12 @@ struct CmdFlakeCheck : FlakeCommand } #endif } catch (Error & e) { - e.addTrace(pos, hintfmt("while checking the app definition '%s'", attrPath)); + e.addTrace(resolve(pos), hintfmt("while checking the app definition '%s'", attrPath)); reportError(e); } }; - auto checkOverlay = [&](const std::string & attrPath, Value & v, const Pos & pos) { + auto checkOverlay = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { state->forceValue(v, pos); if (!v.isLambda() @@ -368,12 +372,12 @@ struct CmdFlakeCheck : FlakeCommand // FIXME: if we have a 'nixpkgs' input, use it to // evaluate the overlay. } catch (Error & e) { - e.addTrace(pos, hintfmt("while checking the overlay '%s'", attrPath)); + e.addTrace(resolve(pos), hintfmt("while checking the overlay '%s'", attrPath)); reportError(e); } }; - auto checkModule = [&](const std::string & attrPath, Value & v, const Pos & pos) { + auto checkModule = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { state->forceValue(v, pos); if (v.isLambda()) { @@ -382,9 +386,11 @@ struct CmdFlakeCheck : FlakeCommand } else if (v.type() == nAttrs) { for (auto & attr : *v.attrs) try { - state->forceValue(*attr.value, *attr.pos); + state->forceValue(*attr.value, attr.pos); } catch (Error & e) { - e.addTrace(*attr.pos, hintfmt("while evaluating the option '%s'", attr.name)); + e.addTrace( + state->positions[attr.pos], + hintfmt("while evaluating the option '%s'", attr.name)); throw; } } else @@ -392,14 +398,14 @@ struct CmdFlakeCheck : FlakeCommand // FIXME: if we have a 'nixpkgs' input, use it to // check the module. } catch (Error & e) { - e.addTrace(pos, hintfmt("while checking the NixOS module '%s'", attrPath)); + e.addTrace(resolve(pos), hintfmt("while checking the NixOS module '%s'", attrPath)); reportError(e); } }; - std::function checkHydraJobs; + std::function checkHydraJobs; - checkHydraJobs = [&](const std::string & attrPath, Value & v, const Pos & pos) { + checkHydraJobs = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { state->forceAttrs(v, pos); @@ -407,23 +413,23 @@ struct CmdFlakeCheck : FlakeCommand throw Error("jobset should not be a derivation at top-level"); for (auto & attr : *v.attrs) { - state->forceAttrs(*attr.value, *attr.pos); + state->forceAttrs(*attr.value, attr.pos); auto attrPath2 = attrPath + "." + (std::string) attr.name; if (state->isDerivation(*attr.value)) { Activity act(*logger, lvlChatty, actUnknown, fmt("checking Hydra job '%s'", attrPath2)); - checkDerivation(attrPath2, *attr.value, *attr.pos); + checkDerivation(attrPath2, *attr.value, attr.pos); } else - checkHydraJobs(attrPath2, *attr.value, *attr.pos); + checkHydraJobs(attrPath2, *attr.value, attr.pos); } } catch (Error & e) { - e.addTrace(pos, hintfmt("while checking the Hydra jobset '%s'", attrPath)); + e.addTrace(resolve(pos), hintfmt("while checking the Hydra jobset '%s'", attrPath)); reportError(e); } }; - auto checkNixOSConfiguration = [&](const std::string & attrPath, Value & v, const Pos & pos) { + auto checkNixOSConfiguration = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { Activity act(*logger, lvlChatty, actUnknown, fmt("checking NixOS configuration '%s'", attrPath)); @@ -433,12 +439,12 @@ struct CmdFlakeCheck : FlakeCommand if (!state->isDerivation(*vToplevel)) throw Error("attribute 'config.system.build.toplevel' is not a derivation"); } catch (Error & e) { - e.addTrace(pos, hintfmt("while checking the NixOS configuration '%s'", attrPath)); + e.addTrace(resolve(pos), hintfmt("while checking the NixOS configuration '%s'", attrPath)); reportError(e); } }; - auto checkTemplate = [&](const std::string & attrPath, Value & v, const Pos & pos) { + auto checkTemplate = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { Activity act(*logger, lvlChatty, actUnknown, fmt("checking template '%s'", attrPath)); @@ -448,7 +454,7 @@ struct CmdFlakeCheck : FlakeCommand if (auto attr = v.attrs->get(state->symbols.create("path"))) { if (attr->name == state->symbols.create("path")) { PathSet context; - auto path = state->coerceToPath(*attr->pos, *attr->value, context); + auto path = state->coerceToPath(attr->pos, *attr->value, context); if (!store->isInStore(path)) throw Error("template '%s' has a bad 'path' attribute"); // TODO: recursively check the flake in 'path'. @@ -457,7 +463,7 @@ struct CmdFlakeCheck : FlakeCommand throw Error("template '%s' lacks attribute 'path'", attrPath); if (auto attr = v.attrs->get(state->symbols.create("description"))) - state->forceStringNoCtx(*attr->value, *attr->pos); + state->forceStringNoCtx(*attr->value, attr->pos); else throw Error("template '%s' lacks attribute 'description'", attrPath); @@ -467,19 +473,19 @@ struct CmdFlakeCheck : FlakeCommand throw Error("template '%s' has unsupported attribute '%s'", attrPath, name); } } catch (Error & e) { - e.addTrace(pos, hintfmt("while checking the template '%s'", attrPath)); + e.addTrace(resolve(pos), hintfmt("while checking the template '%s'", attrPath)); reportError(e); } }; - auto checkBundler = [&](const std::string & attrPath, Value & v, const Pos & pos) { + auto checkBundler = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { state->forceValue(v, pos); if (!v.isLambda()) throw Error("bundler must be a function"); // TODO: check types of inputs/outputs? } catch (Error & e) { - e.addTrace(pos, hintfmt("while checking the template '%s'", attrPath)); + e.addTrace(resolve(pos), hintfmt("while checking the template '%s'", attrPath)); reportError(e); } }; @@ -492,7 +498,7 @@ struct CmdFlakeCheck : FlakeCommand enumerateOutputs(*state, *vFlake, - [&](const std::string & name, Value & vOutput, const Pos & pos) { + [&](const std::string & name, Value & vOutput, const PosIdx pos) { Activity act(*logger, lvlChatty, actUnknown, fmt("checking flake output '%s'", name)); @@ -516,12 +522,12 @@ struct CmdFlakeCheck : FlakeCommand if (name == "checks") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, *attr.pos); - state->forceAttrs(*attr.value, *attr.pos); + checkSystemName(attr.name, attr.pos); + state->forceAttrs(*attr.value, attr.pos); for (auto & attr2 : *attr.value->attrs) { auto drvPath = checkDerivation( fmt("%s.%s.%s", name, attr.name, attr2.name), - *attr2.value, *attr2.pos); + *attr2.value, attr2.pos); if (drvPath && (std::string) attr.name == settings.thisSystem.get()) drvPaths.push_back(DerivedPath::Built{*drvPath}); } @@ -531,61 +537,61 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "formatter") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, *attr.pos); + checkSystemName(attr.name, attr.pos); checkApp( fmt("%s.%s", name, attr.name), - *attr.value, *attr.pos); + *attr.value, attr.pos); } } else if (name == "packages" || name == "devShells") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, *attr.pos); - state->forceAttrs(*attr.value, *attr.pos); + checkSystemName(attr.name, attr.pos); + state->forceAttrs(*attr.value, attr.pos); for (auto & attr2 : *attr.value->attrs) checkDerivation( fmt("%s.%s.%s", name, attr.name, attr2.name), - *attr2.value, *attr2.pos); + *attr2.value, attr2.pos); } } else if (name == "apps") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, *attr.pos); - state->forceAttrs(*attr.value, *attr.pos); + checkSystemName(attr.name, attr.pos); + state->forceAttrs(*attr.value, attr.pos); for (auto & attr2 : *attr.value->attrs) checkApp( fmt("%s.%s.%s", name, attr.name, attr2.name), - *attr2.value, *attr2.pos); + *attr2.value, attr2.pos); } } else if (name == "defaultPackage" || name == "devShell") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, *attr.pos); + checkSystemName(attr.name, attr.pos); checkDerivation( fmt("%s.%s", name, attr.name), - *attr.value, *attr.pos); + *attr.value, attr.pos); } } else if (name == "defaultApp") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, *attr.pos); + checkSystemName(attr.name, attr.pos); checkApp( fmt("%s.%s", name, attr.name), - *attr.value, *attr.pos); + *attr.value, attr.pos); } } else if (name == "legacyPackages") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, *attr.pos); + checkSystemName(attr.name, attr.pos); // FIXME: do getDerivations? } } @@ -597,7 +603,7 @@ struct CmdFlakeCheck : FlakeCommand state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) checkOverlay(fmt("%s.%s", name, attr.name), - *attr.value, *attr.pos); + *attr.value, attr.pos); } else if (name == "nixosModule") @@ -607,14 +613,14 @@ struct CmdFlakeCheck : FlakeCommand state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) checkModule(fmt("%s.%s", name, attr.name), - *attr.value, *attr.pos); + *attr.value, attr.pos); } else if (name == "nixosConfigurations") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) checkNixOSConfiguration(fmt("%s.%s", name, attr.name), - *attr.value, *attr.pos); + *attr.value, attr.pos); } else if (name == "hydraJobs") @@ -627,28 +633,28 @@ struct CmdFlakeCheck : FlakeCommand state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) checkTemplate(fmt("%s.%s", name, attr.name), - *attr.value, *attr.pos); + *attr.value, attr.pos); } else if (name == "defaultBundler") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, *attr.pos); + checkSystemName(attr.name, attr.pos); checkBundler( fmt("%s.%s", name, attr.name), - *attr.value, *attr.pos); + *attr.value, attr.pos); } } else if (name == "bundlers") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, *attr.pos); - state->forceAttrs(*attr.value, *attr.pos); + checkSystemName(attr.name, attr.pos); + state->forceAttrs(*attr.value, attr.pos); for (auto & attr2 : *attr.value->attrs) { checkBundler( fmt("%s.%s.%s", name, attr.name, attr2.name), - *attr2.value, *attr2.pos); + *attr2.value, attr2.pos); } } } @@ -657,7 +663,7 @@ struct CmdFlakeCheck : FlakeCommand warn("unknown flake output '%s'", name); } catch (Error & e) { - e.addTrace(pos, hintfmt("while checking flake output '%s'", name)); + e.addTrace(resolve(pos), hintfmt("while checking flake output '%s'", name)); reportError(e); } }); diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 391255ce9..fd1b95afa 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -467,7 +467,8 @@ bool NixRepl::processLine(std::string line) auto filename = state->coerceToString(noPos, v, context); return {state->symbols.create(*filename), 0}; } else if (v.isLambda()) { - return {v.lambda.fun->pos.file, v.lambda.fun->pos.line}; + auto pos = state->positions[v.lambda.fun->pos]; + return {pos.file, pos.line}; } else { // assume it's a derivation return findPackageFilename(*state, v, arg); @@ -498,7 +499,7 @@ bool NixRepl::processLine(std::string line) Value v, f, result; evalString(arg, v); evalString("drv: (import {}).runCommand \"shell\" { buildInputs = [ drv ]; } \"\"", f); - state->callFunction(f, v, result, Pos()); + state->callFunction(f, v, result, PosIdx()); StorePath drvPath = getDerivationPath(result); runNix("nix-shell", {state->store->printStorePath(drvPath)}); @@ -799,7 +800,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m Bindings::iterator i = v.attrs->find(state->sDrvPath); PathSet context; if (i != v.attrs->end()) - str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context)); + str << state->store->printStorePath(state->coerceToStorePath(i->pos, *i->value, context)); else str << "???"; str << "»"; @@ -861,7 +862,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m case nFunction: if (v.isLambda()) { std::ostringstream s; - s << v.lambda.fun->pos; + s << state->positions[v.lambda.fun->pos]; str << ANSI_BLUE "«lambda @ " << filterANSIEscapes(s.str()) << "»" ANSI_NORMAL; } else if (v.isPrimOp()) { str << ANSI_MAGENTA "«primop»" ANSI_NORMAL; -- cgit v1.2.3 From 8775be33931ec3b1cad97035ff3d5370a97178a1 Mon Sep 17 00:00:00 2001 From: pennae Date: Sat, 5 Mar 2022 14:40:24 +0100 Subject: store Symbols in a table as well, like positions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this slightly increases the amount of memory used for any given symbol, but this increase is more than made up for if the symbol is referenced more than once in the EvalState that holds it. on average every symbol should be referenced at least twice (once to introduce a binding, once to use it), so we expect no increase in memory on average. symbol tables are limited to 2³² entries like position tables, and similar arguments apply to why overflow is not likely: 2³² symbols would require as many string instances (at 24 bytes each) and map entries (at 24 bytes or more each, assuming that the map holds on average at most one item per bucket as the docs say). a full symbol table would require at least 192GB of memory just for symbols, which is well out of reach. (an ofborg eval of nixpks today creates less than a million symbols!) --- src/nix/app.cc | 6 ++--- src/nix/eval.cc | 14 +++++----- src/nix/flake.cc | 80 ++++++++++++++++++++++++++++++------------------------- src/nix/main.cc | 2 +- src/nix/repl.cc | 21 ++++++++------- src/nix/search.cc | 2 +- 6 files changed, 68 insertions(+), 57 deletions(-) (limited to 'src/nix') diff --git a/src/nix/app.cc b/src/nix/app.cc index df7303e15..95ac1cf5c 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -85,9 +85,9 @@ UnresolvedApp Installable::toApp(EvalState & state) else if (type == "derivation") { auto drvPath = cursor->forceDerivation(); - auto outPath = cursor->getAttr(state.sOutPath)->getString(); - auto outputName = cursor->getAttr(state.sOutputName)->getString(); - auto name = cursor->getAttr(state.sName)->getString(); + auto outPath = cursor->getAttr("outPath")->getString(); + auto outputName = cursor->getAttr("outputName")->getString(); + auto name = cursor->getAttr("name")->getString(); auto aPname = cursor->maybeGetAttr("pname"); auto aMeta = cursor->maybeGetAttr("meta"); auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr; diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 81474c2d3..967dc8519 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -88,17 +88,19 @@ struct CmdEval : MixJSON, InstallableCommand else if (v.type() == nAttrs) { if (mkdir(path.c_str(), 0777) == -1) throw SysError("creating directory '%s'", path); - for (auto & attr : *v.attrs) + for (auto & attr : *v.attrs) { + std::string_view name = state->symbols[attr.name]; try { - if (attr.name == "." || attr.name == "..") - throw Error("invalid file name '%s'", attr.name); - recurse(*attr.value, attr.pos, path + "/" + std::string(attr.name)); + if (name == "." || name == "..") + throw Error("invalid file name '%s'", name); + recurse(*attr.value, attr.pos, concatStrings(path, "/", name)); } catch (Error & e) { e.addTrace( state->positions[attr.pos], - hintfmt("while evaluating the attribute '%s'", attr.name)); + hintfmt("while evaluating the attribute '%s'", name)); throw; } + } } else throw TypeError("value at '%s' is not a string or an attribute set", state->positions[pos]); @@ -119,7 +121,7 @@ struct CmdEval : MixJSON, InstallableCommand else { state->forceValueDeep(*v); - logger->cout("%s", *v); + logger->cout("%s", printValue(*state, *v)); } } }; diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 23e5cd24e..c8d8461e4 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -139,11 +139,11 @@ static void enumerateOutputs(EvalState & state, Value & vFlake, else. This way we can disable IFD for hydraJobs and then enable it for other outputs. */ if (auto attr = aOutputs->value->attrs->get(sHydraJobs)) - callback(attr->name, *attr->value, attr->pos); + callback(state.symbols[attr->name], *attr->value, attr->pos); for (auto & attr : *aOutputs->value->attrs) { if (attr.name != sHydraJobs) - callback(attr.name, *attr.value, attr.pos); + callback(state.symbols[attr.name], *attr.value, attr.pos); } } @@ -254,14 +254,6 @@ struct CmdFlakeInfo : CmdFlakeMetadata } }; -static bool argHasName(std::string_view arg, std::string_view expected) -{ - return - arg == expected - || arg == "_" - || (hasPrefix(arg, "_") && arg.substr(1) == expected); -} - struct CmdFlakeCheck : FlakeCommand { bool build = true; @@ -319,6 +311,14 @@ struct CmdFlakeCheck : FlakeCommand return state->positions[p]; }; + auto argHasName = [&] (SymbolIdx arg, std::string_view expected) { + std::string_view name = state->symbols[arg]; + return + name == expected + || name == "_" + || (hasPrefix(name, "_") && name.substr(1) == expected); + }; + auto checkSystemName = [&](const std::string & system, const PosIdx pos) { // FIXME: what's the format of "system"? if (system.find('-') == std::string::npos) @@ -390,7 +390,7 @@ struct CmdFlakeCheck : FlakeCommand } catch (Error & e) { e.addTrace( state->positions[attr.pos], - hintfmt("while evaluating the option '%s'", attr.name)); + hintfmt("while evaluating the option '%s'", state->symbols[attr.name])); throw; } } else @@ -414,7 +414,7 @@ struct CmdFlakeCheck : FlakeCommand for (auto & attr : *v.attrs) { state->forceAttrs(*attr.value, attr.pos); - auto attrPath2 = attrPath + "." + (std::string) attr.name; + auto attrPath2 = concatStrings(attrPath, ".", state->symbols[attr.name]); if (state->isDerivation(*attr.value)) { Activity act(*logger, lvlChatty, actUnknown, fmt("checking Hydra job '%s'", attrPath2)); @@ -468,7 +468,7 @@ struct CmdFlakeCheck : FlakeCommand throw Error("template '%s' lacks attribute 'description'", attrPath); for (auto & attr : *v.attrs) { - std::string name(attr.name); + std::string_view name(state->symbols[attr.name]); if (name != "path" && name != "description" && name != "welcomeText") throw Error("template '%s' has unsupported attribute '%s'", attrPath, name); } @@ -522,13 +522,14 @@ struct CmdFlakeCheck : FlakeCommand if (name == "checks") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, attr.pos); + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); state->forceAttrs(*attr.value, attr.pos); for (auto & attr2 : *attr.value->attrs) { auto drvPath = checkDerivation( - fmt("%s.%s.%s", name, attr.name, attr2.name), + fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), *attr2.value, attr2.pos); - if (drvPath && (std::string) attr.name == settings.thisSystem.get()) + if (drvPath && attr_name == settings.thisSystem.get()) drvPaths.push_back(DerivedPath::Built{*drvPath}); } } @@ -537,9 +538,10 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "formatter") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, attr.pos); + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); checkApp( - fmt("%s.%s", name, attr.name), + fmt("%s.%s", name, attr_name), *attr.value, attr.pos); } } @@ -547,11 +549,12 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "packages" || name == "devShells") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, attr.pos); + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); state->forceAttrs(*attr.value, attr.pos); for (auto & attr2 : *attr.value->attrs) checkDerivation( - fmt("%s.%s.%s", name, attr.name, attr2.name), + fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), *attr2.value, attr2.pos); } } @@ -559,11 +562,12 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "apps") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, attr.pos); + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); state->forceAttrs(*attr.value, attr.pos); for (auto & attr2 : *attr.value->attrs) checkApp( - fmt("%s.%s.%s", name, attr.name, attr2.name), + fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), *attr2.value, attr2.pos); } } @@ -571,9 +575,10 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "defaultPackage" || name == "devShell") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, attr.pos); + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); checkDerivation( - fmt("%s.%s", name, attr.name), + fmt("%s.%s", name, attr_name), *attr.value, attr.pos); } } @@ -581,9 +586,10 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "defaultApp") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, attr.pos); + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); checkApp( - fmt("%s.%s", name, attr.name), + fmt("%s.%s", name, attr_name), *attr.value, attr.pos); } } @@ -591,7 +597,7 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "legacyPackages") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, attr.pos); + checkSystemName(state->symbols[attr.name], attr.pos); // FIXME: do getDerivations? } } @@ -602,7 +608,7 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "overlays") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) - checkOverlay(fmt("%s.%s", name, attr.name), + checkOverlay(fmt("%s.%s", name, state->symbols[attr.name]), *attr.value, attr.pos); } @@ -612,14 +618,14 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "nixosModules") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) - checkModule(fmt("%s.%s", name, attr.name), + checkModule(fmt("%s.%s", name, state->symbols[attr.name]), *attr.value, attr.pos); } else if (name == "nixosConfigurations") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) - checkNixOSConfiguration(fmt("%s.%s", name, attr.name), + checkNixOSConfiguration(fmt("%s.%s", name, state->symbols[attr.name]), *attr.value, attr.pos); } @@ -632,16 +638,17 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "templates") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) - checkTemplate(fmt("%s.%s", name, attr.name), + checkTemplate(fmt("%s.%s", name, state->symbols[attr.name]), *attr.value, attr.pos); } else if (name == "defaultBundler") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, attr.pos); + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); checkBundler( - fmt("%s.%s", name, attr.name), + fmt("%s.%s", name, attr_name), *attr.value, attr.pos); } } @@ -649,11 +656,12 @@ struct CmdFlakeCheck : FlakeCommand else if (name == "bundlers") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { - checkSystemName(attr.name, attr.pos); + const auto & attr_name = state->symbols[attr.name]; + checkSystemName(attr_name, attr.pos); state->forceAttrs(*attr.value, attr.pos); for (auto & attr2 : *attr.value->attrs) { checkBundler( - fmt("%s.%s.%s", name, attr.name, attr2.name), + fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), *attr2.value, attr2.pos); } } @@ -1000,7 +1008,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto showDerivation = [&]() { - auto name = visitor.getAttr(state->sName)->getString(); + auto name = visitor.getAttr("name")->getString(); if (json) { std::optional description; if (auto aMeta = visitor.maybeGetAttr("meta")) { diff --git a/src/nix/main.cc b/src/nix/main.cc index 6198681e7..6d0f6ce6e 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -302,7 +302,7 @@ void mainWrapped(int argc, char * * argv) b["arity"] = primOp->arity; b["args"] = primOp->args; b["doc"] = trim(stripIndentation(primOp->doc)); - res[(std::string) builtin.name] = std::move(b); + res[state.symbols[builtin.name]] = std::move(b); } std::cout << res.dump() << "\n"; return; diff --git a/src/nix/repl.cc b/src/nix/repl.cc index fd1b95afa..998ff7328 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -73,7 +73,7 @@ struct NixRepl void initEnv(); void reloadFiles(); void addAttrsToScope(Value & attrs); - void addVarToScope(const Symbol & name, Value & v); + void addVarToScope(const SymbolIdx name, Value & v); Expr * parseString(std::string s); void evalString(std::string s, Value & v); @@ -347,9 +347,9 @@ StringSet NixRepl::completePrefix(const std::string & prefix) state->forceAttrs(v, noPos); for (auto & i : *v.attrs) { - std::string name = i.name; + std::string_view name = state->symbols[i.name]; if (name.substr(0, cur2.size()) != cur2) continue; - completions.insert(prev + expr + "." + name); + completions.insert(concatStrings(prev, expr, ".", name)); } } catch (ParseError & e) { @@ -464,8 +464,9 @@ bool NixRepl::processLine(std::string line) const auto [file, line] = [&] () -> std::pair { if (v.type() == nPath || v.type() == nString) { PathSet context; - auto filename = state->coerceToString(noPos, v, context); - return {state->symbols.create(*filename), 0}; + auto filename = state->coerceToString(noPos, v, context).toOwned(); + state->symbols.create(filename); + return {filename, 0}; } else if (v.isLambda()) { auto pos = state->positions[v.lambda.fun->pos]; return {pos.file, pos.line}; @@ -672,7 +673,7 @@ void NixRepl::initEnv() varNames.clear(); for (auto & i : state->staticBaseEnv.vars) - varNames.insert(i.first); + varNames.emplace(state->symbols[i.first]); } @@ -702,7 +703,7 @@ void NixRepl::addAttrsToScope(Value & attrs) for (auto & i : *attrs.attrs) { staticEnv.vars.emplace_back(i.name, displ); env->values[displ++] = i.value; - varNames.insert((std::string) i.name); + varNames.emplace(state->symbols[i.name]); } staticEnv.sort(); staticEnv.deduplicate(); @@ -710,7 +711,7 @@ void NixRepl::addAttrsToScope(Value & attrs) } -void NixRepl::addVarToScope(const Symbol & name, Value & v) +void NixRepl::addVarToScope(const SymbolIdx name, Value & v) { if (displ >= envSize) throw Error("environment full; cannot add more variables"); @@ -719,7 +720,7 @@ void NixRepl::addVarToScope(const Symbol & name, Value & v) staticEnv.vars.emplace_back(name, displ); staticEnv.sort(); env->values[displ++] = &v; - varNames.insert((std::string) name); + varNames.emplace(state->symbols[name]); } @@ -812,7 +813,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m typedef std::map Sorted; Sorted sorted; for (auto & i : *v.attrs) - sorted[i.name] = i.value; + sorted.emplace(state->symbols[i.name], i.value); for (auto & i : sorted) { if (isVarName(i.first)) diff --git a/src/nix/search.cc b/src/nix/search.cc index e284de95c..8b1e9ae6c 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -154,7 +154,7 @@ struct CmdSearch : InstallableCommand, MixJSON recurse(); else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) { - auto attr = cursor.maybeGetAttr(state->sRecurseForDerivations); + auto attr = cursor.maybeGetAttr("recurseForDerivations"); if (attr && attr->getBool()) recurse(); } -- cgit v1.2.3 From a385e51a086006c0f7d7c4bc6ed910dbe5375c4d Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 22 Apr 2022 21:45:39 +0200 Subject: rename SymbolIdx -> Symbol, Symbol -> SymbolStr after #6218 `Symbol` no longer confers a uniqueness invariant on the string it wraps, it is now possible to create multiple symbols that compare equal but whose string contents have different addresses. this guarantee is now only provided by `SymbolIdx`, leaving `Symbol` only as a string wrapper that knows about the intricacies of how symbols need to be formatted for output. this change renames `SymbolIdx` to `Symbol` to restore the previous semantics of `Symbol` to that name. we also keep the wrapper type and rename it to `SymbolStr` instead of returning plain strings from lookups into the symbol table because symbols are formatted for output in many places. theoretically we do not need `SymbolStr`, only a function that formats a string for output as a symbol, but having to wrap every symbol that appears in a message into eg `formatSymbol()` is error-prone and inconvient. --- src/nix/app.cc | 2 +- src/nix/flake.cc | 74 +++++++++++++++++++++++++++++-------------------------- src/nix/repl.cc | 4 +-- src/nix/search.cc | 16 ++++++------ 4 files changed, 51 insertions(+), 45 deletions(-) (limited to 'src/nix') diff --git a/src/nix/app.cc b/src/nix/app.cc index 95ac1cf5c..eec53ad7c 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -66,7 +66,7 @@ UnresolvedApp Installable::toApp(EvalState & state) auto type = cursor->getAttr("type")->getString(); - std::string expected = !attrPath.empty() && attrPath[0] == "apps" ? "app" : "derivation"; + std::string expected = !attrPath.empty() && state.symbols[attrPath[0]] == "apps" ? "app" : "derivation"; if (type != expected) throw Error("attribute '%s' should have type '%s'", cursor->getAttrPathStr(), expected); diff --git a/src/nix/flake.cc b/src/nix/flake.cc index c8d8461e4..2c4a64c85 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -311,7 +311,7 @@ struct CmdFlakeCheck : FlakeCommand return state->positions[p]; }; - auto argHasName = [&] (SymbolIdx arg, std::string_view expected) { + auto argHasName = [&] (Symbol arg, std::string_view expected) { std::string_view name = state->symbols[arg]; return name == expected @@ -986,8 +986,11 @@ struct CmdFlakeShow : FlakeCommand, MixJSON { auto j = nlohmann::json::object(); + auto attrPathS = state->symbols.resolve(attrPath); + Activity act(*logger, lvlInfo, actUnknown, - fmt("evaluating '%s'", concatStringsSep(".", attrPath))); + fmt("evaluating '%s'", concatStringsSep(".", attrPathS))); + try { auto recurse = [&]() { @@ -995,14 +998,15 @@ struct CmdFlakeShow : FlakeCommand, MixJSON logger->cout("%s", headerPrefix); auto attrs = visitor.getAttrs(); for (const auto & [i, attr] : enumerate(attrs)) { + const auto & attrName = state->symbols[attr]; bool last = i + 1 == attrs.size(); - auto visitor2 = visitor.getAttr(attr); + auto visitor2 = visitor.getAttr(attrName); auto attrPath2(attrPath); attrPath2.push_back(attr); auto j2 = visit(*visitor2, attrPath2, - fmt(ANSI_GREEN "%s%s" ANSI_NORMAL ANSI_BOLD "%s" ANSI_NORMAL, nextPrefix, last ? treeLast : treeConn, attr), + fmt(ANSI_GREEN "%s%s" ANSI_NORMAL ANSI_BOLD "%s" ANSI_NORMAL, nextPrefix, last ? treeLast : treeConn, attrName), nextPrefix + (last ? treeNull : treeLine)); - if (json) j.emplace(attr, std::move(j2)); + if (json) j.emplace(attrName, std::move(j2)); } }; @@ -1022,10 +1026,10 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } else { logger->cout("%s: %s '%s'", headerPrefix, - attrPath.size() == 2 && attrPath[0] == "devShell" ? "development environment" : - attrPath.size() >= 2 && attrPath[0] == "devShells" ? "development environment" : - attrPath.size() == 3 && attrPath[0] == "checks" ? "derivation" : - attrPath.size() >= 1 && attrPath[0] == "hydraJobs" ? "derivation" : + attrPath.size() == 2 && attrPathS[0] == "devShell" ? "development environment" : + attrPath.size() >= 2 && attrPathS[0] == "devShells" ? "development environment" : + attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" : + attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" : "package", name); } @@ -1033,27 +1037,27 @@ struct CmdFlakeShow : FlakeCommand, MixJSON if (attrPath.size() == 0 || (attrPath.size() == 1 && ( - attrPath[0] == "defaultPackage" - || attrPath[0] == "devShell" - || attrPath[0] == "formatter" - || attrPath[0] == "nixosConfigurations" - || attrPath[0] == "nixosModules" - || attrPath[0] == "defaultApp" - || attrPath[0] == "templates" - || attrPath[0] == "overlays")) + attrPathS[0] == "defaultPackage" + || attrPathS[0] == "devShell" + || attrPathS[0] == "formatter" + || attrPathS[0] == "nixosConfigurations" + || attrPathS[0] == "nixosModules" + || attrPathS[0] == "defaultApp" + || attrPathS[0] == "templates" + || attrPathS[0] == "overlays")) || ((attrPath.size() == 1 || attrPath.size() == 2) - && (attrPath[0] == "checks" - || attrPath[0] == "packages" - || attrPath[0] == "devShells" - || attrPath[0] == "apps")) + && (attrPathS[0] == "checks" + || attrPathS[0] == "packages" + || attrPathS[0] == "devShells" + || attrPathS[0] == "apps")) ) { recurse(); } else if ( - (attrPath.size() == 2 && (attrPath[0] == "defaultPackage" || attrPath[0] == "devShell" || attrPath[0] == "formatter")) - || (attrPath.size() == 3 && (attrPath[0] == "checks" || attrPath[0] == "packages" || attrPath[0] == "devShells")) + (attrPath.size() == 2 && (attrPathS[0] == "defaultPackage" || attrPathS[0] == "devShell" || attrPathS[0] == "formatter")) + || (attrPath.size() == 3 && (attrPathS[0] == "checks" || attrPathS[0] == "packages" || attrPathS[0] == "devShells")) ) { if (visitor.isDerivation()) @@ -1062,14 +1066,14 @@ struct CmdFlakeShow : FlakeCommand, MixJSON throw Error("expected a derivation"); } - else if (attrPath.size() > 0 && attrPath[0] == "hydraJobs") { + else if (attrPath.size() > 0 && attrPathS[0] == "hydraJobs") { if (visitor.isDerivation()) showDerivation(); else recurse(); } - else if (attrPath.size() > 0 && attrPath[0] == "legacyPackages") { + else if (attrPath.size() > 0 && attrPathS[0] == "legacyPackages") { if (attrPath.size() == 1) recurse(); else if (!showLegacy) @@ -1084,8 +1088,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } else if ( - (attrPath.size() == 2 && attrPath[0] == "defaultApp") || - (attrPath.size() == 3 && attrPath[0] == "apps")) + (attrPath.size() == 2 && attrPathS[0] == "defaultApp") || + (attrPath.size() == 3 && attrPathS[0] == "apps")) { auto aType = visitor.maybeGetAttr("type"); if (!aType || aType->getString() != "app") @@ -1098,8 +1102,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } else if ( - (attrPath.size() == 1 && attrPath[0] == "defaultTemplate") || - (attrPath.size() == 2 && attrPath[0] == "templates")) + (attrPath.size() == 1 && attrPathS[0] == "defaultTemplate") || + (attrPath.size() == 2 && attrPathS[0] == "templates")) { auto description = visitor.getAttr("description")->getString(); if (json) { @@ -1112,11 +1116,11 @@ struct CmdFlakeShow : FlakeCommand, MixJSON else { auto [type, description] = - (attrPath.size() == 1 && attrPath[0] == "overlay") - || (attrPath.size() == 2 && attrPath[0] == "overlays") ? std::make_pair("nixpkgs-overlay", "Nixpkgs overlay") : - attrPath.size() == 2 && attrPath[0] == "nixosConfigurations" ? std::make_pair("nixos-configuration", "NixOS configuration") : - (attrPath.size() == 1 && attrPath[0] == "nixosModule") - || (attrPath.size() == 2 && attrPath[0] == "nixosModules") ? std::make_pair("nixos-module", "NixOS module") : + (attrPath.size() == 1 && attrPathS[0] == "overlay") + || (attrPath.size() == 2 && attrPathS[0] == "overlays") ? std::make_pair("nixpkgs-overlay", "Nixpkgs overlay") : + attrPath.size() == 2 && attrPathS[0] == "nixosConfigurations" ? std::make_pair("nixos-configuration", "NixOS configuration") : + (attrPath.size() == 1 && attrPathS[0] == "nixosModule") + || (attrPath.size() == 2 && attrPathS[0] == "nixosModules") ? std::make_pair("nixos-module", "NixOS module") : std::make_pair("unknown", "unknown"); if (json) { j.emplace("type", type); @@ -1125,7 +1129,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } } } catch (EvalError & e) { - if (!(attrPath.size() > 0 && attrPath[0] == "legacyPackages")) + if (!(attrPath.size() > 0 && attrPathS[0] == "legacyPackages")) throw; } diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 998ff7328..2967632ed 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -73,7 +73,7 @@ struct NixRepl void initEnv(); void reloadFiles(); void addAttrsToScope(Value & attrs); - void addVarToScope(const SymbolIdx name, Value & v); + void addVarToScope(const Symbol name, Value & v); Expr * parseString(std::string s); void evalString(std::string s, Value & v); @@ -711,7 +711,7 @@ void NixRepl::addAttrsToScope(Value & attrs) } -void NixRepl::addVarToScope(const SymbolIdx name, Value & v) +void NixRepl::addVarToScope(const Symbol name, Value & v) { if (displ >= envSize) throw Error("environment full; cannot add more variables"); diff --git a/src/nix/search.cc b/src/nix/search.cc index 8b1e9ae6c..6febc0a55 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -77,13 +77,15 @@ struct CmdSearch : InstallableCommand, MixJSON visit = [&](eval_cache::AttrCursor & cursor, const std::vector & attrPath, bool initialRecurse) { + auto attrPathS = state->symbols.resolve(attrPath); + Activity act(*logger, lvlInfo, actUnknown, - fmt("evaluating '%s'", concatStringsSep(".", attrPath))); + fmt("evaluating '%s'", concatStringsSep(".", attrPathS))); try { auto recurse = [&]() { for (const auto & attr : cursor.getAttrs()) { - auto cursor2 = cursor.getAttr(attr); + auto cursor2 = cursor.getAttr(state->symbols[attr]); auto attrPath2(attrPath); attrPath2.push_back(attr); visit(*cursor2, attrPath2, false); @@ -97,7 +99,7 @@ struct CmdSearch : InstallableCommand, MixJSON auto aDescription = aMeta ? aMeta->maybeGetAttr("description") : nullptr; auto description = aDescription ? aDescription->getString() : ""; std::replace(description.begin(), description.end(), '\n', ' '); - auto attrPath2 = concatStringsSep(".", attrPath); + auto attrPath2 = concatStringsSep(".", attrPathS); std::vector attrPathMatches; std::vector descriptionMatches; @@ -146,21 +148,21 @@ struct CmdSearch : InstallableCommand, MixJSON else if ( attrPath.size() == 0 - || (attrPath[0] == "legacyPackages" && attrPath.size() <= 2) - || (attrPath[0] == "packages" && attrPath.size() <= 2)) + || (attrPathS[0] == "legacyPackages" && attrPath.size() <= 2) + || (attrPathS[0] == "packages" && attrPath.size() <= 2)) recurse(); else if (initialRecurse) recurse(); - else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) { + else if (attrPathS[0] == "legacyPackages" && attrPath.size() > 2) { auto attr = cursor.maybeGetAttr("recurseForDerivations"); if (attr && attr->getBool()) recurse(); } } catch (EvalError & e) { - if (!(attrPath.size() > 0 && attrPath[0] == "legacyPackages")) + if (!(attrPath.size() > 0 && attrPathS[0] == "legacyPackages")) throw; } }; -- cgit v1.2.3 From 474695975dde60f582ca0b2fb72c17f664e22876 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 26 Apr 2022 14:01:21 +0200 Subject: EvalCache: Revert to using symbols in getAttr() --- src/nix/app.cc | 6 +++--- src/nix/flake.cc | 2 +- src/nix/search.cc | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nix') diff --git a/src/nix/app.cc b/src/nix/app.cc index eec53ad7c..cce84d026 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -85,9 +85,9 @@ UnresolvedApp Installable::toApp(EvalState & state) else if (type == "derivation") { auto drvPath = cursor->forceDerivation(); - auto outPath = cursor->getAttr("outPath")->getString(); - auto outputName = cursor->getAttr("outputName")->getString(); - auto name = cursor->getAttr("name")->getString(); + auto outPath = cursor->getAttr(state.sOutPath)->getString(); + auto outputName = cursor->getAttr(state.sOutputName)->getString(); + auto name = cursor->getAttr(state.sName)->getString(); auto aPname = cursor->maybeGetAttr("pname"); auto aMeta = cursor->maybeGetAttr("meta"); auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr; diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 2c4a64c85..040c1c7af 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1012,7 +1012,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto showDerivation = [&]() { - auto name = visitor.getAttr("name")->getString(); + auto name = visitor.getAttr(state->sName)->getString(); if (json) { std::optional description; if (auto aMeta = visitor.maybeGetAttr("meta")) { diff --git a/src/nix/search.cc b/src/nix/search.cc index 6febc0a55..76451f810 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -156,7 +156,7 @@ struct CmdSearch : InstallableCommand, MixJSON recurse(); else if (attrPathS[0] == "legacyPackages" && attrPath.size() > 2) { - auto attr = cursor.maybeGetAttr("recurseForDerivations"); + auto attr = cursor.maybeGetAttr(state->sRecurseForDerivations); if (attr && attr->getBool()) recurse(); } -- cgit v1.2.3 From 1ddabe1a0120787ff5bbdba5383222a6eb59c219 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Apr 2022 16:39:47 +0200 Subject: nix: Respect meta.outputsToInstall, and use all outputs by default 'nix profile install' will now install all outputs listed in the package's meta.outputsToInstall attribute, or all outputs if that attribute doesn't exist. This makes it behave consistently with nix-env. Fixes #6385. Furthermore, for consistency, all other 'nix' commands do this as well. E.g. 'nix build' will build and symlink the outputs in meta.outputsToInstall, defaulting to all outputs. Previously, it only built/symlinked the first output. Note that this means that selecting a specific output using attrpath selection (e.g. 'nix build nixpkgs#libxml2.dev') no longer works. A subsequent PR will add a way to specify the desired outputs explicitly. --- src/nix/app.cc | 2 +- src/nix/flake.cc | 4 ++-- src/nix/search.cc | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nix') diff --git a/src/nix/app.cc b/src/nix/app.cc index cce84d026..821964f86 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -89,7 +89,7 @@ UnresolvedApp Installable::toApp(EvalState & state) auto outputName = cursor->getAttr(state.sOutputName)->getString(); auto name = cursor->getAttr(state.sName)->getString(); auto aPname = cursor->maybeGetAttr("pname"); - auto aMeta = cursor->maybeGetAttr("meta"); + auto aMeta = cursor->maybeGetAttr(state.sMeta); auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr; auto mainProgram = aMainProgram diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 040c1c7af..6a34ca67b 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1015,8 +1015,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto name = visitor.getAttr(state->sName)->getString(); if (json) { std::optional description; - if (auto aMeta = visitor.maybeGetAttr("meta")) { - if (auto aDescription = aMeta->maybeGetAttr("description")) + if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) { + if (auto aDescription = aMeta->maybeGetAttr(state->sDescription)) description = aDescription->getString(); } j.emplace("type", "derivation"); diff --git a/src/nix/search.cc b/src/nix/search.cc index 76451f810..87dc1c0de 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -93,10 +93,10 @@ struct CmdSearch : InstallableCommand, MixJSON }; if (cursor.isDerivation()) { - DrvName name(cursor.getAttr("name")->getString()); + DrvName name(cursor.getAttr(state->sName)->getString()); - auto aMeta = cursor.maybeGetAttr("meta"); - auto aDescription = aMeta ? aMeta->maybeGetAttr("description") : nullptr; + auto aMeta = cursor.maybeGetAttr(state->sMeta); + auto aDescription = aMeta ? aMeta->maybeGetAttr(state->sDescription) : nullptr; auto description = aDescription ? aDescription->getString() : ""; std::replace(description.begin(), description.end(), '\n', ' '); auto attrPath2 = concatStringsSep(".", attrPathS); -- cgit v1.2.3 From 13d8400ac511dd36dcfd74c35737d093cf52bba3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Apr 2022 16:51:12 +0200 Subject: Remove obsolete FIXME --- src/nix/profile.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/profile.cc b/src/nix/profile.cc index b151e48d6..52c918016 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -67,7 +67,6 @@ struct ProfileElement ref store, const BuiltPaths & builtPaths) { - // FIXME: respect meta.outputsToInstall storePaths.clear(); for (auto & buildable : builtPaths) { std::visit(overloaded { -- cgit v1.2.3 From acf990c9ea9de913a500cf2b7a7492eef3bcd7b5 Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Thu, 28 Apr 2022 12:54:14 +0200 Subject: fix errors case and wording --- src/nix/flake.cc | 4 ++-- src/nix/main.cc | 2 +- src/nix/prefetch.cc | 16 ++++++++-------- src/nix/repl.cc | 6 +++--- src/nix/upgrade-nix.cc | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 3cf764a20..e835b8052 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -126,12 +126,12 @@ static void enumerateOutputs(EvalState & state, Value & vFlake, std::function callback) { auto pos = vFlake.determinePos(noPos); - state.forceAttrs(vFlake, pos, "While evaluating a flake to get its outputs"); + state.forceAttrs(vFlake, pos, "while evaluating a flake to get its outputs"); auto aOutputs = vFlake.attrs->get(state.symbols.create("outputs")); assert(aOutputs); - state.forceAttrs(*aOutputs->value, pos, "While evaluating the outputs of a flake"); + state.forceAttrs(*aOutputs->value, pos, "while evaluating the outputs of a flake"); auto sHydraJobs = state.symbols.create("hydraJobs"); diff --git a/src/nix/main.cc b/src/nix/main.cc index 0c6286686..0dc14e2e9 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -196,7 +196,7 @@ static void showHelp(std::vector subcommand, MultiCommand & topleve if (!attr) throw UsageError("Nix has no subcommand '%s'", concatStringsSep("", subcommand)); - auto markdown = state.forceString(*attr->value, noPos, "While evaluating the lowdown help text"); + auto markdown = state.forceString(*attr->value, noPos, "while evaluating the lowdown help text"); RunPager pager; std::cout << renderMarkdownToTerminal(markdown) << "\n"; diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index 4376da896..782149575 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -28,17 +28,17 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url) Value vMirrors; // FIXME: use nixpkgs flake state.eval(state.parseExprFromString("import ", "."), vMirrors); - state.forceAttrs(vMirrors, noPos, "While evaluating the set of all mirrors"); + state.forceAttrs(vMirrors, noPos, "while evaluating the set of all mirrors"); auto mirrorList = vMirrors.attrs->find(state.symbols.create(mirrorName)); if (mirrorList == vMirrors.attrs->end()) throw Error("unknown mirror name '%s'", mirrorName); - state.forceList(*mirrorList->value, noPos, "While evaluating this mirror configuration"); + state.forceList(*mirrorList->value, noPos, "while evaluating one mirror configuration"); if (mirrorList->value->listSize() < 1) throw Error("mirror URL '%s' did not expand to anything", url); - std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "While evaluating the first available mirror")); + std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "while evaluating the first available mirror")); return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1); } @@ -196,27 +196,27 @@ static int main_nix_prefetch_url(int argc, char * * argv) Value vRoot; state->evalFile(path, vRoot); Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot).first); - state->forceAttrs(v, noPos, "While evaluating the source attribute to prefetch"); + state->forceAttrs(v, noPos, "while evaluating the source attribute to prefetch"); /* Extract the URL. */ auto & attr = v.attrs->need(state->symbols.create("urls")); - state->forceList(*attr.value, noPos, "While evaluating the urls to prefetch"); + state->forceList(*attr.value, noPos, "while evaluating the urls to prefetch"); if (attr.value->listSize() < 1) throw Error("'urls' list is empty"); - url = state->forceString(*attr.value->listElems()[0], noPos, "While evaluating the first url from the urls list"); + url = state->forceString(*attr.value->listElems()[0], noPos, "while evaluating the first url from the urls list"); /* Extract the hash mode. */ auto attr2 = v.attrs->get(state->symbols.create("outputHashMode")); if (!attr2) printInfo("warning: this does not look like a fetchurl call"); else - unpack = state->forceString(*attr2->value, noPos, "While evaluating the outputHashMode of the source to prefetch") == "recursive"; + unpack = state->forceString(*attr2->value, noPos, "while evaluating the outputHashMode of the source to prefetch") == "recursive"; /* Extract the name. */ if (!name) { auto attr3 = v.attrs->get(state->symbols.create("name")); if (!attr3) - name = state->forceString(*attr3->value, noPos, "While evaluating the name of the source to prefetch"); + name = state->forceString(*attr3->value, noPos, "while evaluating the name of the source to prefetch"); } } diff --git a/src/nix/repl.cc b/src/nix/repl.cc index b4a029ecc..7f7912de3 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -462,7 +462,7 @@ bool NixRepl::processLine(std::string line) if (v.type() == nPath || v.type() == nString) { PathSet context; - auto filename = state->coerceToString(noPos, v, context, "While evaluating the filename to edit"); + auto filename = state->coerceToString(noPos, v, context, "while evaluating the filename to edit"); pos.file = state->symbols.create(*filename); } else if (v.isLambda()) { pos = v.lambda.fun->pos; @@ -683,7 +683,7 @@ void NixRepl::reloadFiles() void NixRepl::addAttrsToScope(Value & attrs) { - state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "While evaluating an attribute set to be merged in the global scope"); + state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "while evaluating an attribute set to be merged in the global scope"); if (displ + attrs.attrs->size() >= envSize) throw Error("environment full; cannot add more variables"); @@ -788,7 +788,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m Bindings::iterator i = v.attrs->find(state->sDrvPath); PathSet context; if (i != v.attrs->end()) - str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context, "While evaluating the drvPath of a derivation")); + str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context, "while evaluating the drvPath of a derivation")); else str << "???"; str << "»"; diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 1f433a199..0c317de16 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -144,7 +144,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand Bindings & bindings(*state->allocBindings(0)); auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v).first; - return store->parseStorePath(state->forceString(*v2, noPos, "While evaluating the path tho latest nix version")); + return store->parseStorePath(state->forceString(*v2, noPos, "while evaluating the path tho latest nix version")); } }; -- cgit v1.2.3 From d77d813017d9bb5c82040d4a7749f80582422d7e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 28 Apr 2022 14:24:17 +0200 Subject: Shut up clang warning --- src/nix/fmt.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/fmt.cc b/src/nix/fmt.cc index e5d44bd38..6f6a4a632 100644 --- a/src/nix/fmt.cc +++ b/src/nix/fmt.cc @@ -26,7 +26,8 @@ struct CmdFmt : SourceExprCommand { Strings getDefaultFlakeAttrPathPrefixes() override { return Strings{}; } - void run(ref store) { + void run(ref store) override + { auto evalState = getEvalState(); auto evalStore = getEvalStore(); -- cgit v1.2.3 From c21afd684cb5f59337b879684728884fd8275ce4 Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Sun, 30 Jan 2022 11:30:57 -0500 Subject: Update `nix flake` documentation of `ref` handling Update the documentation about how `ref` is resolved if it is not specified. Add a note about special handling of local workdirs with `git+file`. --- src/nix/flake.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/flake.md b/src/nix/flake.md index 7d179a6c4..c8251eb74 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -153,7 +153,7 @@ Currently the `type` attribute can be one of the following: git(+http|+https|+ssh|+git|+file|):(//)?(\?)? ``` - The `ref` attribute defaults to `master`. + The `ref` attribute defaults to resolving the `HEAD` reference. The `rev` attribute must denote a commit that exists in the branch or tag specified by the `ref` attribute, since Nix doesn't do a full @@ -161,6 +161,11 @@ Currently the `type` attribute can be one of the following: doesn't allow fetching a `rev` without a known `ref`). The default is the commit currently pointed to by `ref`. + When `git+file` is used without specifying `ref` or `rev`, files are + fetched directly from the local `path` as long as they have been added + to the Git repository. If there are uncommitted changes, the reference + is treated as dirty and a warning is printed. + For example, the following are valid Git flake references: * `git+https://example.org/my/repo` -- cgit v1.2.3 From 4a79cba5118f29b896f3d50164beacd4901ab01f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 22 Apr 2022 15:17:01 +0200 Subject: Allow selecting derivation outputs using 'installable!outputs' E.g. 'nixpkgs#glibc^dev,static' or 'nixpkgs#glibc^*'. --- src/nix/bundle.cc | 4 ++-- src/nix/develop.cc | 1 + src/nix/flake.cc | 2 +- src/nix/nix.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/nix/profile.cc | 1 + 5 files changed, 50 insertions(+), 3 deletions(-) (limited to 'src/nix') diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc index 2421adf4e..2e48e4c74 100644 --- a/src/nix/bundle.cc +++ b/src/nix/bundle.cc @@ -75,10 +75,10 @@ struct CmdBundle : InstallableCommand auto val = installable->toValue(*evalState).first; - auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath(".")); + auto [bundlerFlakeRef, bundlerName, outputsSpec] = parseFlakeRefWithFragmentAndOutputsSpec(bundler, absPath(".")); const flake::LockFlags lockFlags{ .writeLockFile = false }; InstallableFlake bundler{this, - evalState, std::move(bundlerFlakeRef), bundlerName, + evalState, std::move(bundlerFlakeRef), bundlerName, outputsSpec, {"bundlers." + settings.thisSystem.get() + ".default", "defaultBundler." + settings.thisSystem.get() }, diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 7fc74d34e..1190b8348 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -507,6 +507,7 @@ struct CmdDevelop : Common, MixEnvironment state, installable->nixpkgsFlakeRef(), "bashInteractive", + DefaultOutputs(), Strings{}, Strings{"legacyPackages." + settings.thisSystem.get() + "."}, nixpkgsLockFlags); diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 6a34ca67b..1938ce4e6 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -724,7 +724,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(templateUrl, absPath(".")); auto installable = InstallableFlake(nullptr, - evalState, std::move(templateFlakeRef), templateName, + evalState, std::move(templateFlakeRef), templateName, DefaultOutputs(), defaultTemplateAttrPaths, defaultTemplateAttrPathsPrefixes, lockFlags); diff --git a/src/nix/nix.md b/src/nix/nix.md index 0dacadee6..d48682a94 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -146,6 +146,51 @@ For most commands, if no installable is specified, the default is `.`, i.e. Nix will operate on the default flake output attribute of the flake in the current directory. +## Derivation output selection + +Derivations can have multiple outputs, each corresponding to a +different store path. For instance, a package can have a `bin` output +that contains programs, and a `dev` output that provides development +artifacts like C/C++ header files. The outputs on which `nix` commands +operate are determined as follows: + +* You can explicitly specify the desired outputs using the syntax + *installable*`^`*output1*`,`*...*`,`*outputN*. For example, you can + obtain the `dev` and `static` outputs of the `glibc` package: + + ```console + # nix build 'nixpkgs#glibc^dev,static' + # ls ./result-dev/include/ ./result-static/lib/ + … + ``` + +* You can also specify that *all* outputs should be used using the + syntax *installable*`^*`. For example, the following shows the size + of all outputs of the `glibc` package in the binary cache: + + ```console + # nix path-info -S --eval-store auto --store https://cache.nixos.org 'nixpkgs#glibc^*' + /nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123 33208200 + /nix/store/851dp95qqiisjifi639r0zzg5l465ny4-glibc-2.33-123-bin 36142896 + /nix/store/kdgs3q6r7xdff1p7a9hnjr43xw2404z7-glibc-2.33-123-debug 155787312 + /nix/store/n4xa8h6pbmqmwnq0mmsz08l38abb06zc-glibc-2.33-123-static 42488328 + /nix/store/q6580lr01jpcsqs4r5arlh4ki2c1m9rv-glibc-2.33-123-dev 44200560 + ``` + +* If you didn't specify the desired outputs, but the derivation has an + attribute `meta.outputsToInstall`, Nix will use those outputs. For + example, since the package `nixpkgs#libxml2` has this attribute: + + ```console + # nix eval 'nixpkgs#libxml2.meta.outputsToInstall' + [ "bin" "man" ] + ``` + + a command like `nix shell nixpkgs#libxml2` will provide only those + two outputs by default. + +* Otherwise, Nix will use all outputs of the derivation. + # Nix stores Most `nix` subcommands operate on a *Nix store*. diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 52c918016..78c8af80c 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -443,6 +443,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf getEvalState(), FlakeRef(element.source->originalRef), "", + DefaultOutputs(), // FIXME Strings{element.source->attrPath}, Strings{}, lockFlags); -- cgit v1.2.3 From a3c6c5b1c745a72a6a46bdf1a1de7a51a53f76b0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 3 May 2022 14:37:28 +0200 Subject: nix profile: Support overriding outputs --- src/nix/profile-install.md | 7 +++++++ src/nix/profile.cc | 30 +++++++++++++++++------------- 2 files changed, 24 insertions(+), 13 deletions(-) (limited to 'src/nix') diff --git a/src/nix/profile-install.md b/src/nix/profile-install.md index e3009491e..aed414963 100644 --- a/src/nix/profile-install.md +++ b/src/nix/profile-install.md @@ -20,6 +20,13 @@ R""( # nix profile install nixpkgs/d73407e8e6002646acfdef0e39ace088bacc83da#hello ``` +* Install a specific output of a package: + + ```console + # nix profile install nixpkgs#bash^man + ``` + + # Description This command adds *installables* to a Nix profile. diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 78c8af80c..685776bec 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -22,13 +22,13 @@ struct ProfileElementSource // FIXME: record original attrpath. FlakeRef resolvedRef; std::string attrPath; - // FIXME: output names + OutputsSpec outputs; bool operator < (const ProfileElementSource & other) const { return - std::pair(originalRef.to_string(), attrPath) < - std::pair(other.originalRef.to_string(), other.attrPath); + std::tuple(originalRef.to_string(), attrPath, outputs) < + std::tuple(other.originalRef.to_string(), other.attrPath, other.outputs); } }; @@ -42,7 +42,7 @@ struct ProfileElement std::string describe() const { if (source) - return fmt("%s#%s", source->originalRef, source->attrPath); + return fmt("%s#%s%s", source->originalRef, source->attrPath, printOutputsSpec(source->outputs)); StringSet names; for (auto & path : storePaths) names.insert(DrvName(path.name()).name); @@ -98,7 +98,7 @@ struct ProfileManifest auto version = json.value("version", 0); std::string sUrl; std::string sOriginalUrl; - switch(version){ + switch (version) { case 1: sUrl = "uri"; sOriginalUrl = "originalUri"; @@ -116,11 +116,12 @@ struct ProfileManifest for (auto & p : e["storePaths"]) element.storePaths.insert(state.store->parseStorePath((std::string) p)); element.active = e["active"]; - if (e.value(sUrl,"") != "") { - element.source = ProfileElementSource{ + if (e.value(sUrl, "") != "") { + element.source = ProfileElementSource { parseFlakeRef(e[sOriginalUrl]), parseFlakeRef(e[sUrl]), - e["attrPath"] + e["attrPath"], + e["outputs"].get() }; } elements.emplace_back(std::move(element)); @@ -156,6 +157,7 @@ struct ProfileManifest obj["originalUrl"] = element.source->originalRef.to_string(); obj["url"] = element.source->resolvedRef.to_string(); obj["attrPath"] = element.source->attrPath; + obj["outputs"] = element.source->outputs; } array.push_back(obj); } @@ -283,10 +285,11 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile if (auto installable2 = std::dynamic_pointer_cast(installable)) { // FIXME: make build() return this? auto [attrPath, resolvedRef, drv] = installable2->toDerivation(); - element.source = ProfileElementSource{ + element.source = ProfileElementSource { installable2->flakeRef, resolvedRef, attrPath, + installable2->outputsSpec }; } @@ -443,7 +446,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf getEvalState(), FlakeRef(element.source->originalRef), "", - DefaultOutputs(), // FIXME + element.source->outputs, Strings{element.source->attrPath}, Strings{}, lockFlags); @@ -455,10 +458,11 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf printInfo("upgrading '%s' from flake '%s' to '%s'", element.source->attrPath, element.source->resolvedRef, resolvedRef); - element.source = ProfileElementSource{ + element.source = ProfileElementSource { installable->flakeRef, resolvedRef, attrPath, + installable->outputsSpec }; installables.push_back(installable); @@ -514,8 +518,8 @@ struct CmdProfileList : virtual EvalCommand, virtual StoreCommand, MixDefaultPro for (size_t i = 0; i < manifest.elements.size(); ++i) { auto & element(manifest.elements[i]); logger->cout("%d %s %s %s", i, - element.source ? element.source->originalRef.to_string() + "#" + element.source->attrPath : "-", - element.source ? element.source->resolvedRef.to_string() + "#" + element.source->attrPath : "-", + element.source ? element.source->originalRef.to_string() + "#" + element.source->attrPath + printOutputsSpec(element.source->outputs) : "-", + element.source ? element.source->resolvedRef.to_string() + "#" + element.source->attrPath + printOutputsSpec(element.source->outputs) : "-", concatStringsSep(" ", store->printStorePathSet(element.storePaths))); } } -- cgit v1.2.3 From a9cbc2857f4dd3af738b76edea00d692fbcee63c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 10 May 2022 16:42:35 +0200 Subject: nix develop: Find bin/bash in the bashInteractive outputs --- src/nix/develop.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src/nix') diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 1190b8348..3a99fff6f 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -512,9 +512,20 @@ struct CmdDevelop : Common, MixEnvironment Strings{"legacyPackages." + settings.thisSystem.get() + "."}, nixpkgsLockFlags); - shell = store->printStorePath( - Installable::toStorePath(getEvalStore(), store, Realise::Outputs, OperateOn::Output, bashInstallable)) - + "/bin/bash"; + bool found = false; + + for (auto & path : Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, {bashInstallable})) { + auto s = store->printStorePath(path) + "/bin/bash"; + if (pathExists(s)) { + shell = s; + found = true; + break; + } + } + + if (!found) + throw Error("package 'nixpkgs#bashInteractive' does not provide a 'bin/bash'"); + } catch (Error &) { ignoreException(); } -- cgit v1.2.3 From 2998527b185a41157be6ead42fd03a66601c4f56 Mon Sep 17 00:00:00 2001 From: Jimmy Reichley Date: Tue, 10 May 2022 16:53:22 -0400 Subject: Allow setting bash-prompt-prefix nix develop configuration --- src/nix/develop.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/nix') diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 3a99fff6f..2a3fc0213 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -18,6 +18,9 @@ struct DevelopSettings : Config Setting bashPrompt{this, "", "bash-prompt", "The bash prompt (`PS1`) in `nix develop` shells."}; + Setting bashPromptPrefix{this, "", "bash-prompt-prefix", + "Prefix prepended to the `PS1` environment variable in `nix develop` shells."}; + Setting bashPromptSuffix{this, "", "bash-prompt-suffix", "Suffix appended to the `PS1` environment variable in `nix develop` shells."}; }; @@ -482,6 +485,9 @@ struct CmdDevelop : Common, MixEnvironment if (developSettings.bashPrompt != "") script += fmt("[ -n \"$PS1\" ] && PS1=%s;\n", shellEscape(developSettings.bashPrompt.get())); + if (developSettings.bashPromptPrefix != "") + script += fmt("[ -n \"$PS1\" ] && PS1=%s\"$PS1\";\n", + shellEscape(developSettings.bashPromptPrefix.get())); if (developSettings.bashPromptSuffix != "") script += fmt("[ -n \"$PS1\" ] && PS1+=%s;\n", shellEscape(developSettings.bashPromptSuffix.get())); -- cgit v1.2.3 From 584475acf9f4b8eda2a451901f6f9af35ae976e0 Mon Sep 17 00:00:00 2001 From: Jimmy Reichley Date: Tue, 10 May 2022 16:55:25 -0400 Subject: Add documentation for bash-prompt-prefix --- src/nix/develop.md | 4 ++-- src/nix/flake.md | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src/nix') diff --git a/src/nix/develop.md b/src/nix/develop.md index 8bcff66c9..e036ec6b9 100644 --- a/src/nix/develop.md +++ b/src/nix/develop.md @@ -80,8 +80,8 @@ initialised by `stdenv` and exits. This build environment can be recorded into a profile using `--profile`. The prompt used by the `bash` shell can be customised by setting the -`bash-prompt` and `bash-prompt-suffix` settings in `nix.conf` or in -the flake's `nixConfig` attribute. +`bash-prompt`, `bash-prompt-prefix`, and `bash-prompt-suffix` settings in +`nix.conf` or in the flake's `nixConfig` attribute. # Flake output attributes diff --git a/src/nix/flake.md b/src/nix/flake.md index c8251eb74..aa3f9f303 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -331,9 +331,10 @@ The following attributes are supported in `flake.nix`: * `nixConfig`: a set of `nix.conf` options to be set when evaluating any part of a flake. In the interests of security, only a small set of - whitelisted options (currently `bash-prompt`, `bash-prompt-suffix`, - and `flake-registry`) are allowed to be set without confirmation so long as - `accept-flake-config` is not set in the global configuration. + whitelisted options (currently `bash-prompt`, `bash-prompt-prefix`, + `bash-prompt-suffix`, and `flake-registry`) are allowed to be set without + confirmation so long as `accept-flake-config` is not set in the global + configuration. ## Flake inputs -- cgit v1.2.3 From aefc6c4f41bfac0c76807c234fd0a786dd40f140 Mon Sep 17 00:00:00 2001 From: Eli Kogan-Wang Date: Wed, 11 May 2022 12:15:08 +0200 Subject: Add priority for nix profile install --- src/nix/profile.cc | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 685776bec..fb8bef670 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -37,7 +37,7 @@ struct ProfileElement StorePathSet storePaths; std::optional source; bool active = true; - // FIXME: priority + int priority = 5; std::string describe() const { @@ -116,6 +116,9 @@ struct ProfileManifest for (auto & p : e["storePaths"]) element.storePaths.insert(state.store->parseStorePath((std::string) p)); element.active = e["active"]; + if(e.contains("priority")) { + element.priority = e["priority"]; + } if (e.value(sUrl, "") != "") { element.source = ProfileElementSource { parseFlakeRef(e[sOriginalUrl]), @@ -153,6 +156,7 @@ struct ProfileManifest nlohmann::json obj; obj["storePaths"] = paths; obj["active"] = element.active; + obj["priority"] = element.priority; if (element.source) { obj["originalUrl"] = element.source->originalRef.to_string(); obj["url"] = element.source->resolvedRef.to_string(); @@ -177,7 +181,7 @@ struct ProfileManifest for (auto & element : elements) { for (auto & path : element.storePaths) { if (element.active) - pkgs.emplace_back(store->printStorePath(path), true, 5); + pkgs.emplace_back(store->printStorePath(path), true, element.priority); references.insert(path); } } @@ -259,6 +263,23 @@ builtPathsPerInstallable( struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile { + std::optional priority; + CmdProfileInstall() { + addFlag({ + .longName = "priority", + .description = "The priority of the package to install.", + .labels = {"priority"}, + .handler = {[&](std::string s) { + try{ + priority = std::stoi(s); + } catch (std::invalid_argument & e) { + throw ParseError("invalid priority '%s'", s); + } + }}, + // .completer = // no completer since number + }); + }; + std::string description() override { return "install a package into a profile"; @@ -282,6 +303,10 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile for (auto & installable : installables) { ProfileElement element; + if(priority) { + element.priority = *priority; + }; + if (auto installable2 = std::dynamic_pointer_cast(installable)) { // FIXME: make build() return this? auto [attrPath, resolvedRef, drv] = installable2->toDerivation(); -- cgit v1.2.3 From 1461e6cdda06f7f461114cce5b415f6d50381311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Wed, 11 May 2022 12:55:31 +0200 Subject: Stop the logger properly in legacy commands Ensures the logger is stopped on exit in legacy commands. Without this, when using `nix-build --log-format bar` and stopping nix with CTRL+C, the bar is not cleared from the screen. --- src/nix/main.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index 6d0f6ce6e..dadb54306 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -261,6 +261,8 @@ void mainWrapped(int argc, char * * argv) } #endif + Finally f([] { logger->stop(); }); + programPath = argv[0]; auto programName = std::string(baseNameOf(programPath)); @@ -279,8 +281,6 @@ void mainWrapped(int argc, char * * argv) verbosity = lvlInfo; } - Finally f([] { logger->stop(); }); - NixArgs args; if (argc == 2 && std::string(argv[1]) == "__dump-args") { -- cgit v1.2.3 From 49ad315c0357116787ef45a1249009b6bc00301f Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 12 May 2022 20:10:02 +0000 Subject: Use `^` not `!` in indexed store derivations installable syntax Match the other syntax that was recently added --- src/nix/nix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 34c763c69..32112d38d 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -130,7 +130,7 @@ the Nix store. Here are the recognised types of installables: If you want to operate on the store derivation itself, pass the `--derivation` flag. -* **Indexed store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv!out` +* **Indexed store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^out` *(Experimental, part of by the `computed-derivations` experimental feature.)* -- cgit v1.2.3 From 8150b93968c648c6d273aaffaffba94096ec3faf Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 13 May 2022 11:12:11 -0400 Subject: fix: alignment during flake show of legacyPackages Fixes: https://github.com/NixOS/nix/issues/6240 https://github.com/NixOS/nix/issues/6045 --- src/nix/flake.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 1938ce4e6..f55929751 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1076,9 +1076,13 @@ struct CmdFlakeShow : FlakeCommand, MixJSON else if (attrPath.size() > 0 && attrPathS[0] == "legacyPackages") { if (attrPath.size() == 1) recurse(); - else if (!showLegacy) - logger->warn(fmt("%s: " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--legacy' to show)", headerPrefix)); - else { + else if (!showLegacy){ + if (!json) + logger->cout(fmt("%s " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--legacy' to show)", headerPrefix)); + else { + logger->warn(fmt("%s omitted (use '--legacy' to show)", concatStringsSep(".", attrPathS))); + } + } else { if (visitor.isDerivation()) showDerivation(); else if (attrPath.size() <= 2) -- cgit v1.2.3 From be2b19041eeec53fba24f7c2494f3f700a4ec595 Mon Sep 17 00:00:00 2001 From: Eli Kogan-Wang Date: Fri, 13 May 2022 22:02:28 +0200 Subject: Integrate review changes --- src/nix/profile.cc | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src/nix') diff --git a/src/nix/profile.cc b/src/nix/profile.cc index fb8bef670..ca5041873 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -269,14 +269,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile .longName = "priority", .description = "The priority of the package to install.", .labels = {"priority"}, - .handler = {[&](std::string s) { - try{ - priority = std::stoi(s); - } catch (std::invalid_argument & e) { - throw ParseError("invalid priority '%s'", s); - } - }}, - // .completer = // no completer since number + .handler = {&priority}, }); }; @@ -303,21 +296,27 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile for (auto & installable : installables) { ProfileElement element; - if(priority) { - element.priority = *priority; - }; + if (auto installable2 = std::dynamic_pointer_cast(installable)) { // FIXME: make build() return this? - auto [attrPath, resolvedRef, drv] = installable2->toDerivation(); + auto [attrPath, resolvedRef, drv, priority] = installable2->toDerivation(); element.source = ProfileElementSource { installable2->flakeRef, resolvedRef, attrPath, installable2->outputsSpec }; + + if(drv.priority) { + element.priority = *drv.priority; + } } + if(priority) { // if --priority was specified we want to override the priority of the installable + element.priority = *priority; + }; + element.updateStorePaths(getEvalStore(), store, builtPaths[installable.get()]); manifest.elements.push_back(std::move(element)); @@ -476,7 +475,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf Strings{}, lockFlags); - auto [attrPath, resolvedRef, drv] = installable->toDerivation(); + auto [attrPath, resolvedRef, drv, priority] = installable->toDerivation(); if (element.source->resolvedRef == resolvedRef) continue; -- cgit v1.2.3 From 27d0f6747d7e70be4b9ade28ce77444e6135cadb Mon Sep 17 00:00:00 2001 From: Eli Kogan-Wang Date: Mon, 16 May 2022 15:17:35 +0200 Subject: resolve redundant priority passing, wrap NixInt in eval-cache variant --- src/nix/profile.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/profile.cc b/src/nix/profile.cc index ca5041873..1aae347df 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -300,7 +300,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile if (auto installable2 = std::dynamic_pointer_cast(installable)) { // FIXME: make build() return this? - auto [attrPath, resolvedRef, drv, priority] = installable2->toDerivation(); + auto [attrPath, resolvedRef, drv] = installable2->toDerivation(); element.source = ProfileElementSource { installable2->flakeRef, resolvedRef, @@ -475,7 +475,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf Strings{}, lockFlags); - auto [attrPath, resolvedRef, drv, priority] = installable->toDerivation(); + auto [attrPath, resolvedRef, drv] = installable->toDerivation(); if (element.source->resolvedRef == resolvedRef) continue; -- cgit v1.2.3 From 452ffe5464f20ac44a01c536349895d138150a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophane=20Hufschmitt?= <7226587+thufschmitt@users.noreply.github.com> Date: Wed, 18 May 2022 16:46:13 +0200 Subject: Hint at the source file on conflict in `flake new` Add a pointer to the source file (from the template) when `nix flake new` (or `init`) encounters an already existing file Fix #6542 --- src/nix/flake.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 1938ce4e6..a1edb5dbf 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -758,7 +758,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand if (pathExists(to2)) { auto contents2 = readFile(to2); if (contents != contents2) - throw Error("refusing to overwrite existing file '%s'", to2); + throw Error("refusing to overwrite existing file '%s' - please merge manually with '%s'", to2, from2); } else writeFile(to2, contents); } @@ -766,7 +766,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto target = readLink(from2); if (pathExists(to2)) { if (readLink(to2) != target) - throw Error("refusing to overwrite existing symlink '%s'", to2); + throw Error("refusing to overwrite existing symlink '%s' - please merge manually with '%s'", to2, from2); } else createSymlink(target, to2); } -- cgit v1.2.3 From 06d57ce7597fc1b49ce1cdc721edc64eaafe38fb Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Wed, 22 Dec 2021 15:36:08 -0700 Subject: nix repl: load flakes from cli args If experimental feature "flakes" is enabled, args passed to `nix repl` will now be considered flake refs and imported using the existing `:load-flake` machinery. In addition, `:load-flake` now supports loading flake fragments. --- src/nix/repl.cc | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 2967632ed..d20eb0929 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -646,11 +646,11 @@ void NixRepl::loadFlake(const std::string & flakeRefS) if (flakeRefS.empty()) throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)"); - auto flakeRef = parseFlakeRef(flakeRefS, absPath("."), true); + auto [flakeRef, fragment] = parseFlakeRefWithFragment(flakeRefS, absPath("."), true); if (evalSettings.pureEval && !flakeRef.input.isLocked()) throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS); - Value v; + auto v = state->allocValue(); flake::callFlake(*state, flake::lockFlake(*state, flakeRef, @@ -659,8 +659,17 @@ void NixRepl::loadFlake(const std::string & flakeRefS) .useRegistries = !evalSettings.pureEval, .allowMutable = !evalSettings.pureEval, }), - v); - addAttrsToScope(v); + *v); + + auto f = v->attrs->get(state->symbols.create(fragment)); + + if (f == 0) { + warn("no attribute %s, nothing loaded", fragment); + return; + }; + + fragment != "" ? addAttrsToScope(*f->value) : addAttrsToScope(*v); + } @@ -689,7 +698,10 @@ void NixRepl::reloadFiles() if (!first) notice(""); first = false; notice("Loading '%1%'...", i); - loadFile(i); + + settings.isExperimentalFeatureEnabled(Xp::Flakes) + ? loadFlake(i) + : loadFile(i); } } -- cgit v1.2.3 From 81567a096258026148b42f3048be9b2ba295b41a Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 18 Feb 2022 18:33:03 -0500 Subject: repl: allow loading installables from CLI repl: search installable with findAlongAttrPath repl: refactor handling of args repl: temp --- src/nix/repl.cc | 87 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 37 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index d20eb0929..df921ef06 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -22,6 +22,7 @@ extern "C" { #include "ansicolor.hh" #include "shared.hh" #include "eval.hh" +#include "eval-cache.hh" #include "eval-inline.hh" #include "attr-path.hh" #include "store-api.hh" @@ -42,16 +43,20 @@ extern "C" { namespace nix { +typedef std::vector> Installables; + struct NixRepl #if HAVE_BOEHMGC : gc #endif { std::string curDir; - std::unique_ptr state; + ref state; Bindings * autoArgs; Strings loadedFiles; + typedef std::vector> AnnotatedValues; + std::function getValues; const static int envSize = 32768; StaticEnv staticEnv; @@ -61,13 +66,16 @@ struct NixRepl const Path historyFile; - NixRepl(const Strings & searchPath, nix::ref store); + NixRepl(const Strings & searchPath, nix::ref store,ref state, + std::function getValues); ~NixRepl(); - void mainLoop(const std::vector & files); + void mainLoop(); StringSet completePrefix(const std::string & prefix); bool getLine(std::string & input, const std::string &prompt); StorePath getDerivationPath(Value & v); bool processLine(std::string line); + + void loadInstallable(Installable & installable); void loadFile(const Path & path); void loadFlake(const std::string & flakeRef); void initEnv(); @@ -92,8 +100,10 @@ std::string removeWhitespace(std::string s) } -NixRepl::NixRepl(const Strings & searchPath, nix::ref store) - : state(std::make_unique(searchPath, store)) +NixRepl::NixRepl(const Strings & searchPath, nix::ref store,ref state, + std::function getValues) + : state(state) + , getValues(getValues) , staticEnv(false, &state->staticBaseEnv) , historyFile(getDataDir() + "/nix/repl-history") { @@ -198,16 +208,12 @@ namespace { } } -void NixRepl::mainLoop(const std::vector & files) +void NixRepl::mainLoop() { std::string error = ANSI_RED "error:" ANSI_NORMAL " "; notice("Welcome to Nix " + nixVersion + ". Type :? for help.\n"); - for (auto & i : files) - loadedFiles.push_back(i); - reloadFiles(); - if (!loadedFiles.empty()) notice(""); // Allow nix-repl specific settings in .inputrc rl_readline_name = "nix-repl"; @@ -630,6 +636,11 @@ bool NixRepl::processLine(std::string line) return true; } +void NixRepl::loadInstallable(Installable & installable) +{ + auto [val, pos] = installable.toValue(*state); + addAttrsToScope(*val); +} void NixRepl::loadFile(const Path & path) { @@ -646,11 +657,11 @@ void NixRepl::loadFlake(const std::string & flakeRefS) if (flakeRefS.empty()) throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)"); - auto [flakeRef, fragment] = parseFlakeRefWithFragment(flakeRefS, absPath("."), true); + auto flakeRef = parseFlakeRef(flakeRefS, absPath("."), true); if (evalSettings.pureEval && !flakeRef.input.isLocked()) throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS); - auto v = state->allocValue(); + Value v; flake::callFlake(*state, flake::lockFlake(*state, flakeRef, @@ -659,17 +670,8 @@ void NixRepl::loadFlake(const std::string & flakeRefS) .useRegistries = !evalSettings.pureEval, .allowMutable = !evalSettings.pureEval, }), - *v); - - auto f = v->attrs->get(state->symbols.create(fragment)); - - if (f == 0) { - warn("no attribute %s, nothing loaded", fragment); - return; - }; - - fragment != "" ? addAttrsToScope(*f->value) : addAttrsToScope(*v); - + v); + addAttrsToScope(v); } @@ -693,15 +695,14 @@ void NixRepl::reloadFiles() Strings old = loadedFiles; loadedFiles.clear(); - bool first = true; for (auto & i : old) { - if (!first) notice(""); - first = false; notice("Loading '%1%'...", i); + loadFile(i); + } - settings.isExperimentalFeatureEnabled(Xp::Flakes) - ? loadFlake(i) - : loadFile(i); + for (auto & [i,what] : getValues()) { + notice("Loading Installable '%1%'...", what); + addAttrsToScope(*i); } } @@ -898,17 +899,20 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m return str; } -struct CmdRepl : StoreCommand, MixEvalArgs +struct CmdRepl : InstallableCommand { std::vector files; + Strings getDefaultFlakeAttrPathPrefixes() + override { + return {}; + } + Strings getDefaultFlakeAttrPaths() + override { + return {""}; + } CmdRepl() { - expectArgs({ - .label = "files", - .handler = {&files}, - .completer = completePath - }); } std::string description() override @@ -925,10 +929,19 @@ struct CmdRepl : StoreCommand, MixEvalArgs void run(ref store) override { + evalSettings.pureEval = false; - auto repl = std::make_unique(searchPath, openStore()); + auto state = getEvalState(); + auto repl = std::make_unique(searchPath, openStore(),state + ,[&]()->NixRepl::AnnotatedValues{ + auto installable = load(); + auto [val, pos] = installable->toValue(*state); + auto what = installable->what(); + return { {val,what} }; + } + ); repl->autoArgs = getAutoArgs(*repl->state); - repl->mainLoop(files); + repl->mainLoop(); } }; -- cgit v1.2.3 From 5640b528349c43717aa501797a4f337373ebf3e4 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 11 Mar 2022 13:26:08 -0500 Subject: repl: use installables --- src/nix/repl.cc | 23 ++++++++++++----------- src/nix/repl.md | 30 +++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 14 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index df921ef06..b5ecc8ad0 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -43,8 +43,6 @@ extern "C" { namespace nix { -typedef std::vector> Installables; - struct NixRepl #if HAVE_BOEHMGC : gc @@ -899,17 +897,16 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m return str; } -struct CmdRepl : InstallableCommand +struct CmdRepl : InstallablesCommand { std::vector files; - Strings getDefaultFlakeAttrPathPrefixes() - override { - return {}; - } Strings getDefaultFlakeAttrPaths() override { return {""}; } + virtual bool useDefaultInstallables() { + return file.has_value() or expr.has_value(); + } CmdRepl() { @@ -934,10 +931,14 @@ struct CmdRepl : InstallableCommand auto state = getEvalState(); auto repl = std::make_unique(searchPath, openStore(),state ,[&]()->NixRepl::AnnotatedValues{ - auto installable = load(); - auto [val, pos] = installable->toValue(*state); - auto what = installable->what(); - return { {val,what} }; + auto installables = load(); + NixRepl::AnnotatedValues values; + for (auto & installable: installables){ + auto [val, pos] = installable->toValue(*state); + auto what = installable->what(); + values.push_back( {val,what} ); + } + return values; } ); repl->autoArgs = getAutoArgs(*repl->state); diff --git a/src/nix/repl.md b/src/nix/repl.md index 9b6f2bee3..be1498e5b 100644 --- a/src/nix/repl.md +++ b/src/nix/repl.md @@ -24,10 +24,34 @@ R""( * Interact with Nixpkgs in the REPL: ```console - # nix repl '' + # nix repl --file example.nix + Loading Installable ''... + Added 3 variables. - Loading ''... - Added 12428 variables. + # nix repl --expr '{a={b=3;c=4;};}' + Loading Installable ''... + Added 1 variables. + + # nix repl --expr '{a={b=3;c=4;};}' a + Loading Installable ''... + Added 1 variables. + + # nix repl nixpkgs + Loading Installable 'flake:nixpkgs#'... + Added 5 variables. + + nix-repl> legacyPackages.x86_64-linux.emacs.name + "emacs-27.1" + + nix-repl> legacyPackages.x86_64-linux.emacs.name + "emacs-27.1" + + nix-repl> :q + + # nix repl --expr 'import {}' --impure + + Loading Installable ''... + Added 12439 variables. nix-repl> emacs.name "emacs-27.1" -- cgit v1.2.3 From 1ca3f6035da4e82647382405c774e43e02de3fa1 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 11 Mar 2022 13:52:08 -0500 Subject: repl: update docs with installables --- src/nix/repl.cc | 16 +++------------- src/nix/repl.md | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index b5ecc8ad0..ac0f1f4d7 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -73,7 +73,6 @@ struct NixRepl StorePath getDerivationPath(Value & v); bool processLine(std::string line); - void loadInstallable(Installable & installable); void loadFile(const Path & path); void loadFlake(const std::string & flakeRef); void initEnv(); @@ -634,12 +633,6 @@ bool NixRepl::processLine(std::string line) return true; } -void NixRepl::loadInstallable(Installable & installable) -{ - auto [val, pos] = installable.toValue(*state); - addAttrsToScope(*val); -} - void NixRepl::loadFile(const Path & path) { loadedFiles.remove(path); @@ -899,6 +892,9 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m struct CmdRepl : InstallablesCommand { + CmdRepl(){ + evalSettings.pureEval = false; + } std::vector files; Strings getDefaultFlakeAttrPaths() override { @@ -908,10 +904,6 @@ struct CmdRepl : InstallablesCommand return file.has_value() or expr.has_value(); } - CmdRepl() - { - } - std::string description() override { return "start an interactive environment for evaluating Nix expressions"; @@ -926,8 +918,6 @@ struct CmdRepl : InstallablesCommand void run(ref store) override { - - evalSettings.pureEval = false; auto state = getEvalState(); auto repl = std::make_unique(searchPath, openStore(),state ,[&]()->NixRepl::AnnotatedValues{ diff --git a/src/nix/repl.md b/src/nix/repl.md index be1498e5b..6a526f7d0 100644 --- a/src/nix/repl.md +++ b/src/nix/repl.md @@ -48,7 +48,7 @@ R""( nix-repl> :q - # nix repl --expr 'import {}' --impure + # nix repl --expr 'import {}' Loading Installable ''... Added 12439 variables. -- cgit v1.2.3 From 9f8c1183fa10aa9d95bce0ca2f3337532ad7981b Mon Sep 17 00:00:00 2001 From: tomberek Date: Wed, 18 May 2022 21:18:07 -0400 Subject: Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Théophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com> --- src/nix/repl.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index ac0f1f4d7..a1b42b760 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -896,11 +896,12 @@ struct CmdRepl : InstallablesCommand evalSettings.pureEval = false; } std::vector files; - Strings getDefaultFlakeAttrPaths() - override { + Strings getDefaultFlakeAttrPaths() override + { return {""}; } - virtual bool useDefaultInstallables() { + virtual bool useDefaultInstallables() override + { return file.has_value() or expr.has_value(); } -- cgit v1.2.3 From 7534798eedb696226101f2c8793ba9ace049f5e4 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Wed, 18 May 2022 21:33:41 -0400 Subject: refactor: factor out getValue --- src/nix/repl.cc | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index a1b42b760..cae76bb5d 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -920,18 +920,22 @@ struct CmdRepl : InstallablesCommand void run(ref store) override { auto state = getEvalState(); - auto repl = std::make_unique(searchPath, openStore(),state - ,[&]()->NixRepl::AnnotatedValues{ - auto installables = load(); - NixRepl::AnnotatedValues values; - for (auto & installable: installables){ - auto [val, pos] = installable->toValue(*state); - auto what = installable->what(); - values.push_back( {val,what} ); - } - return values; - } - ); + auto getValues = [&]()->NixRepl::AnnotatedValues{ + auto installables = load(); + NixRepl::AnnotatedValues values; + for (auto & installable: installables){ + auto [val, pos] = installable->toValue(*state); + auto what = installable->what(); + values.push_back( {val,what} ); + } + return values; + }; + auto repl = std::make_unique( + searchPath, + openStore(), + state, + getValues + ); repl->autoArgs = getAutoArgs(*repl->state); repl->mainLoop(); } -- cgit v1.2.3 From e1f308a1ec3c395cd4978b45400f7a45adcea0dc Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Wed, 18 May 2022 22:28:15 -0400 Subject: repl: provide backward compat with legacy usage --- src/nix/repl.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index cae76bb5d..d4079816f 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -895,6 +895,22 @@ struct CmdRepl : InstallablesCommand CmdRepl(){ evalSettings.pureEval = false; } + void prepare() + { + if (!settings.isExperimentalFeatureEnabled(Xp::Flakes) && !(file)) { + warn("future versions of Nix will require using `--file` to load a file"); + if (this->_installables.size() > 1) { + warn("more than one input file is not currently supported"); + } + if (this->_installables.size() >= 1) { + file = std::optional( + this->_installables[0].data() + ); + } + _installables.clear(); + } + installables = InstallablesCommand::load(); + } std::vector files; Strings getDefaultFlakeAttrPaths() override { -- cgit v1.2.3 From f21dec5befc9ee273a5210dec322d30c3c3be595 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Thu, 19 May 2022 01:01:45 -0400 Subject: repl: hide flake behavior behind flag and provide warning --- src/nix/repl.cc | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index d4079816f..18cdb3580 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -897,17 +897,14 @@ struct CmdRepl : InstallablesCommand } void prepare() { - if (!settings.isExperimentalFeatureEnabled(Xp::Flakes) && !(file)) { + if (!settings.isExperimentalFeatureEnabled(Xp::Flakes) && !(file) && this->_installables.size() >= 1) { warn("future versions of Nix will require using `--file` to load a file"); - if (this->_installables.size() > 1) { + if (this->_installables.size() > 1) warn("more than one input file is not currently supported"); - } - if (this->_installables.size() >= 1) { - file = std::optional( - this->_installables[0].data() - ); - } - _installables.clear(); + auto filePath = this->_installables[0].data(); + file = std::optional(filePath); + _installables.front() = _installables.back(); + _installables.pop_back(); } installables = InstallablesCommand::load(); } @@ -940,9 +937,20 @@ struct CmdRepl : InstallablesCommand auto installables = load(); NixRepl::AnnotatedValues values; for (auto & installable: installables){ - auto [val, pos] = installable->toValue(*state); auto what = installable->what(); - values.push_back( {val,what} ); + if (!settings.isExperimentalFeatureEnabled(Xp::Flakes) && file){ + auto [val, pos] = installable->toValue(*state); + auto what = installable->what(); + state->forceValue(*val, pos); + auto autoArgs = getAutoArgs(*state); + Value *valPost = state->allocValue(); + state->autoCallFunction(*autoArgs, *val, *valPost); + state->forceValue(*valPost, pos); + values.push_back( {valPost, what }); + } else { + auto [val, pos] = installable->toValue(*state); + values.push_back( {val,what} ); + } } return values; }; -- cgit v1.2.3 From 5b8c1deb18e0e6fc7a83fb8101cf5fc8dba38843 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 16 Oct 2020 00:35:24 +0100 Subject: fetchTree: Allow fetching plain files Add a new `file` fetcher type, which will fetch a plain file over http(s), or from the local file. Because plain `http(s)://` or `file://` urls can already correspond to `tarball` inputs (if the path ends-up with a know archive extension), the URL parsing logic is a bit convuluted in that: - {http,https,file}:// urls will be interpreted as either a tarball or a file input, depending on the extensions of the path part (so `https://foo.com/bar` will be a `file` input and `https://foo.com/bar.tar.gz` as a `tarball` input) - `file+{something}://` urls will be interpreted as `file` urls (with the `file+` part removed) - `tarball+{something}://` urls will be interpreted as `tarball` urls (with the `tarball+` part removed) Fix #3785 Co-Authored-By: Tony Olagbaiye --- src/nix/flake.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/nix') diff --git a/src/nix/flake.md b/src/nix/flake.md index aa3f9f303..a1ab43281 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -181,9 +181,17 @@ Currently the `type` attribute can be one of the following: * `tarball`: Tarballs. The location of the tarball is specified by the attribute `url`. - In URL form, the schema must be `http://`, `https://` or `file://` - URLs and the extension must be `.zip`, `.tar`, `.tgz`, `.tar.gz`, - `.tar.xz`, `.tar.bz2` or `.tar.zst`. + In URL form, the schema must be `tarball+http://`, `tarball+https://` or `tarball+file://`. + If the extension corresponds to a known archive format (`.zip`, `.tar`, + `.tgz`, `.tar.gz`, `.tar.xz`, `.tar.bz2` or `.tar.zst`), then the `tarball+` + can be dropped. + +* `file`: Plain files or directory tarballs, either over http(s) or from the local + disk. + + In URL form, the schema must be `file+http://`, `file+https://` or `file+file://`. + If the extension doesn’t correspond to a known archive format (as defined by the + `tarball` fetcher), then the `file+` prefix can be dropped. * `github`: A more efficient way to fetch repositories from GitHub. The following attributes are required: -- cgit v1.2.3 From 7d7e00272a2f47f68b3809296992db84ae871e09 Mon Sep 17 00:00:00 2001 From: tomberek Date: Fri, 20 May 2022 01:28:20 -0400 Subject: Apply suggestions from code review Style fixes from @edolstra Co-authored-by: Eelco Dolstra --- src/nix/repl.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 18cdb3580..6c05daa11 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -97,7 +97,7 @@ std::string removeWhitespace(std::string s) } -NixRepl::NixRepl(const Strings & searchPath, nix::ref store,ref state, +NixRepl::NixRepl(const Strings & searchPath, nix::ref store, ref state, std::function getValues) : state(state) , getValues(getValues) @@ -691,8 +691,8 @@ void NixRepl::reloadFiles() loadFile(i); } - for (auto & [i,what] : getValues()) { - notice("Loading Installable '%1%'...", what); + for (auto & [i, what] : getValues()) { + notice("Loading installable '%1%'...", what); addAttrsToScope(*i); } } @@ -943,13 +943,13 @@ struct CmdRepl : InstallablesCommand auto what = installable->what(); state->forceValue(*val, pos); auto autoArgs = getAutoArgs(*state); - Value *valPost = state->allocValue(); + auto valPost = state->allocValue(); state->autoCallFunction(*autoArgs, *val, *valPost); state->forceValue(*valPost, pos); values.push_back( {valPost, what }); } else { auto [val, pos] = installable->toValue(*state); - values.push_back( {val,what} ); + values.push_back( {val, what} ); } } return values; -- cgit v1.2.3 From db613a85fb7fb8c8a0f476f83db92523cce327f7 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 20 May 2022 01:35:06 -0400 Subject: repl: allow --file to always utilize autoargs --- src/nix/repl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 6c05daa11..e9898c08c 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -938,7 +938,7 @@ struct CmdRepl : InstallablesCommand NixRepl::AnnotatedValues values; for (auto & installable: installables){ auto what = installable->what(); - if (!settings.isExperimentalFeatureEnabled(Xp::Flakes) && file){ + if (file){ auto [val, pos] = installable->toValue(*state); auto what = installable->what(); state->forceValue(*val, pos); -- cgit v1.2.3 From 7a04fb1c56ca60652c2a44019b31fe8cf2e2bc46 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 20 May 2022 08:20:00 -0400 Subject: repl: add repl-flake experimental feature for gating --- src/nix/repl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/repl.cc b/src/nix/repl.cc index e9898c08c..b12f05c15 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -897,7 +897,7 @@ struct CmdRepl : InstallablesCommand } void prepare() { - if (!settings.isExperimentalFeatureEnabled(Xp::Flakes) && !(file) && this->_installables.size() >= 1) { + if (!settings.isExperimentalFeatureEnabled(Xp::ReplFlake) && !(file) && this->_installables.size() >= 1) { warn("future versions of Nix will require using `--file` to load a file"); if (this->_installables.size() > 1) warn("more than one input file is not currently supported"); -- cgit v1.2.3 From 81a9bf0ad2ff3244096ed14299c65c0b32c0aca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Camille=20Favier?= Date: Sat, 21 May 2022 14:41:24 +0200 Subject: =?UTF-8?q?typo:=20defaultApps=20=E2=86=92=20defaultApp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/nix/flake.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 1938ce4e6..500116eaf 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -509,7 +509,7 @@ struct CmdFlakeCheck : FlakeCommand std::string_view replacement = name == "defaultPackage" ? "packages..default" : - name == "defaultApps" ? "apps..default" : + name == "defaultApp" ? "apps..default" : name == "defaultTemplate" ? "templates.default" : name == "defaultBundler" ? "bundlers..default" : name == "overlay" ? "overlays.default" : -- cgit v1.2.3 From 2f8a34cddcdd738afebde38e83b2315d3e305152 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 25 May 2022 15:05:39 +0200 Subject: Fix warning --- src/nix/profile.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 1aae347df..3814e7d5a 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -263,7 +263,8 @@ builtPathsPerInstallable( struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile { - std::optional priority; + std::optional priority; + CmdProfileInstall() { addFlag({ .longName = "priority", -- cgit v1.2.3 From 159b5815b527f466578a2d28fbf832617cc45b88 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Mon, 31 Jan 2022 18:03:24 +0100 Subject: repl: `--option pure-eval true` actually enables pure eval mode To quote Eelco in #5867: > Unfortunately we can't do > > evalSettings.pureEval.setDefault(false); > > because then we have to do the same in main.cc (where > pureEval is set to true), and that would allow pure-eval > to be disabled globally from nix.conf. Instead, a command should specify that it should be impure by default. Then, `evalSettings.pureEval` will be set to `false;` unless it's overridden by e.g. a CLI flag. In that case it's IMHO OK to be (theoretically) able to override `pure-eval` via `nix.conf` because it doesn't have an effect on commands where `forceImpureByDefault` returns `false` (i.e. everything where pure eval actually matters). Closes #5867 --- src/nix/main.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index dadb54306..f398e3118 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -380,6 +380,9 @@ void mainWrapped(int argc, char * * argv) settings.ttlPositiveNarInfoCache = 0; } + if (args.command->second->forceImpureByDefault() && !evalSettings.pureEval.overridden) { + evalSettings.pureEval = false; + } args.command->second->prepare(); args.command->second->run(); } -- cgit v1.2.3 From 51b3cc151eb479d9c59e45b5de78dee191354717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20W=C3=B6gi?= <789@c-w.li> Date: Wed, 1 Jun 2022 16:33:03 +0200 Subject: Explain exactly what nix-upgrade nix does --- src/nix/upgrade-nix.cc | 2 +- src/nix/upgrade-nix.md | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/nix') diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 17a5a77ee..2d2453395 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -34,7 +34,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand std::string description() override { - return "upgrade Nix to the latest stable version"; + return "upgrade Nix to the stable version declared in Nixpkgs"; } std::string doc() override diff --git a/src/nix/upgrade-nix.md b/src/nix/upgrade-nix.md index 4d27daad9..084c80ba2 100644 --- a/src/nix/upgrade-nix.md +++ b/src/nix/upgrade-nix.md @@ -2,7 +2,7 @@ R""( # Examples -* Upgrade Nix to the latest stable version: +* Upgrade Nix to the stable version declared in Nixpkgs: ```console # nix upgrade-nix @@ -16,8 +16,11 @@ R""( # Description -This command upgrades Nix to the latest version. By default, it -locates the directory containing the `nix` binary in the `$PATH` +This command upgrades Nix to the stable version declared in Nixpkgs. +This stable version is defined in [nix-fallback-paths.nix](https://github.com/NixOS/nixpkgs/raw/master/nixos/modules/installer/tools/nix-fallback-paths.nix) +and updated manually. It may not always be the latest tagged release. + +By default, it locates the directory containing the `nix` binary in the `$PATH` environment variable. If that directory is a Nix profile, it will upgrade the `nix` package in that profile to the latest stable binary release. -- cgit v1.2.3 From b42358b9bec12dfdc419136f32ded2a4f7d7dea7 Mon Sep 17 00:00:00 2001 From: Fishhh Date: Sun, 5 Jun 2022 18:45:58 +0200 Subject: Add `--exclude` flag to `nix search` If a package's attribute path, description or name contains matches for any of the regexes specified via `-e` or `--exclude` that package is excluded from the final output. --- src/nix/search.cc | 23 ++++++++++++++++++++++- src/nix/search.md | 13 ++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/search.cc b/src/nix/search.cc index 87dc1c0de..62ad98999 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -18,16 +18,24 @@ using namespace nix; std::string wrap(std::string prefix, std::string s) { - return prefix + s + ANSI_NORMAL; + return concatStrings(prefix, s, ANSI_NORMAL); } struct CmdSearch : InstallableCommand, MixJSON { std::vector res; + std::vector excludeRes; CmdSearch() { expectArgs("regex", &res); + addFlag(Flag { + .longName = "exclude", + .shortName = 'e', + .description = "Hide packages whose attribute path, name or description contain *regex*.", + .labels = {"regex"}, + .handler = Handler(&excludeRes), + }); } std::string description() override @@ -62,11 +70,16 @@ struct CmdSearch : InstallableCommand, MixJSON res.push_back("^"); std::vector regexes; + std::vector excludeRegexes; regexes.reserve(res.size()); + excludeRegexes.reserve(excludeRes.size()); for (auto & re : res) regexes.push_back(std::regex(re, std::regex::extended | std::regex::icase)); + for (auto & re : excludeRes) + excludeRegexes.emplace_back(re, std::regex::extended | std::regex::icase); + auto state = getEvalState(); auto jsonOut = json ? std::make_unique(std::cout) : nullptr; @@ -106,6 +119,14 @@ struct CmdSearch : InstallableCommand, MixJSON std::vector nameMatches; bool found = false; + for (auto & regex : excludeRegexes) { + if ( + std::regex_search(attrPath2, regex) + || std::regex_search(name.name, regex) + || std::regex_search(description, regex)) + return; + } + for (auto & regex : regexes) { found = false; auto addAll = [&found](std::sregex_iterator it, std::vector & vec) { diff --git a/src/nix/search.md b/src/nix/search.md index d182788a6..5a5b5ae05 100644 --- a/src/nix/search.md +++ b/src/nix/search.md @@ -43,12 +43,23 @@ R""( # nix search nixpkgs 'firefox|chromium' ``` -* Search for packages containing `git'`and either `frontend` or `gui`: +* Search for packages containing `git` and either `frontend` or `gui`: ```console # nix search nixpkgs git 'frontend|gui' ``` +* Search for packages containing `neovim` but hide ones containing either `gui` or `python`: + + ```console + # nix search nixpkgs neovim -e 'python|gui' + ``` + or + + ```console + # nix search nixpkgs neovim -e 'python' -e 'gui' + ``` + # Description `nix search` searches *installable* (which must be evaluatable, e.g. a -- cgit v1.2.3 From e009367c8d4523bfe3a1bc20583b27d06948a390 Mon Sep 17 00:00:00 2001 From: Fishhh Date: Sun, 5 Jun 2022 18:48:48 +0200 Subject: Remove redundant `std::move`s in calls to `hiliteMatches` --- src/nix/search.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nix') diff --git a/src/nix/search.cc b/src/nix/search.cc index 62ad98999..f1f5f9641 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -154,15 +154,15 @@ struct CmdSearch : InstallableCommand, MixJSON jsonElem.attr("version", name.version); jsonElem.attr("description", description); } else { - auto name2 = hiliteMatches(name.name, std::move(nameMatches), ANSI_GREEN, "\e[0;2m"); + auto name2 = hiliteMatches(name.name, nameMatches, ANSI_GREEN, "\e[0;2m"); if (results > 1) logger->cout(""); logger->cout( "* %s%s", - wrap("\e[0;1m", hiliteMatches(attrPath2, std::move(attrPathMatches), ANSI_GREEN, "\e[0;1m")), + wrap("\e[0;1m", hiliteMatches(attrPath2, attrPathMatches, ANSI_GREEN, "\e[0;1m")), name.version != "" ? " (" + name.version + ")" : ""); if (description != "") logger->cout( - " %s", hiliteMatches(description, std::move(descriptionMatches), ANSI_GREEN, ANSI_NORMAL)); + " %s", hiliteMatches(description, descriptionMatches, ANSI_GREEN, ANSI_NORMAL)); } } } -- cgit v1.2.3 From 814ddfa5f53002216f260b3d33ca41514fa8d777 Mon Sep 17 00:00:00 2001 From: Lorenzo Manacorda Date: Wed, 8 Jun 2022 11:46:50 +0200 Subject: Fix missing ` in key manual --- src/nix/key-generate-secret.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/key-generate-secret.md b/src/nix/key-generate-secret.md index 4938f637c..609b1abcc 100644 --- a/src/nix/key-generate-secret.md +++ b/src/nix/key-generate-secret.md @@ -30,7 +30,7 @@ convert-secret-to-public` to get the corresponding public key for verifying signed store paths. The mandatory argument `--key-name` specifies a key name (such as -`cache.example.org-1). It is used to look up keys on the client when +`cache.example.org-1`). It is used to look up keys on the client when it verifies signatures. It can be anything, but it’s suggested to use the host name of your cache (e.g. `cache.example.org`) with a suffix denoting the number of the key (to be incremented every time you need -- cgit v1.2.3 From dae4a8a6c8d8dfde3292d3e9e05977bc13648bda Mon Sep 17 00:00:00 2001 From: tomberek Date: Wed, 15 Jun 2022 09:02:36 -0400 Subject: Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Théophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com> --- src/nix/repl.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/repl.md b/src/nix/repl.md index 6a526f7d0..23ef0f4e6 100644 --- a/src/nix/repl.md +++ b/src/nix/repl.md @@ -36,7 +36,7 @@ R""( Loading Installable ''... Added 1 variables. - # nix repl nixpkgs + # nix repl --extra_experimental_features 'flakes repl-flake' nixpkgs Loading Installable 'flake:nixpkgs#'... Added 5 variables. -- cgit v1.2.3 From d6d0e781bbade76f6ea3f310cb36973f4013826d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Sun, 19 Jun 2022 17:54:27 +0200 Subject: Complete flake inputs for all given flakes Allow `nix build flake1 flake2 --update-input ` to complete the inputs of both flakes. Also do tilde expansion so that `nix build ~/flake --update-input ` works. --- src/nix/flake.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 8370b8dcf..439eb53ba 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -50,9 +50,9 @@ public: return flake::lockFlake(*getEvalState(), getFlakeRef(), lockFlags); } - std::optional getFlakeRefForCompletion() override + std::vector getFlakesForCompletion() override { - return getFlakeRef(); + return {flakeUrl}; } }; -- cgit v1.2.3 From 4ade8a5f25a32cdf591ea369318d9d256e49025a Mon Sep 17 00:00:00 2001 From: Fishhh Date: Mon, 20 Jun 2022 18:00:32 +0200 Subject: Fix arity of `--exclude` flag in `nix search` Due to incorrectly using the Handler(vector*) constructor the `--exclude` flag would swallow all proceeding arguments instead of just one. --- src/nix/search.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/search.cc b/src/nix/search.cc index f1f5f9641..bdd45cbed 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -34,7 +34,9 @@ struct CmdSearch : InstallableCommand, MixJSON .shortName = 'e', .description = "Hide packages whose attribute path, name or description contain *regex*.", .labels = {"regex"}, - .handler = Handler(&excludeRes), + .handler = {[this](std::string s) { + excludeRes.push_back(s); + }}, }); } -- cgit v1.2.3 From 3a85fd077cf8a404e0b7c727e47b8fcee85280a5 Mon Sep 17 00:00:00 2001 From: "Manu [tennox]" <2084639+tennox@users.noreply.github.com> Date: Tue, 21 Jun 2022 17:26:32 +0100 Subject: #6542 Apply flake templates partially on conflicts Will still exit with non-zero exit code and clearly prompt which files to merge: ``` nixx flake init -t github:numtide/devshell wrote: /home/manu/dev/stuff/gopassbridge/.envrc refusing to overwrite existing file '/home/manu/dev/stuff/gopassbridge/.gitignore' -> merge manually with '/nix/store/ksmwhyghjwb4d9dw6hcpbvng1msdvjim-source/template/.gitignore' wrote: /home/manu/dev/stuff/gopassbridge/devshell.toml wrote: /home/manu/dev/stuff/gopassbridge/flake.nix error: Encountered 1 conflicts - please merge manually ``` --- src/nix/flake.cc | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index a1edb5dbf..24255c247 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -740,7 +740,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand "If you've set '%s' to a string, try using a path instead.", templateDir, templateDirAttr->getAttrPathStr()); - std::vector files; + std::vector changedFiles; + std::vector conflictedFiles; + auto success = false; std::function copyDir; copyDir = [&](const Path & from, const Path & to) @@ -757,22 +759,33 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto contents = readFile(from2); if (pathExists(to2)) { auto contents2 = readFile(to2); - if (contents != contents2) - throw Error("refusing to overwrite existing file '%s' - please merge manually with '%s'", to2, from2); + if (contents != contents2) { + printError("refusing to overwrite existing file '%s'\n-> merge manually with '%s'", to2, from2); + success = false; + conflictedFiles.push_back(to2); + } else { + notice("skipping identical file: %s", from2); + } + continue; } else writeFile(to2, contents); } else if (S_ISLNK(st.st_mode)) { auto target = readLink(from2); if (pathExists(to2)) { - if (readLink(to2) != target) - throw Error("refusing to overwrite existing symlink '%s' - please merge manually with '%s'", to2, from2); + if (readLink(to2) != target) { + printError("refusing to overwrite existing file '%s' - please merge manually with '%s'", to2, from2); + success = false; + conflictedFiles.push_back(to2); + } else { + notice("skipping identical file: %s", from2); + } } else createSymlink(target, to2); } else throw Error("file '%s' has unsupported type", from2); - files.push_back(to2); + changedFiles.push_back(to2); notice("wrote: %s", to2); } }; @@ -781,7 +794,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand if (pathExists(flakeDir + "/.git")) { Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" }; - for (auto & s : files) args.push_back(s); + for (auto & s : changedFiles) args.push_back(s); runProgram("git", true, args); } auto welcomeText = cursor->maybeGetAttr("welcomeText"); @@ -789,6 +802,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand notice("\n"); notice(renderMarkdownToTerminal(welcomeText->getString())); } + + if (!success) + throw Error("Encountered %d conflicts - please merge manually", conflictedFiles.size()); } }; -- cgit v1.2.3 From 155c57c17131770a33dbd86055684d3605a0d505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Wed, 22 Jun 2022 11:24:20 +0200 Subject: nix develop: save XDG_DATA_DIRS for loadable completion --- src/nix/develop.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 2a3fc0213..6d9ad9942 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -276,15 +276,25 @@ struct Common : InstallableCommand, MixProfile const BuildEnvironment & buildEnvironment, const Path & outputsDir = absPath(".") + "/outputs") { + // A list of colon-separated environment variables that should be + // prepended to, rather than overwritten, in order to keep the shell usable. + // Please keep this list minimal in order to avoid impurities. + static const char * const savedVars[] = { + "PATH", // for commands + "XDG_DATA_DIRS", // for loadable completion + }; + std::ostringstream out; out << "unset shellHook\n"; - out << "nix_saved_PATH=\"$PATH\"\n"; + for (auto & var : savedVars) + out << fmt("nix_saved_%s=\"$%s\"\n", var, var); buildEnvironment.toBash(out, ignoreVars); - out << "PATH=\"$PATH:$nix_saved_PATH\"\n"; + for (auto & var : savedVars) + out << fmt("%s=\"$%s:$nix_saved_%s\"\n", var, var, var); out << "export NIX_BUILD_TOP=\"$(mktemp -d -t nix-shell.XXXXXX)\"\n"; for (auto & i : {"TMP", "TMPDIR", "TEMP", "TEMPDIR"}) -- cgit v1.2.3 From d3176ce076407ef3e63667c0436bccf8be317ae4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 22 Jun 2022 22:43:53 +0200 Subject: Fix build-remote in nix-static 'build-remote' is now executed via /proc/self/exe so it always works. --- src/nix/main.cc | 5 +++++ src/nix/run.cc | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index f398e3118..17c92ebc6 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -266,6 +266,11 @@ void mainWrapped(int argc, char * * argv) programPath = argv[0]; auto programName = std::string(baseNameOf(programPath)); + if (argc > 0 && std::string_view(argv[0]) == "__build-remote") { + programName = "build-remote"; + argv++; argc--; + } + { auto legacy = (*RegisterLegacyCommand::commands)[programName]; if (legacy) return legacy(argc, argv); diff --git a/src/nix/run.cc b/src/nix/run.cc index 25a8fa8d3..45d2dfd0d 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -47,7 +47,7 @@ void runProgramInStore(ref store, Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program }; for (auto & arg : args) helperArgs.push_back(arg); - execv(readLink("/proc/self/exe").c_str(), stringsToCharPtrs(helperArgs).data()); + execv(getSelfExe().value_or("nix").c_str(), stringsToCharPtrs(helperArgs).data()); throw SysError("could not execute chroot helper"); } -- cgit v1.2.3 From 117baee1b78f662291e980075668720179c1c455 Mon Sep 17 00:00:00 2001 From: Manuel <2084639+tennox@users.noreply.github.com> Date: Sun, 26 Jun 2022 18:00:34 +0100 Subject: Update src/nix/flake.cc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/NixOS/nix/pull/6699#discussion_r904096906 Co-authored-by: Théophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com> --- src/nix/flake.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 24255c247..fdb373f24 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -760,7 +760,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand if (pathExists(to2)) { auto contents2 = readFile(to2); if (contents != contents2) { - printError("refusing to overwrite existing file '%s'\n-> merge manually with '%s'", to2, from2); + printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); success = false; conflictedFiles.push_back(to2); } else { -- cgit v1.2.3 From 58cbbdc5e78b952bfaf8ff36e9c94ccbd08469b7 Mon Sep 17 00:00:00 2001 From: Manuel <2084639+tennox@users.noreply.github.com> Date: Sun, 26 Jun 2022 18:00:57 +0100 Subject: Update src/nix/flake.cc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/NixOS/nix/pull/6699#discussion_r904097147 Co-authored-by: Théophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com> --- src/nix/flake.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index fdb373f24..10bbcaf43 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -774,7 +774,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto target = readLink(from2); if (pathExists(to2)) { if (readLink(to2) != target) { - printError("refusing to overwrite existing file '%s' - please merge manually with '%s'", to2, from2); + printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); success = false; conflictedFiles.push_back(to2); } else { -- cgit v1.2.3 From 4374e3ec67a6c3ed8342908a5229437424926bf5 Mon Sep 17 00:00:00 2001 From: "Manu [tennox]" <2084639+tennox@users.noreply.github.com> Date: Sun, 26 Jun 2022 18:12:30 +0100 Subject: #6699 flake init: Apply suggestions of @thufschmitt --- src/nix/flake.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 10bbcaf43..1140548e7 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -742,7 +742,6 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand std::vector changedFiles; std::vector conflictedFiles; - auto success = false; std::function copyDir; copyDir = [&](const Path & from, const Path & to) @@ -761,7 +760,6 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto contents2 = readFile(to2); if (contents != contents2) { printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); - success = false; conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); @@ -775,7 +773,6 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand if (pathExists(to2)) { if (readLink(to2) != target) { printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); - success = false; conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); @@ -803,8 +800,8 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand notice(renderMarkdownToTerminal(welcomeText->getString())); } - if (!success) - throw Error("Encountered %d conflicts - please merge manually", conflictedFiles.size()); + if (!conflictedFiles.empty()) + throw Error("Encountered %d conflicts - see above", conflictedFiles.size()); } }; -- cgit v1.2.3 From ae4c9ef8e284eabf3624d9e9ad0f0b432e06da41 Mon Sep 17 00:00:00 2001 From: "Manu [tennox]" <2084639+tennox@users.noreply.github.com> Date: Sun, 26 Jun 2022 21:29:45 +0100 Subject: #6699 flake init: fix trying to add unchanged file After skipping because of being of identical content it tried to git add it. --- src/nix/flake.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 1140548e7..895a7de76 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -777,6 +777,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand } else { notice("skipping identical file: %s", from2); } + continue; } else createSymlink(target, to2); } @@ -789,7 +790,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand copyDir(templateDir, flakeDir); - if (pathExists(flakeDir + "/.git")) { + if (!changedFiles.empty() && pathExists(flakeDir + "/.git")) { Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" }; for (auto & s : changedFiles) args.push_back(s); runProgram("git", true, args); -- cgit v1.2.3 From cd361b31faf5a00ccd57eedf3dbd344d9ffb2faf Mon Sep 17 00:00:00 2001 From: Alex Wied Date: Tue, 28 Jun 2022 22:43:37 -0400 Subject: doc: Fix typo --- src/nix/registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/registry.md b/src/nix/registry.md index d5c9ef442..bd3575d1b 100644 --- a/src/nix/registry.md +++ b/src/nix/registry.md @@ -29,7 +29,7 @@ highest precedence: can be specified using the NixOS option `nix.registry`. * The user registry `~/.config/nix/registry.json`. This registry can - be modified by commands such as `nix flake pin`. + be modified by commands such as `nix registry pin`. * Overrides specified on the command line using the option `--override-flake`. -- cgit v1.2.3 From 711b2e1f48316d80853635408c518e3562a1fa37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Mon, 20 Jun 2022 04:15:38 +0200 Subject: Fix flake input completion for `InstallablesCommand`s Defers completion of flake inputs until the whole command line is parsed so that we know what flakes we need to complete the inputs of. Previously, `nix build flake --update-input ` always behaved like `nix build . --update-input `. --- src/nix/main.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index f398e3118..f6138cbe6 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -342,7 +342,10 @@ void mainWrapped(int argc, char * * argv) if (!completions) throw; } - if (completions) return; + if (completions) { + args.completionHook(); + return; + } if (args.showVersion) { printVersion(programName); -- cgit v1.2.3 From 8735f55decab03ecf3571f756a22abc3b3dc6304 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 14 Jul 2022 20:22:46 -0400 Subject: Fix bug, test more, document more --- src/nix/nix.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 32112d38d..5d669e8b1 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -134,8 +134,9 @@ the Nix store. Here are the recognised types of installables: *(Experimental, part of by the `computed-derivations` experimental feature.)* - Store derivations can be indexed with a specific output name. This - allows finer control versus just specifying a derivation (without + Store derivations can be indexed with a non-empty comma-separated list + of specific output names, or `*` meaning all ouptuts. This allows + finer control versus just specifying a derivation (without `--derivation`) and getting all the outputs. This is especially useful for (currently unstable) floating content -- cgit v1.2.3 From 04386f7d69d9c370eb4367ca41d89ac5990ac02e Mon Sep 17 00:00:00 2001 From: Jeremy Fleischman Date: Thu, 14 Jul 2022 23:11:02 -0700 Subject: nix develop: do not assume that saved vars are set This fixes https://github.com/NixOS/nix/issues/6809 --- src/nix/develop.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 6d9ad9942..ba7ba7c25 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -288,8 +288,10 @@ struct Common : InstallableCommand, MixProfile out << "unset shellHook\n"; - for (auto & var : savedVars) + for (auto & var : savedVars) { + out << fmt("%s=${%s:-}\n", var, var); out << fmt("nix_saved_%s=\"$%s\"\n", var, var); + } buildEnvironment.toBash(out, ignoreVars); -- cgit v1.2.3 From 279ecf7cdee94b3b5e37e4ade3af3a6d20ca9cde Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 15 Jul 2022 13:29:15 +0000 Subject: Remove `computed-derivations` experimental feature We don't need it yet. --- src/nix/nix.md | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 5d669e8b1..ede88ebde 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -132,8 +132,6 @@ the Nix store. Here are the recognised types of installables: * **Indexed store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^out` - *(Experimental, part of by the `computed-derivations` experimental feature.)* - Store derivations can be indexed with a non-empty comma-separated list of specific output names, or `*` meaning all ouptuts. This allows finer control versus just specifying a derivation (without -- cgit v1.2.3 From 0e4ec98ae8a4ec60b24ebd676a9ace0f4ca81da8 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 15 Jul 2022 09:49:23 -0400 Subject: Fix typo in docs Thanks! Co-authored-by: Eelco Dolstra --- src/nix/nix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index ede88ebde..29ad195ae 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -133,7 +133,7 @@ the Nix store. Here are the recognised types of installables: * **Indexed store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^out` Store derivations can be indexed with a non-empty comma-separated list - of specific output names, or `*` meaning all ouptuts. This allows + of specific output names, or `*` meaning all outputs. This allows finer control versus just specifying a derivation (without `--derivation`) and getting all the outputs. -- cgit v1.2.3 From 12461e246b02371c6b6981b4e65985e9397474e1 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 15 Jul 2022 13:59:32 +0000 Subject: Leverage existing docs for new store-path^outputs syntax --- src/nix/nix.md | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 29ad195ae..811936024 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -130,17 +130,6 @@ the Nix store. Here are the recognised types of installables: If you want to operate on the store derivation itself, pass the `--derivation` flag. -* **Indexed store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^out` - - Store derivations can be indexed with a non-empty comma-separated list - of specific output names, or `*` meaning all outputs. This allows - finer control versus just specifying a derivation (without - `--derivation`) and getting all the outputs. - - This is especially useful for (currently unstable) floating content - addressed derivations, which do not have precomputed output paths that - can be used instead. - * **Nix attributes**: `--file /path/to/nixpkgs hello` When the `-f` / `--file` *path* option is given, installables are @@ -175,6 +164,13 @@ operate are determined as follows: … ``` + and likewise, using a store path to a "drv" file to specify the derivation: + + ```console + # nix build '/nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^dev,static' + … + ``` + * You can also specify that *all* outputs should be used using the syntax *installable*`^*`. For example, the following shows the size of all outputs of the `glibc` package in the binary cache: @@ -188,9 +184,17 @@ operate are determined as follows: /nix/store/q6580lr01jpcsqs4r5arlh4ki2c1m9rv-glibc-2.33-123-dev 44200560 ``` -* If you didn't specify the desired outputs, but the derivation has an - attribute `meta.outputsToInstall`, Nix will use those outputs. For - example, since the package `nixpkgs#libxml2` has this attribute: + and likewise, again using a store path to a "drv" file to specify the derivation: + + ```console + # nix path-info -S --eval-store auto --store https://cache.nixos.org '/nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^*' + … + ``` + +* If you didn't specify the desired outputs, but the derivation comes + from an expression which has an attribute `meta.outputsToInstall`, Nix + will use those outputs. For example, since the package + `nixpkgs#libxml2` has this attribute: ```console # nix eval 'nixpkgs#libxml2.meta.outputsToInstall' -- cgit v1.2.3 From 64404220f54a36d3457433580ab8d78cf016572d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sol=C3=A8ne=20Rapenne?= Date: Wed, 20 Jul 2022 14:53:03 +0200 Subject: nix shell: document how to invoke multiple commands from the command line --- src/nix/shell.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/nix') diff --git a/src/nix/shell.md b/src/nix/shell.md index 90b81fb2f..161fdeb8d 100644 --- a/src/nix/shell.md +++ b/src/nix/shell.md @@ -23,6 +23,12 @@ R""( Hi everybody! ``` +* Run multiple commands in a shell environment: + + ```console + # nix shell nixpkgs#gnumake -c /bin/sh -c "cd src && make" + ``` + * Run GNU Hello in a chroot store: ```console -- cgit v1.2.3 From 92bae33ca5db60e729ce07156ebf1c06cf865cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sol=C3=A8ne=20Rapenne?= Date: Thu, 21 Jul 2022 14:25:07 +0200 Subject: nix shell: example shouldn't use an absolute path for the shell Co-authored-by: Eelco Dolstra --- src/nix/shell.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/shell.md b/src/nix/shell.md index 161fdeb8d..9fa1031f5 100644 --- a/src/nix/shell.md +++ b/src/nix/shell.md @@ -26,7 +26,7 @@ R""( * Run multiple commands in a shell environment: ```console - # nix shell nixpkgs#gnumake -c /bin/sh -c "cd src && make" + # nix shell nixpkgs#gnumake -c sh -c "cd src && make" ``` * Run GNU Hello in a chroot store: -- cgit v1.2.3 From 4c8441be0a59cead901acdfc3285d835c400c615 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Thu, 4 Aug 2022 09:45:30 +0200 Subject: docs/flake-update: fix example --- src/nix/flake-update.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/flake-update.md b/src/nix/flake-update.md index 03b50e38e..2ee8a707d 100644 --- a/src/nix/flake-update.md +++ b/src/nix/flake-update.md @@ -6,7 +6,7 @@ R""( lock file: ```console - # nix flake update + # nix flake update --commit-lock-file * Updated 'nix': 'github:NixOS/nix/9fab14adbc3810d5cc1f88672fde1eee4358405c' -> 'github:NixOS/nix/8927cba62f5afb33b01016d5c4f7f8b7d0adde3c' * Updated 'nixpkgs': 'github:NixOS/nixpkgs/3d2d8f281a27d466fa54b469b5993f7dde198375' -> 'github:NixOS/nixpkgs/a3a3dda3bacf61e8a39258a0ed9c924eeca8e293' … -- cgit v1.2.3 From b58785ab83166556934028465c189cf8694ca517 Mon Sep 17 00:00:00 2001 From: David Arnold Date: Wed, 10 Aug 2022 18:49:29 -0500 Subject: docfix: bundlers --- src/nix/bundle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/bundle.md b/src/nix/bundle.md index 2bb70711f..a18161a3c 100644 --- a/src/nix/bundle.md +++ b/src/nix/bundle.md @@ -44,7 +44,7 @@ flake output attributes: * `bundlers..default` -If an attribute *name* is given, `nix run` tries the following flake +If an attribute *name* is given, `nix bundle` tries the following flake output attributes: * `bundlers..` -- cgit v1.2.3 From e62160579f40a0425061c2223e0a303d42736ea2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 16 Aug 2022 14:58:08 +0200 Subject: nix flake metadata: Don't show "Inputs" if there are no inputs --- src/nix/flake.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index e01bc6d10..3967f1102 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -212,7 +212,8 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON ANSI_BOLD "Last modified:" ANSI_NORMAL " %s", std::put_time(std::localtime(&*lastModified), "%F %T")); - logger->cout(ANSI_BOLD "Inputs:" ANSI_NORMAL); + if (!lockedFlake.lockFile.root->inputs.empty()) + logger->cout(ANSI_BOLD "Inputs:" ANSI_NORMAL); std::unordered_set> visited; -- cgit v1.2.3 From 7d800909e94c482a2093bc95a2f3dca565c148b2 Mon Sep 17 00:00:00 2001 From: Jakub Kuczys Date: Sat, 20 Aug 2022 03:48:42 +0200 Subject: Fix default profile path for root in nix profile documentation --- src/nix/profile.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/profile.md b/src/nix/profile.md index 8dade051d..be3c5ba1a 100644 --- a/src/nix/profile.md +++ b/src/nix/profile.md @@ -11,7 +11,7 @@ them to be rolled back easily. The default profile used by `nix profile` is `$HOME/.nix-profile`, which, if it does not exist, is created as a symlink to -`/nix/var/nix/profiles/per-user/default` if Nix is invoked by the +`/nix/var/nix/profiles/default` if Nix is invoked by the `root` user, or `/nix/var/nix/profiles/per-user/`*username* otherwise. You can specify another profile location using `--profile` *path*. -- cgit v1.2.3 From 062e4fcdde145ec6780df8d1002dc7380f6eb4bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Tue, 16 Aug 2022 12:23:37 +0200 Subject: JSON: print paths as strings without copying them to the store Makes `printValueAsJSON` not copy paths to the store for `nix eval --json`, `nix-instantiate --eval --json` and `nix-env --json`. Fixes https://github.com/NixOS/nix/issues/5612 --- src/nix/eval.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 967dc8519..cc022ae43 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -116,7 +116,7 @@ struct CmdEval : MixJSON, InstallableCommand else if (json) { JSONPlaceholder jsonOut(std::cout); - printValueAsJSON(*state, true, *v, pos, jsonOut, context); + printValueAsJSON(*state, true, *v, pos, jsonOut, context, false); } else { -- cgit v1.2.3 From 4c2ff4a0f4c2106d5792a87a1ba9ee1fd18c0e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Mon, 22 Aug 2022 15:07:52 +0200 Subject: JSON: add missing newlines after `nix eval --json` and `nix-instantiate --eval --json`. --- src/nix/eval.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nix') diff --git a/src/nix/eval.cc b/src/nix/eval.cc index cc022ae43..ddd2790c6 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -117,6 +117,7 @@ struct CmdEval : MixJSON, InstallableCommand else if (json) { JSONPlaceholder jsonOut(std::cout); printValueAsJSON(*state, true, *v, pos, jsonOut, context, false); + std::cout << std::endl; } else { -- cgit v1.2.3 From db026103b18fb8b5a719594502edd0f89eb9c268 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 23 Aug 2022 14:57:08 +0200 Subject: nix develop: Ignore some more bash special variables Fixes #6940. --- src/nix/get-env.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/get-env.sh b/src/nix/get-env.sh index 42c806450..a7a8a01b9 100644 --- a/src/nix/get-env.sh +++ b/src/nix/get-env.sh @@ -43,6 +43,7 @@ __dumpEnv() { local __var_name="${BASH_REMATCH[2]}" if [[ $__var_name =~ ^BASH_ || \ + $__var_name =~ ^COMP_ || \ $__var_name = _ || \ $__var_name = DIRSTACK || \ $__var_name = EUID || \ @@ -54,7 +55,9 @@ __dumpEnv() { $__var_name = PWD || \ $__var_name = RANDOM || \ $__var_name = SHLVL || \ - $__var_name = SECONDS \ + $__var_name = SECONDS || \ + $__var_name = EPOCHREALTIME || \ + $__var_name = EPOCHSECONDS \ ]]; then continue; fi if [[ -z $__first ]]; then printf ',\n'; else __first=; fi -- cgit v1.2.3 From bb411e4ae16d6a5c61ea595c0c12e2ecee081ff9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 24 Aug 2022 22:36:40 +0200 Subject: Fix progress bar flicker with -L This was caused by -L calling setLogFormat() again, which caused the creation of a new progress bar without destroying the old one. So we had two progress bars clobbering each other. We should change 'logger' to be a smart pointer, but I'll do that in a future PR. Fixes #6931. --- src/nix/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index a8404a2ea..f434e9655 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -82,7 +82,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs .shortName = 'L', .description = "Print full build logs on standard error.", .category = loggingCategory, - .handler = {[&]() {setLogFormat(LogFormat::barWithLogs); }}, + .handler = {[&]() { logger->setPrintBuildLogs(true); }}, }); addFlag({ -- cgit v1.2.3 From 6ce2e96c88c71e40303980eb5793aa6ae4a5a333 Mon Sep 17 00:00:00 2001 From: Jonathan Ringer Date: Tue, 6 Sep 2022 08:18:13 -0700 Subject: Docs: Add nix develop --command entry Add example of nix develop being used to execuate a series of script commands. This is common when doing things like CI/CD, and should be represented in the official documentation. Also useful for people looking for the 'nix develop' equivalent of 'nix-shell --run'. Related: - https://github.com/NixOS/nix/issues/6908 - https://github.com/NixOS/nix/issues/6908#issuecomment-1229266853 --- src/nix/develop.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/nix') diff --git a/src/nix/develop.md b/src/nix/develop.md index e036ec6b9..4e8542d1b 100644 --- a/src/nix/develop.md +++ b/src/nix/develop.md @@ -66,6 +66,12 @@ R""( `nixpkgs#glibc` in `~/my-glibc` and want to compile another package against it. +* Run a series of script commands: + + ```console + # nix develop --command bash -c "mkdir build && cmake .. && make" + ``` + # Description `nix develop` starts a `bash` shell that provides an interactive build -- cgit v1.2.3 From 27be54ca533933db8c3e0cde4b213abf10dd5237 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 6 Sep 2022 18:27:39 +0200 Subject: nix develop: Ignore stdenv's $SHELL Stdenv sets this to a bash that doesn't have readline/completion support, so running 'nix (develop|shell)' inside a 'nix develop' gives you a crippled shell. So let's just ignore the derivation's $SHELL. This could break interactive use of build phases that use $SHELL, but they appear to be fairly rare. --- src/nix/develop.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nix') diff --git a/src/nix/develop.cc b/src/nix/develop.cc index ba7ba7c25..4de109754 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -246,6 +246,7 @@ struct Common : InstallableCommand, MixProfile "NIX_LOG_FD", "NIX_REMOTE", "PPID", + "SHELL", "SHELLOPTS", "SSL_CERT_FILE", // FIXME: only want to ignore /no-cert-file.crt "TEMP", -- cgit v1.2.3 From d365cced4fadbbc63f0c39902a7091e1a34c34de Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 13 Sep 2022 16:58:32 +0200 Subject: Trim option descriptions This removes unintended blank lines in Markdown when the description is a multiline string literal. --- src/nix/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index f434e9655..e0155cd5d 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -325,7 +325,7 @@ void mainWrapped(int argc, char * * argv) std::cout << "attrs\n"; break; } for (auto & s : *completions) - std::cout << s.completion << "\t" << s.description << "\n"; + std::cout << s.completion << "\t" << trim(s.description) << "\n"; } }); -- cgit v1.2.3 From 752f967c0fe2489fe13d8c2c65c3ecba72064adc Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 22 Sep 2022 10:43:48 -0400 Subject: "valid signature" -> "trustworthy signature" I just had a colleague get confused by the previous phrase for good reason. "valid" sounds like an *objective* criterion, e.g. and *invalid signature* would be one that would be trusted by no one, e.g. because it misformatted or something. What is actually going is that there might be a signature which is perfectly valid to *someone else*, but not to the user, because they don't trust the corresponding public key. This is a *subjective* criterion, because it depends on the arbitrary and personal choice of which public keys to trust. I therefore think "trustworthy" is a better adjective to use. Whether something is worthy of trust is clearly subjective, and then "trust" within that word nicely evokes `trusted-public-keys` and friends. --- src/nix/make-content-addressed.md | 2 +- src/nix/verify.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/make-content-addressed.md b/src/nix/make-content-addressed.md index 215683e6d..b0685bb6c 100644 --- a/src/nix/make-content-addressed.md +++ b/src/nix/make-content-addressed.md @@ -22,7 +22,7 @@ R""( ```console # nix copy --to /tmp/nix --trusted-public-keys '' nixpkgs#hello - cannot add path '/nix/store/zy9wbxwcygrwnh8n2w9qbbcr6zk87m26-libunistring-0.9.10' because it lacks a valid signature + cannot add path '/nix/store/zy9wbxwcygrwnh8n2w9qbbcr6zk87m26-libunistring-0.9.10' because it lacks a trustworthy signature ``` * Create a content-addressed representation of the current NixOS diff --git a/src/nix/verify.cc b/src/nix/verify.cc index e92df1303..6dc539e24 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -41,7 +41,7 @@ struct CmdVerify : StorePathsCommand addFlag({ .longName = "sigs-needed", .shortName = 'n', - .description = "Require that each path has at least *n* valid signatures.", + .description = "Require that each path has at least *n* trustworthy signatures.", .labels = {"n"}, .handler = {&sigsNeeded} }); -- cgit v1.2.3 From a2a8cb10ac17e03691b9f73ae14e5b6edbe66f4e Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 22 Sep 2022 14:36:26 -0400 Subject: Dodge "trusted" vs "trustworthy" by being explicit Hopefully this is best! --- src/nix/make-content-addressed.md | 2 +- src/nix/verify.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/make-content-addressed.md b/src/nix/make-content-addressed.md index b0685bb6c..32eecc880 100644 --- a/src/nix/make-content-addressed.md +++ b/src/nix/make-content-addressed.md @@ -22,7 +22,7 @@ R""( ```console # nix copy --to /tmp/nix --trusted-public-keys '' nixpkgs#hello - cannot add path '/nix/store/zy9wbxwcygrwnh8n2w9qbbcr6zk87m26-libunistring-0.9.10' because it lacks a trustworthy signature + cannot add path '/nix/store/zy9wbxwcygrwnh8n2w9qbbcr6zk87m26-libunistring-0.9.10' because it lacks a signature by a trusted key ``` * Create a content-addressed representation of the current NixOS diff --git a/src/nix/verify.cc b/src/nix/verify.cc index 6dc539e24..1ddedd320 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -41,7 +41,7 @@ struct CmdVerify : StorePathsCommand addFlag({ .longName = "sigs-needed", .shortName = 'n', - .description = "Require that each path has at least *n* trustworthy signatures.", + .description = "Require that each path has is signed by *n* different keys.", .labels = {"n"}, .handler = {&sigsNeeded} }); -- cgit v1.2.3 From 60e23c8baeb0e28ec163676b4fd4a24c40d89fe9 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 23 Sep 2022 13:57:57 -0400 Subject: Apply suggestions from code review Co-authored-by: Valentin Gagarin Co-authored-by: Rune K. Svendsen --- src/nix/verify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/verify.cc b/src/nix/verify.cc index 1ddedd320..efa2434dc 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -41,7 +41,7 @@ struct CmdVerify : StorePathsCommand addFlag({ .longName = "sigs-needed", .shortName = 'n', - .description = "Require that each path has is signed by *n* different keys.", + .description = "Require that each path is signed by at least *n* different keys.", .labels = {"n"}, .handler = {&sigsNeeded} }); -- cgit v1.2.3 From 069409d16787232dfbaac6a580d4e66d11bb5c86 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Fri, 7 Oct 2022 09:07:22 -0700 Subject: Print common flags in --help --- src/nix/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index e0155cd5d..006911216 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -187,7 +187,7 @@ static void showHelp(std::vector subcommand, MultiCommand & topleve *vUtils); auto attrs = state.buildBindings(16); - attrs.alloc("command").mkString(toplevel.toJSON().dump()); + attrs.alloc("toplevel").mkString(toplevel.toJSON().dump()); auto vRes = state.allocValue(); state.callFunction(*vGenerateManpage, state.allocValue()->mkAttrs(attrs), *vRes, noPos); -- cgit v1.2.3 From eba610956b088e0d881c44189ef3e0d613bbf922 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 12 Oct 2022 15:09:00 +0200 Subject: Move some options into a misc category This unclutters the per-command options a bit by moving out some global options. --- src/nix/main.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index 006911216..d78312944 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -74,6 +74,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs addFlag({ .longName = "help", .description = "Show usage information.", + .category = miscCategory, .handler = {[&]() { throw HelpRequested(); }}, }); @@ -88,6 +89,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs addFlag({ .longName = "version", .description = "Show version information.", + .category = miscCategory, .handler = {[&]() { showVersion = true; }}, }); @@ -95,12 +97,14 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs .longName = "offline", .aliases = {"no-net"}, // FIXME: remove .description = "Disable substituters and consider all previously downloaded files up-to-date.", + .category = miscCategory, .handler = {[&]() { useNet = false; }}, }); addFlag({ .longName = "refresh", .description = "Consider all previously downloaded files out-of-date.", + .category = miscCategory, .handler = {[&]() { refresh = true; }}, }); } -- cgit v1.2.3 From af9c9504ca8c2be9e9854e74a081743d882c8a8d Mon Sep 17 00:00:00 2001 From: Nathan Henrie Date: Mon, 17 Oct 2022 14:15:32 -0600 Subject: Fix typo -- dashes not underscores --- src/nix/repl.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/repl.md b/src/nix/repl.md index 23ef0f4e6..c5113be61 100644 --- a/src/nix/repl.md +++ b/src/nix/repl.md @@ -36,7 +36,7 @@ R""( Loading Installable ''... Added 1 variables. - # nix repl --extra_experimental_features 'flakes repl-flake' nixpkgs + # nix repl --extra-experimental-features 'flakes repl-flake' nixpkgs Loading Installable 'flake:nixpkgs#'... Added 5 variables. -- cgit v1.2.3 From 61f89e954af060c8dbdcd5a4fffcf023ac555686 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 18 Oct 2022 16:42:06 +0200 Subject: Add command 'nix store path-from-hash-part' This exposes the Store::queryPathFromHashPart() interface in the CLI. --- src/nix/path-from-hash-part.cc | 39 +++++++++++++++++++++++++++++++++++++++ src/nix/path-from-hash-part.md | 20 ++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/nix/path-from-hash-part.cc create mode 100644 src/nix/path-from-hash-part.md (limited to 'src/nix') diff --git a/src/nix/path-from-hash-part.cc b/src/nix/path-from-hash-part.cc new file mode 100644 index 000000000..7f7cda8d3 --- /dev/null +++ b/src/nix/path-from-hash-part.cc @@ -0,0 +1,39 @@ +#include "command.hh" +#include "store-api.hh" + +using namespace nix; + +struct CmdPathFromHashPart : StoreCommand +{ + std::string hashPart; + + CmdPathFromHashPart() + { + expectArgs({ + .label = "hash-part", + .handler = {&hashPart}, + }); + } + + std::string description() override + { + return "get a store path from its hash part"; + } + + std::string doc() override + { + return + #include "path-from-hash-part.md" + ; + } + + void run(ref store) override + { + if (auto storePath = store->queryPathFromHashPart(hashPart)) + logger->cout(store->printStorePath(*storePath)); + else + throw Error("there is no store path corresponding to '%s'", hashPart); + } +}; + +static auto rCmdPathFromHashPart = registerCommand2({"store", "path-from-hash-part"}); diff --git a/src/nix/path-from-hash-part.md b/src/nix/path-from-hash-part.md new file mode 100644 index 000000000..788e13ab6 --- /dev/null +++ b/src/nix/path-from-hash-part.md @@ -0,0 +1,20 @@ +R""( + +# Examples + +* Return the full store path with the given hash part: + + ```console + # nix store path-from-hash-part --store https://cache.nixos.org/ 0i2jd68mp5g6h2sa5k9c85rb80sn8hi9 + /nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10 + ``` + +# Description + +Given the hash part of a store path (that is, the 32 characters +following `/nix/store/`), return the full store path. This is +primarily useful in the implementation of binary caches, where a +request for a `.narinfo` file only supplies the hash part +(e.g. `https://cache.nixos.org/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9.narinfo`). + +)"" -- cgit v1.2.3 From aff6d10934f046066ed68b0d54fa077e726008e5 Mon Sep 17 00:00:00 2001 From: Yorick van Pelt Date: Wed, 26 Oct 2022 10:05:27 +0200 Subject: nix run: fix "'defaultApp.x86_64-linux' should have type 'derivation'" --- src/nix/app.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/app.cc b/src/nix/app.cc index 821964f86..48de8fb82 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -66,7 +66,9 @@ UnresolvedApp Installable::toApp(EvalState & state) auto type = cursor->getAttr("type")->getString(); - std::string expected = !attrPath.empty() && state.symbols[attrPath[0]] == "apps" ? "app" : "derivation"; + std::string expected = !attrPath.empty() && + (state.symbols[attrPath[0]] == "apps" || state.symbols[attrPath[0]] == "defaultApp") + ? "app" : "derivation"; if (type != expected) throw Error("attribute '%s' should have type '%s'", cursor->getAttrPathStr(), expected); -- cgit v1.2.3 From 9bff7e8ee26c97441858e1cea097f44c6db61235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophane=20Hufschmitt?= <7226587+thufschmitt@users.noreply.github.com> Date: Tue, 25 Oct 2022 21:17:32 +0200 Subject: Fix `nix __build-remote` Because of a wrong index, `nix __build-remote` wasn't working. Fix the index to restore the command (and the build hook). --- src/nix/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index d78312944..f8e93e367 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -270,7 +270,7 @@ void mainWrapped(int argc, char * * argv) programPath = argv[0]; auto programName = std::string(baseNameOf(programPath)); - if (argc > 0 && std::string_view(argv[0]) == "__build-remote") { + if (argc > 1 && std::string_view(argv[1]) == "__build-remote") { programName = "build-remote"; argv++; argc--; } -- cgit v1.2.3 From cd86eeb693342c79b01ff38ca723088dc1e42291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Roche?= Date: Fri, 28 Oct 2022 12:19:37 +0200 Subject: Move savedArgv into libmain `savedArgv` is not accessible by plugins when defined in main binary. Moving it into one of the nix lib fix the problem. --- src/nix/main.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/main.cc b/src/nix/main.cc index d78312944..956730276 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -53,7 +53,6 @@ static bool haveInternet() } std::string programPath; -char * * savedArgv; struct HelpRequested { }; -- cgit v1.2.3 From f7ab93b0685b653c60b86540639a42b03389c90b Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Sun, 6 Nov 2022 12:25:21 +0100 Subject: manual: build action -> build task after discussing this with multiple people, I'm convinced that "build task" is more precise: a derivation is not an action, but inert until it is built. also it's easier to pronounce. proposal: use "build task" for the generic concept "description of how to derive new files from the contents of existing files". then it will be easier to distinguish what we mean by "derivation" (a specific data structure and Nix language value type) and "store derivation" (a serialisation of a derivation into a file in the Nix store). --- src/nix/daemon.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/daemon.md b/src/nix/daemon.md index e97016a94..d5cdadf08 100644 --- a/src/nix/daemon.md +++ b/src/nix/daemon.md @@ -11,7 +11,7 @@ R""( # Description This command runs the Nix daemon, which is a required component in -multi-user Nix installations. It performs build actions and other +multi-user Nix installations. It runs build tasks and other operations on the Nix store on behalf of non-root users. Usually you don't run the daemon directly; instead it's managed by a service management framework such as `systemd`. -- cgit v1.2.3 From efadeee8fd593cd9457c75299165d5d5ac159d0f Mon Sep 17 00:00:00 2001 From: Et7f3 Date: Sat, 12 Nov 2022 23:04:58 +0100 Subject: build: use pkg-config for lowdown --- src/nix/local.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/local.mk b/src/nix/local.mk index e4ec7634d..0f2f016ec 100644 --- a/src/nix/local.mk +++ b/src/nix/local.mk @@ -18,7 +18,7 @@ nix_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libexpr nix_LIBS = libexpr libmain libfetchers libstore libutil libcmd -nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -llowdown +nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) $(foreach name, \ nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \ -- cgit v1.2.3 From 09f00dd4d01aa1b6866978d162022133e521614f Mon Sep 17 00:00:00 2001 From: Yorick van Pelt Date: Wed, 16 Nov 2022 16:49:49 +0100 Subject: Replace src/libutil/json.cc with nlohmann json generation --- src/nix/eval.cc | 7 ++-- src/nix/flake.cc | 37 +++++++++++++-------- src/nix/ls.cc | 5 ++- src/nix/make-content-addressed.cc | 12 ++++--- src/nix/path-info.cc | 8 ++--- src/nix/search.cc | 19 +++++++---- src/nix/show-derivation.cc | 67 ++++++++++++++++----------------------- 7 files changed, 80 insertions(+), 75 deletions(-) (limited to 'src/nix') diff --git a/src/nix/eval.cc b/src/nix/eval.cc index ddd2790c6..ba82b5772 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -4,10 +4,11 @@ #include "store-api.hh" #include "eval.hh" #include "eval-inline.hh" -#include "json.hh" #include "value-to-json.hh" #include "progress-bar.hh" +#include + using namespace nix; struct CmdEval : MixJSON, InstallableCommand @@ -115,9 +116,7 @@ struct CmdEval : MixJSON, InstallableCommand } else if (json) { - JSONPlaceholder jsonOut(std::cout); - printValueAsJSON(*state, true, *v, pos, jsonOut, context, false); - std::cout << std::endl; + std::cout << printValueAsJSON(*state, true, *v, pos, context, false).dump() << std::endl; } else { diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 3967f1102..336f6723a 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -11,7 +11,6 @@ #include "attr-path.hh" #include "fetchers.hh" #include "registry.hh" -#include "json.hh" #include "eval-cache.hh" #include "markdown.hh" @@ -21,6 +20,7 @@ using namespace nix; using namespace nix::flake; +using json = nlohmann::json; class FlakeCommand : virtual Args, public MixFlakeOptions { @@ -917,35 +917,44 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun { auto flake = lockFlake(); - auto jsonRoot = json ? std::optional(std::cout) : std::nullopt; - StorePathSet sources; sources.insert(flake.flake.sourceInfo->storePath); - if (jsonRoot) - jsonRoot->attr("path", store->printStorePath(flake.flake.sourceInfo->storePath)); // FIXME: use graph output, handle cycles. - std::function & jsonObj)> traverse; - traverse = [&](const Node & node, std::optional & jsonObj) + std::function traverse; + traverse = [&](const Node & node) { - auto jsonObj2 = jsonObj ? jsonObj->object("inputs") : std::optional(); + nlohmann::json jsonObj2 = json ? json::object() : nlohmann::json(nullptr); for (auto & [inputName, input] : node.inputs) { if (auto inputNode = std::get_if<0>(&input)) { - auto jsonObj3 = jsonObj2 ? jsonObj2->object(inputName) : std::optional(); auto storePath = dryRun ? (*inputNode)->lockedRef.input.computeStorePath(*store) : (*inputNode)->lockedRef.input.fetch(store).first.storePath; - if (jsonObj3) - jsonObj3->attr("path", store->printStorePath(storePath)); - sources.insert(std::move(storePath)); - traverse(**inputNode, jsonObj3); + if (json) { + auto& jsonObj3 = jsonObj2[inputName]; + jsonObj3["path"] = store->printStorePath(storePath); + sources.insert(std::move(storePath)); + jsonObj3["inputs"] = traverse(**inputNode); + } else { + sources.insert(std::move(storePath)); + traverse(**inputNode); + } } } + return jsonObj2; }; - traverse(*flake.lockFile.root, jsonRoot); + if (json) { + nlohmann::json jsonRoot = { + {"path", store->printStorePath(flake.flake.sourceInfo->storePath)}, + {"inputs", traverse(*flake.lockFile.root)}, + }; + std::cout << jsonRoot.dump() << std::endl; + } else { + traverse(*flake.lockFile.root); + } if (!dryRun && !dstUri.empty()) { ref dstStore = dstUri.empty() ? openStore() : openStore(dstUri); diff --git a/src/nix/ls.cc b/src/nix/ls.cc index 07554994b..e964b01b3 100644 --- a/src/nix/ls.cc +++ b/src/nix/ls.cc @@ -3,7 +3,7 @@ #include "fs-accessor.hh" #include "nar-accessor.hh" #include "common-args.hh" -#include "json.hh" +#include using namespace nix; @@ -91,10 +91,9 @@ struct MixLs : virtual Args, MixJSON if (path == "/") path = ""; if (json) { - JSONPlaceholder jsonRoot(std::cout); if (showDirectory) throw UsageError("'--directory' is useless with '--json'"); - listNar(jsonRoot, accessor, path, recursive); + std::cout << listNar(accessor, path, recursive); } else listText(accessor); } diff --git a/src/nix/make-content-addressed.cc b/src/nix/make-content-addressed.cc index 34860c38f..f2e4cefbe 100644 --- a/src/nix/make-content-addressed.cc +++ b/src/nix/make-content-addressed.cc @@ -2,10 +2,13 @@ #include "store-api.hh" #include "make-content-addressed.hh" #include "common-args.hh" -#include "json.hh" + +#include using namespace nix; +using nlohmann::json; + struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, MixJSON { CmdMakeContentAddressed() @@ -25,6 +28,7 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, ; } + using StorePathsCommand::run; void run(ref srcStore, StorePaths && storePaths) override { auto dstStore = dstUri.empty() ? openStore() : openStore(dstUri); @@ -33,13 +37,13 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, StorePathSet(storePaths.begin(), storePaths.end())); if (json) { - JSONObject jsonRoot(std::cout); - JSONObject jsonRewrites(jsonRoot.object("rewrites")); + nlohmann::json jsonRewrites = json::object(); for (auto & path : storePaths) { auto i = remappings.find(path); assert(i != remappings.end()); - jsonRewrites.attr(srcStore->printStorePath(path), srcStore->printStorePath(i->second)); + jsonRewrites[srcStore->printStorePath(path)] = srcStore->printStorePath(i->second); } + std::cout << json::object({"rewrites", jsonRewrites}).dump(); } else { for (auto & path : storePaths) { auto i = remappings.find(path); diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc index d690fe594..613c5b191 100644 --- a/src/nix/path-info.cc +++ b/src/nix/path-info.cc @@ -1,12 +1,13 @@ #include "command.hh" #include "shared.hh" #include "store-api.hh" -#include "json.hh" #include "common-args.hh" #include #include +#include + using namespace nix; struct CmdPathInfo : StorePathsCommand, MixJSON @@ -86,11 +87,10 @@ struct CmdPathInfo : StorePathsCommand, MixJSON pathLen = std::max(pathLen, store->printStorePath(storePath).size()); if (json) { - JSONPlaceholder jsonRoot(std::cout); - store->pathInfoToJSON(jsonRoot, + std::cout << store->pathInfoToJSON( // FIXME: preserve order? StorePathSet(storePaths.begin(), storePaths.end()), - true, showClosureSize, SRI, AllowInvalid); + true, showClosureSize, SRI, AllowInvalid).dump(); } else { diff --git a/src/nix/search.cc b/src/nix/search.cc index bdd45cbed..d2a31607d 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -5,7 +5,6 @@ #include "names.hh" #include "get-drvs.hh" #include "common-args.hh" -#include "json.hh" #include "shared.hh" #include "eval-cache.hh" #include "attr-path.hh" @@ -13,8 +12,10 @@ #include #include +#include using namespace nix; +using json = nlohmann::json; std::string wrap(std::string prefix, std::string s) { @@ -84,7 +85,8 @@ struct CmdSearch : InstallableCommand, MixJSON auto state = getEvalState(); - auto jsonOut = json ? std::make_unique(std::cout) : nullptr; + std::optional jsonOut; + if (json) jsonOut = json::object(); uint64_t results = 0; @@ -151,10 +153,11 @@ struct CmdSearch : InstallableCommand, MixJSON { results++; if (json) { - auto jsonElem = jsonOut->object(attrPath2); - jsonElem.attr("pname", name.name); - jsonElem.attr("version", name.version); - jsonElem.attr("description", description); + (*jsonOut)[attrPath2] = { + {"pname", name.name}, + {"version", name.version}, + {"description", description}, + }; } else { auto name2 = hiliteMatches(name.name, nameMatches, ANSI_GREEN, "\e[0;2m"); if (results > 1) logger->cout(""); @@ -193,6 +196,10 @@ struct CmdSearch : InstallableCommand, MixJSON for (auto & cursor : installable->getCursors(*state)) visit(*cursor, cursor->getAttrPath(), true); + if (json) { + std::cout << jsonOut->dump() << std::endl; + } + if (!json && !results) throw Error("no results for the given search term(s)!"); } diff --git a/src/nix/show-derivation.cc b/src/nix/show-derivation.cc index fb46b4dbf..af2e676a4 100644 --- a/src/nix/show-derivation.cc +++ b/src/nix/show-derivation.cc @@ -5,10 +5,11 @@ #include "common-args.hh" #include "store-api.hh" #include "archive.hh" -#include "json.hh" #include "derivations.hh" +#include using namespace nix; +using json = nlohmann::json; struct CmdShowDerivation : InstallablesCommand { @@ -48,77 +49,63 @@ struct CmdShowDerivation : InstallablesCommand drvPaths = std::move(closure); } - { - - JSONObject jsonRoot(std::cout, true); + json jsonRoot = json::object(); for (auto & drvPath : drvPaths) { if (!drvPath.isDerivation()) continue; - auto drvObj(jsonRoot.object(store->printStorePath(drvPath))); + json& drvObj = jsonRoot[store->printStorePath(drvPath)]; auto drv = store->readDerivation(drvPath); { - auto outputsObj(drvObj.object("outputs")); + json& outputsObj = drvObj["outputs"]; + outputsObj = json::object(); for (auto & [_outputName, output] : drv.outputs) { auto & outputName = _outputName; // work around clang bug - auto outputObj { outputsObj.object(outputName) }; + auto& outputObj = outputsObj[outputName]; + outputObj = json::object(); std::visit(overloaded { [&](const DerivationOutput::InputAddressed & doi) { - outputObj.attr("path", store->printStorePath(doi.path)); + outputObj["path"] = store->printStorePath(doi.path); }, [&](const DerivationOutput::CAFixed & dof) { - outputObj.attr("path", store->printStorePath(dof.path(*store, drv.name, outputName))); - outputObj.attr("hashAlgo", dof.hash.printMethodAlgo()); - outputObj.attr("hash", dof.hash.hash.to_string(Base16, false)); + outputObj["path"] = store->printStorePath(dof.path(*store, drv.name, outputName)); + outputObj["hashAlgo"] = dof.hash.printMethodAlgo(); + outputObj["hash"] = dof.hash.hash.to_string(Base16, false); }, [&](const DerivationOutput::CAFloating & dof) { - outputObj.attr("hashAlgo", makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType)); + outputObj["hashAlgo"] = makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType); }, [&](const DerivationOutput::Deferred &) {}, [&](const DerivationOutput::Impure & doi) { - outputObj.attr("hashAlgo", makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType)); - outputObj.attr("impure", true); + outputObj["hashAlgo"] = makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType); + outputObj["impure"] = true; }, }, output.raw()); } } { - auto inputsList(drvObj.list("inputSrcs")); + auto& inputsList = drvObj["inputSrcs"]; + inputsList = json::array(); for (auto & input : drv.inputSrcs) - inputsList.elem(store->printStorePath(input)); - } - - { - auto inputDrvsObj(drvObj.object("inputDrvs")); - for (auto & input : drv.inputDrvs) { - auto inputList(inputDrvsObj.list(store->printStorePath(input.first))); - for (auto & outputId : input.second) - inputList.elem(outputId); - } + inputsList.emplace_back(store->printStorePath(input)); } - drvObj.attr("system", drv.platform); - drvObj.attr("builder", drv.builder); - { - auto argsList(drvObj.list("args")); - for (auto & arg : drv.args) - argsList.elem(arg); + auto& inputDrvsObj = drvObj["inputDrvs"]; + inputDrvsObj = json::object(); + for (auto & input : drv.inputDrvs) + inputDrvsObj[store->printStorePath(input.first)] = input.second; } - { - auto envObj(drvObj.object("env")); - for (auto & var : drv.env) - envObj.attr(var.first, var.second); - } + drvObj["system"] = drv.platform; + drvObj["builder"] = drv.builder; + drvObj["args"] = drv.args; + drvObj["env"] = drv.env; } - - } - - std::cout << "\n"; + std::cout << jsonRoot.dump(2) << std::endl; } }; -- cgit v1.2.3 From f538ee434285304cb61cf10bf13127f13bfced1b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 21 Nov 2022 09:38:08 +0100 Subject: Rename derivedPathsWithHintsToJSON -> builtPathsToJSON --- src/nix/build.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/build.cc b/src/nix/build.cc index 9c648d28e..2b91f8e0a 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -78,7 +78,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile Realise::Outputs, installables, buildMode); - if (json) logger->cout("%s", derivedPathsWithHintsToJSON(buildables, store).dump()); + if (json) logger->cout("%s", builtPathsToJSON(buildables, store).dump()); if (outLink != "") if (auto store2 = store.dynamic_pointer_cast()) -- cgit v1.2.3 From 300753d594fd7cd818d08f9c7a18a9ebc305bd95 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 21 Nov 2022 10:49:01 +0100 Subject: nix build --json: Include build statistics Example: # nix build -L --extra-experimental-features cgroups --impure --expr 'with import {}; runCommand "foo" {} "dd if=/dev/urandom bs=1M count=1024 | md5sum; mkdir $out"' --json [ { "cpuSystem": 1.911431, "cpuUser": 1.214249, "drvPath": "/nix/store/xzdqz67xba18hljhycp0hwfigzrs2z69-foo.drv", "outputs": { "out": "/nix/store/rh9mc9l2gkpq8kn2sgzndr6ll7ffjh6l-foo" }, "startTime": 1669024076, "stopTime": 1669024079 } ] --- src/nix/app.cc | 11 ++++++++--- src/nix/build.cc | 42 ++++++++++++++++++++++++++++++++++++++---- src/nix/profile.cc | 4 ++-- 3 files changed, 48 insertions(+), 9 deletions(-) (limited to 'src/nix') diff --git a/src/nix/app.cc b/src/nix/app.cc index 48de8fb82..5658f2a52 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -37,11 +37,13 @@ struct InstallableDerivedPath : Installable * Return the rewrites that are needed to resolve a string whose context is * included in `dependencies`. */ -StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies) +StringPairs resolveRewrites( + Store & store, + const std::vector & dependencies) { StringPairs res; for (auto & dep : dependencies) - if (auto drvDep = std::get_if(&dep)) + if (auto drvDep = std::get_if(&dep.path)) for (auto & [ outputName, outputPath ] : drvDep->outputs) res.emplace( downstreamPlaceholder(store, drvDep->drvPath, outputName), @@ -53,7 +55,10 @@ StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies) /** * Resolve the given string assuming the given context. */ -std::string resolveString(Store & store, const std::string & toResolve, const BuiltPaths dependencies) +std::string resolveString( + Store & store, + const std::string & toResolve, + const std::vector & dependencies) { auto rewrites = resolveRewrites(store, dependencies); return rewriteStrings(toResolve, rewrites); diff --git a/src/nix/build.cc b/src/nix/build.cc index 2b91f8e0a..94b169167 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -10,6 +10,37 @@ using namespace nix; +nlohmann::json derivedPathsToJSON(const DerivedPaths & paths, ref store) +{ + auto res = nlohmann::json::array(); + for (auto & t : paths) { + std::visit([&res, store](const auto & t) { + res.push_back(t.toJSON(store)); + }, t.raw()); + } + return res; +} + +nlohmann::json builtPathsWithResultToJSON(const std::vector & buildables, ref store) +{ + auto res = nlohmann::json::array(); + for (auto & b : buildables) { + std::visit([&](const auto & t) { + auto j = t.toJSON(store); + if (b.result) { + j["startTime"] = b.result->startTime; + j["stopTime"] = b.result->stopTime; + if (b.result->cpuUser) + j["cpuUser"] = ((double) b.result->cpuUser->count()) / 1000000; + if (b.result->cpuSystem) + j["cpuSystem"] = ((double) b.result->cpuSystem->count()) / 1000000; + } + res.push_back(j); + }, b.path.raw()); + } + return res; +} + struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile { Path outLink = "result"; @@ -78,7 +109,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile Realise::Outputs, installables, buildMode); - if (json) logger->cout("%s", builtPathsToJSON(buildables, store).dump()); + if (json) logger->cout("%s", builtPathsWithResultToJSON(buildables, store).dump()); if (outLink != "") if (auto store2 = store.dynamic_pointer_cast()) @@ -98,7 +129,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile store2->addPermRoot(output.second, absPath(symlink)); } }, - }, buildable.raw()); + }, buildable.path.raw()); } if (printOutputPaths) { @@ -113,11 +144,14 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile std::cout << store->printStorePath(output.second) << std::endl; } }, - }, buildable.raw()); + }, buildable.path.raw()); } } - updateProfile(buildables); + BuiltPaths buildables2; + for (auto & b : buildables) + buildables2.push_back(b.path); + updateProfile(buildables2); } }; diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 3814e7d5a..11910523d 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -253,11 +253,11 @@ struct ProfileManifest static std::map builtPathsPerInstallable( - const std::vector, BuiltPath>> & builtPaths) + const std::vector, BuiltPathWithResult>> & builtPaths) { std::map res; for (auto & [installable, builtPath] : builtPaths) - res[installable.get()].push_back(builtPath); + res[installable.get()].push_back(builtPath.path); return res; } -- cgit v1.2.3 From e7a5b76844a649645e51a60dd18fd383d14d8755 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 21 Nov 2022 09:38:08 +0100 Subject: Rename derivedPathsWithHintsToJSON -> builtPathsToJSON --- src/nix/build.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/build.cc b/src/nix/build.cc index 9c648d28e..2b91f8e0a 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -78,7 +78,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile Realise::Outputs, installables, buildMode); - if (json) logger->cout("%s", derivedPathsWithHintsToJSON(buildables, store).dump()); + if (json) logger->cout("%s", builtPathsToJSON(buildables, store).dump()); if (outLink != "") if (auto store2 = store.dynamic_pointer_cast()) -- cgit v1.2.3 From f0baa5c1283359a413ca3a254527587c86b2f097 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 21 Nov 2022 10:49:01 +0100 Subject: nix build --json: Include build statistics Example: # nix build -L --extra-experimental-features cgroups --impure --expr 'with import {}; runCommand "foo" {} "dd if=/dev/urandom bs=1M count=1024 | md5sum; mkdir $out"' --json [ { "cpuSystem": 1.911431, "cpuUser": 1.214249, "drvPath": "/nix/store/xzdqz67xba18hljhycp0hwfigzrs2z69-foo.drv", "outputs": { "out": "/nix/store/rh9mc9l2gkpq8kn2sgzndr6ll7ffjh6l-foo" }, "startTime": 1669024076, "stopTime": 1669024079 } ] --- src/nix/app.cc | 11 ++++++++--- src/nix/build.cc | 38 ++++++++++++++++++++++++++++++++++---- src/nix/profile.cc | 4 ++-- 3 files changed, 44 insertions(+), 9 deletions(-) (limited to 'src/nix') diff --git a/src/nix/app.cc b/src/nix/app.cc index 48de8fb82..5658f2a52 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -37,11 +37,13 @@ struct InstallableDerivedPath : Installable * Return the rewrites that are needed to resolve a string whose context is * included in `dependencies`. */ -StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies) +StringPairs resolveRewrites( + Store & store, + const std::vector & dependencies) { StringPairs res; for (auto & dep : dependencies) - if (auto drvDep = std::get_if(&dep)) + if (auto drvDep = std::get_if(&dep.path)) for (auto & [ outputName, outputPath ] : drvDep->outputs) res.emplace( downstreamPlaceholder(store, drvDep->drvPath, outputName), @@ -53,7 +55,10 @@ StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies) /** * Resolve the given string assuming the given context. */ -std::string resolveString(Store & store, const std::string & toResolve, const BuiltPaths dependencies) +std::string resolveString( + Store & store, + const std::string & toResolve, + const std::vector & dependencies) { auto rewrites = resolveRewrites(store, dependencies); return rewriteStrings(toResolve, rewrites); diff --git a/src/nix/build.cc b/src/nix/build.cc index 2b91f8e0a..85b1efc33 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -10,6 +10,33 @@ using namespace nix; +nlohmann::json derivedPathsToJSON(const DerivedPaths & paths, ref store) +{ + auto res = nlohmann::json::array(); + for (auto & t : paths) { + std::visit([&res, store](const auto & t) { + res.push_back(t.toJSON(store)); + }, t.raw()); + } + return res; +} + +nlohmann::json builtPathsWithResultToJSON(const std::vector & buildables, ref store) +{ + auto res = nlohmann::json::array(); + for (auto & b : buildables) { + std::visit([&](const auto & t) { + auto j = t.toJSON(store); + if (b.result) { + j["startTime"] = b.result->startTime; + j["stopTime"] = b.result->stopTime; + } + res.push_back(j); + }, b.path.raw()); + } + return res; +} + struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile { Path outLink = "result"; @@ -78,7 +105,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile Realise::Outputs, installables, buildMode); - if (json) logger->cout("%s", builtPathsToJSON(buildables, store).dump()); + if (json) logger->cout("%s", builtPathsWithResultToJSON(buildables, store).dump()); if (outLink != "") if (auto store2 = store.dynamic_pointer_cast()) @@ -98,7 +125,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile store2->addPermRoot(output.second, absPath(symlink)); } }, - }, buildable.raw()); + }, buildable.path.raw()); } if (printOutputPaths) { @@ -113,11 +140,14 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile std::cout << store->printStorePath(output.second) << std::endl; } }, - }, buildable.raw()); + }, buildable.path.raw()); } } - updateProfile(buildables); + BuiltPaths buildables2; + for (auto & b : buildables) + buildables2.push_back(b.path); + updateProfile(buildables2); } }; diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 3814e7d5a..11910523d 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -253,11 +253,11 @@ struct ProfileManifest static std::map builtPathsPerInstallable( - const std::vector, BuiltPath>> & builtPaths) + const std::vector, BuiltPathWithResult>> & builtPaths) { std::map res; for (auto & [installable, builtPath] : builtPaths) - res[installable.get()].push_back(builtPath); + res[installable.get()].push_back(builtPath.path); return res; } -- cgit v1.2.3 From b13fd4c58e81b2b2b0d72caa5ce80de861622610 Mon Sep 17 00:00:00 2001 From: Taeer Bar-Yam Date: Wed, 23 Nov 2022 11:39:50 -0500 Subject: Fix why-depends for CA derivations why-depends assumed that we knew the output path of the second argument. For CA derivations, we might not know until it's built. One way to solve this would be to build the second installable to get the output path. In this case we don't need to, though. If the first installable (A) depends on the second (B), then getting the store path of A will necessitate having the store path B. The contrapositive is, if the store path of B is not known (i.e. it's a CA derivation which hasn't been built), then A does not depend on B. --- src/nix/why-depends.cc | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'src/nix') diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc index 1d9ab28ba..285e36722 100644 --- a/src/nix/why-depends.cc +++ b/src/nix/why-depends.cc @@ -84,19 +84,35 @@ struct CmdWhyDepends : SourceExprCommand auto package = parseInstallable(store, _package); auto packagePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package); auto dependency = parseInstallable(store, _dependency); - auto dependencyPath = Installable::toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency); - auto dependencyPathHash = dependencyPath.hashPart(); + auto derivedDependency = dependency->toDerivedPath(); + auto optDependencyPath = std::visit(overloaded { + [](const DerivedPath::Opaque & nodrv) -> std::optional { + return { nodrv.path }; + }, + [&](const DerivedPath::Built & hasdrv) -> std::optional { + if (hasdrv.outputs.size() != 1) { + throw Error("argument '%s' should evaluate to one store path", dependency->what()); + } + auto outputMap = store->queryPartialDerivationOutputMap(hasdrv.drvPath); + auto maybePath = outputMap.find(*hasdrv.outputs.begin()); + if (maybePath == outputMap.end()) { + throw Error("unexpected end of iterator"); + } + return maybePath->second; + }, + }, derivedDependency.raw()); StorePathSet closure; store->computeFSClosure({packagePath}, closure, false, false); - if (!closure.count(dependencyPath)) { - printError("'%s' does not depend on '%s'", - store->printStorePath(packagePath), - store->printStorePath(dependencyPath)); + if (!optDependencyPath.has_value() || !closure.count(*optDependencyPath)) { + printError("'%s' does not depend on '%s'", package->what(), dependency->what()); return; } + auto dependencyPath = *optDependencyPath; + auto dependencyPathHash = dependencyPath.hashPart(); + stopProgressBar(); // FIXME auto accessor = store->getFSAccessor(); -- cgit v1.2.3 From bd8571a5c3724ba5917564a5243af173966515c5 Mon Sep 17 00:00:00 2001 From: Taeer Bar-Yam Date: Wed, 23 Nov 2022 12:06:47 -0500 Subject: add explanation and test --- src/nix/why-depends.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/nix') diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc index 285e36722..723017497 100644 --- a/src/nix/why-depends.cc +++ b/src/nix/why-depends.cc @@ -83,6 +83,17 @@ struct CmdWhyDepends : SourceExprCommand { auto package = parseInstallable(store, _package); auto packagePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package); + + /* We don't need to build `dependency`. We try to get the store + * path if it's already known, and if not, then it's not a dependency. + * + * Why? If `package` does depends on `dependency`, then getting the + * store path of `package` above necessitated having the store path + * of `dependency`. The contrapositive is, if the store path of + * `dependency` is not already known at this point (i.e. it's a CA + * derivation which hasn't been built), then `package` did not need it + * to build. + */ auto dependency = parseInstallable(store, _dependency); auto derivedDependency = dependency->toDerivedPath(); auto optDependencyPath = std::visit(overloaded { -- cgit v1.2.3 From 0b092bd87f35e463fea66ddd40639e7b260680a0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 30 Nov 2022 13:46:33 +0100 Subject: nix store make-content-addressed: Fix JSON construction Fixes error: [json.exception.type_error.301] cannot create object from initializer list in tests/fetchClosure.sh. --- src/nix/make-content-addressed.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/make-content-addressed.cc b/src/nix/make-content-addressed.cc index f2e4cefbe..f236bebd6 100644 --- a/src/nix/make-content-addressed.cc +++ b/src/nix/make-content-addressed.cc @@ -43,7 +43,7 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, assert(i != remappings.end()); jsonRewrites[srcStore->printStorePath(path)] = srcStore->printStorePath(i->second); } - std::cout << json::object({"rewrites", jsonRewrites}).dump(); + std::cout << nlohmann::json{"rewrites", jsonRewrites}.dump(); } else { for (auto & path : storePaths) { auto i = remappings.find(path); -- cgit v1.2.3 From f1e1ba9fe094a774f0fd05e537228e628d0bc8cb Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 1 Dec 2022 16:29:09 +0100 Subject: Really fix 'nix store make-content-addressed --json' https://hydra.nixos.org/log/mcgypcf9vj4n8vdmw7lj3l05c899v73w-nix-2.12.0pre20221201_16b03f0-x86_64-unknown-linux-musl.drv --- src/nix/make-content-addressed.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/make-content-addressed.cc b/src/nix/make-content-addressed.cc index f236bebd6..d86b90fc7 100644 --- a/src/nix/make-content-addressed.cc +++ b/src/nix/make-content-addressed.cc @@ -37,13 +37,15 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, StorePathSet(storePaths.begin(), storePaths.end())); if (json) { - nlohmann::json jsonRewrites = json::object(); + auto jsonRewrites = json::object(); for (auto & path : storePaths) { auto i = remappings.find(path); assert(i != remappings.end()); jsonRewrites[srcStore->printStorePath(path)] = srcStore->printStorePath(i->second); } - std::cout << nlohmann::json{"rewrites", jsonRewrites}.dump(); + auto json = json::object(); + json["rewrites"] = jsonRewrites; + std::cout << json.dump(); } else { for (auto & path : storePaths) { auto i = remappings.find(path); -- cgit v1.2.3 From e0ab2069c975abf80db9fdca23f0c164df921829 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 5 Dec 2022 16:55:55 +0100 Subject: Consistent capitalisation --- src/nix/eval.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 5dedf02c2..23fef7c68 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -111,7 +111,7 @@ struct CmdEval : MixJSON, InstallableCommand else if (raw) { stopProgressBar(); - std::cout << *state->coerceToString(noPos, *v, context, "While generating the eval command output"); + std::cout << *state->coerceToString(noPos, *v, context, "while generating the eval command output"); } else if (json) { -- cgit v1.2.3 From 703d863a48f549b2626382eda407ffae779f8725 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 7 Dec 2022 12:58:58 +0100 Subject: Trivial changes from the lazy-trees branch --- src/nix/daemon.cc | 2 +- src/nix/flake-update.md | 2 +- src/nix/flake.cc | 4 ++-- src/nix/profile-list.md | 6 +++--- src/nix/profile-upgrade.md | 6 +++--- src/nix/profile.md | 3 +-- src/nix/registry.cc | 8 +++----- 7 files changed, 14 insertions(+), 17 deletions(-) (limited to 'src/nix') diff --git a/src/nix/daemon.cc b/src/nix/daemon.cc index 940923d3b..c527fdb0a 100644 --- a/src/nix/daemon.cc +++ b/src/nix/daemon.cc @@ -257,7 +257,7 @@ static void daemonLoop() } catch (Interrupted & e) { return; } catch (Error & error) { - ErrorInfo ei = error.info(); + auto ei = error.info(); // FIXME: add to trace? ei.msg = hintfmt("error processing connection: %1%", ei.msg.str()); logError(ei); diff --git a/src/nix/flake-update.md b/src/nix/flake-update.md index 2ee8a707d..8c6042d94 100644 --- a/src/nix/flake-update.md +++ b/src/nix/flake-update.md @@ -16,7 +16,7 @@ R""( # Description This command recreates the lock file of a flake (`flake.lock`), thus -updating the lock for every mutable input (like `nixpkgs`) to its +updating the lock for every unlocked input (like `nixpkgs`) to its current version. This is equivalent to passing `--recreate-lock-file` to any command that operates on a flake. That is, diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 336f6723a..96f035117 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -215,7 +215,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON if (!lockedFlake.lockFile.root->inputs.empty()) logger->cout(ANSI_BOLD "Inputs:" ANSI_NORMAL); - std::unordered_set> visited; + std::set> visited; std::function recurse; @@ -227,7 +227,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON if (auto lockedNode = std::get_if<0>(&input.second)) { logger->cout("%s" ANSI_BOLD "%s" ANSI_NORMAL ": %s", prefix + (last ? treeLast : treeConn), input.first, - *lockedNode ? (*lockedNode)->lockedRef : flake.lockedRef); + (*lockedNode)->lockedRef); bool firstVisit = visited.insert(*lockedNode).second; diff --git a/src/nix/profile-list.md b/src/nix/profile-list.md index bdab9a208..fa786162f 100644 --- a/src/nix/profile-list.md +++ b/src/nix/profile-list.md @@ -20,11 +20,11 @@ following fields: * An integer that can be used to unambiguously identify the package in invocations of `nix profile remove` and `nix profile upgrade`. -* The original ("mutable") flake reference and output attribute path +* The original ("unlocked") flake reference and output attribute path used at installation time. -* The immutable flake reference to which the mutable flake reference - was resolved. +* The locked flake reference to which the unlocked flake reference was + resolved. * The store path(s) of the package. diff --git a/src/nix/profile-upgrade.md b/src/nix/profile-upgrade.md index e06e74abe..39cca428b 100644 --- a/src/nix/profile-upgrade.md +++ b/src/nix/profile-upgrade.md @@ -2,7 +2,7 @@ R""( # Examples -* Upgrade all packages that were installed using a mutable flake +* Upgrade all packages that were installed using an unlocked flake reference: ```console @@ -32,9 +32,9 @@ the package was installed. > **Warning** > -> This only works if you used a *mutable* flake reference at +> This only works if you used an *unlocked* flake reference at > installation time, e.g. `nixpkgs#hello`. It does not work if you -> used an *immutable* flake reference +> used a *locked* flake reference > (e.g. `github:NixOS/nixpkgs/13d0c311e3ae923a00f734b43fd1d35b47d8943a#hello`), > since in that case the "latest version" is always the same. diff --git a/src/nix/profile.md b/src/nix/profile.md index be3c5ba1a..273e02280 100644 --- a/src/nix/profile.md +++ b/src/nix/profile.md @@ -88,8 +88,7 @@ has the following fields: the user at the time of installation (e.g. `nixpkgs`). This is also the flake reference that will be used by `nix profile upgrade`. -* `uri`: The immutable flake reference to which `originalUrl` - resolved. +* `uri`: The locked flake reference to which `originalUrl` resolved. * `attrPath`: The flake output attribute that provided this package. Note that this is not necessarily the attribute that the diff --git a/src/nix/registry.cc b/src/nix/registry.cc index c496f94f8..b5bdfba95 100644 --- a/src/nix/registry.cc +++ b/src/nix/registry.cc @@ -183,14 +183,12 @@ struct CmdRegistryPin : RegistryCommand, EvalCommand void run(nix::ref store) override { - if (locked.empty()) { - locked = url; - } + if (locked.empty()) locked = url; auto registry = getRegistry(); auto ref = parseFlakeRef(url); - auto locked_ref = parseFlakeRef(locked); + auto lockedRef = parseFlakeRef(locked); registry->remove(ref.input); - auto [tree, resolved] = locked_ref.resolve(store).input.fetch(store); + auto [tree, resolved] = lockedRef.resolve(store).input.fetch(store); fetchers::Attrs extraAttrs; if (ref.subdir != "") extraAttrs["dir"] = ref.subdir; registry->add(ref.input, resolved, extraAttrs); -- cgit v1.2.3 From dc075dcdd0306adec911ec8d898b723f464f7c0a Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 12 Dec 2022 16:26:10 -0500 Subject: Apply suggestions from code review Co-authored-by: Eelco Dolstra --- src/nix/nix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 811936024..6ff27e479 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -187,7 +187,7 @@ operate are determined as follows: and likewise, again using a store path to a "drv" file to specify the derivation: ```console - # nix path-info -S --eval-store auto --store https://cache.nixos.org '/nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^*' + # nix path-info -S '/nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^*' … ``` -- cgit v1.2.3 From d8c1c24c78ebeb1f695e29a489be567118eb073e Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 12 Dec 2022 17:32:24 -0500 Subject: Adjust docs --- src/nix/nix.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 6ff27e479..529d5f796 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -190,11 +190,9 @@ operate are determined as follows: # nix path-info -S '/nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^*' … ``` - -* If you didn't specify the desired outputs, but the derivation comes - from an expression which has an attribute `meta.outputsToInstall`, Nix - will use those outputs. For example, since the package - `nixpkgs#libxml2` has this attribute: +* If you didn't specify the desired outputs, but the derivation hs an + attribute `meta.outputsToInstall`, Nix will use those outputs. For + example, since the package `nixpkgs#libxml2` has this attribute: ```console # nix eval 'nixpkgs#libxml2.meta.outputsToInstall' @@ -204,6 +202,9 @@ operate are determined as follows: a command like `nix shell nixpkgs#libxml2` will provide only those two outputs by default. + Note that a store derivation (given by `.drv` file store path) doesn't have + any attributes like `meta`, and thus this case doesn't apply to it. + * Otherwise, Nix will use all outputs of the derivation. # Nix stores -- cgit v1.2.3 From 32ae715db1771342fc356f1521cdda9ecd453358 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 12 Dec 2022 17:37:45 -0500 Subject: Fix typos in the docs Thanks! Co-authored-by: Valentin Gagarin --- src/nix/nix.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 529d5f796..723d3c87e 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -184,13 +184,13 @@ operate are determined as follows: /nix/store/q6580lr01jpcsqs4r5arlh4ki2c1m9rv-glibc-2.33-123-dev 44200560 ``` - and likewise, again using a store path to a "drv" file to specify the derivation: + and likewise, using a store path to a "drv" file to specify the derivation: ```console # nix path-info -S '/nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^*' … ``` -* If you didn't specify the desired outputs, but the derivation hs an +* If you didn't specify the desired outputs, but the derivation has an attribute `meta.outputsToInstall`, Nix will use those outputs. For example, since the package `nixpkgs#libxml2` has this attribute: -- cgit v1.2.3 From 09860c16ce526a079d3bd5e8d8bb6f26dc259b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sol=C3=A8ne=20Rapenne?= Date: Tue, 13 Dec 2022 11:46:33 +0100 Subject: documentation: use sections instead of list items --- src/nix/flake.md | 73 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 34 deletions(-) (limited to 'src/nix') diff --git a/src/nix/flake.md b/src/nix/flake.md index a1ab43281..810e9ebea 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -18,51 +18,56 @@ values such as packages or NixOS modules provided by the flake). Flake references (*flakerefs*) are a way to specify the location of a flake. These have two different forms: -* An attribute set representation, e.g. - ```nix - { - type = "github"; - owner = "NixOS"; - repo = "nixpkgs"; - } - ``` +## Attribute set representation - The only required attribute is `type`. The supported types are - listed below. +Example: -* A URL-like syntax, e.g. +```nix +{ + type = "github"; + owner = "NixOS"; + repo = "nixpkgs"; +} +``` - ``` - github:NixOS/nixpkgs - ``` +The only required attribute is `type`. The supported types are +listed below. - These are used on the command line as a more convenient alternative - to the attribute set representation. For instance, in the command +## URL-like syntax - ```console - # nix build github:NixOS/nixpkgs#hello - ``` +Example: - `github:NixOS/nixpkgs` is a flake reference (while `hello` is an - output attribute). They are also allowed in the `inputs` attribute - of a flake, e.g. +``` +github:NixOS/nixpkgs +``` - ```nix - inputs.nixpkgs.url = github:NixOS/nixpkgs; - ``` +These are used on the command line as a more convenient alternative +to the attribute set representation. For instance, in the command - is equivalent to +```console +# nix build github:NixOS/nixpkgs#hello +``` - ```nix - inputs.nixpkgs = { - type = "github"; - owner = "NixOS"; - repo = "nixpkgs"; - }; - ``` +`github:NixOS/nixpkgs` is a flake reference (while `hello` is an +output attribute). They are also allowed in the `inputs` attribute +of a flake, e.g. + +```nix +inputs.nixpkgs.url = github:NixOS/nixpkgs; +``` + +is equivalent to + +```nix +inputs.nixpkgs = { + type = "github"; + owner = "NixOS"; + repo = "nixpkgs"; +}; +``` -## Examples +### Examples Here are some examples of flake references in their URL-like representation: -- cgit v1.2.3 From 94cf0da7b2955d5b54a142b9e920332746a61033 Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Mon, 19 Dec 2022 13:16:06 -0700 Subject: fix(develop): make `nix develop` drv recreatable --- src/nix/develop.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nix') diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 4de109754..6c3a9c6c6 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -192,10 +192,12 @@ static StorePath getDerivationEnvironment(ref store, ref evalStore drv.env.erase("allowedRequisites"); drv.env.erase("disallowedReferences"); drv.env.erase("disallowedRequisites"); + drv.env.erase("name"); /* Rehash and write the derivation. FIXME: would be nice to use 'buildDerivation', but that's privileged. */ drv.name += "-env"; + drv.env.emplace("name", drv.name); drv.inputSrcs.insert(std::move(getEnvShPath)); if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) { for (auto & output : drv.outputs) { -- cgit v1.2.3 From 3a66d82e1da1302586055a70903de2f9a7425087 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Tue, 20 Dec 2022 15:26:05 +0100 Subject: update description of "store derivation" in installables section a store derivation is not a store path itself, it has a store path. --- src/nix/nix.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 723d3c87e..43de6869b 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -115,12 +115,12 @@ the Nix store. Here are the recognised types of installables: * **Store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv` - Store derivations are store paths with extension `.drv` and are a - low-level representation of a build-time dependency graph used - internally by Nix. By default, if you pass a store derivation to a - `nix` subcommand, it will operate on the *output paths* of the - derivation. For example, `nix path-info` prints information about - the output paths: + Store derivations are a low-level, internal representation of build tasks in Nix, and have store paths with extension `.drv`. + By default, if you pass the path to a store derivation to a `nix` subcommand, the command will operate on the [output path]s of the derivation. + + [output path]: ../../glossary.md#gloss-output-path + + For example, `nix path-info` prints information about the output paths: ```console # nix path-info --json /nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv -- cgit v1.2.3 From 7797661a70bcd6a7caf756964785ea7727ed1be0 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Tue, 20 Dec 2022 15:37:40 +0100 Subject: link "store derivation" to glossary definition --- src/nix/nix.md | 4 +++- src/nix/path-info.md | 4 +++- src/nix/show-derivation.md | 6 ++++-- src/nix/store-copy-log.md | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 43de6869b..9641cccb2 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -202,9 +202,11 @@ operate are determined as follows: a command like `nix shell nixpkgs#libxml2` will provide only those two outputs by default. - Note that a store derivation (given by `.drv` file store path) doesn't have + Note that a [store derivation] (given by its `.drv` file store path) doesn't have any attributes like `meta`, and thus this case doesn't apply to it. + [store derivation]: ../../glossary.md#gloss-store-derivation + * Otherwise, Nix will use all outputs of the derivation. # Nix stores diff --git a/src/nix/path-info.md b/src/nix/path-info.md index 7a1714ba4..b30898ac0 100644 --- a/src/nix/path-info.md +++ b/src/nix/path-info.md @@ -68,7 +68,9 @@ R""( ] ``` -* Print the path of the store derivation produced by `nixpkgs#hello`: +* Print the path of the [store derivation] produced by `nixpkgs#hello`: + + [store derivation]: ../../glossary.md#gloss-store-derivation ```console # nix path-info --derivation nixpkgs#hello diff --git a/src/nix/show-derivation.md b/src/nix/show-derivation.md index aa863899c..2cd93aa62 100644 --- a/src/nix/show-derivation.md +++ b/src/nix/show-derivation.md @@ -2,9 +2,11 @@ R""( # Examples -* Show the store derivation that results from evaluating the Hello +* Show the [store derivation] that results from evaluating the Hello package: + [store derivation]: ../../glossary.md#gloss-store-derivation + ```console # nix show-derivation nixpkgs#hello { @@ -37,7 +39,7 @@ R""( # Description This command prints on standard output a JSON representation of the -store derivations to which *installables* evaluate. Store derivations +[store derivation]s to which *installables* evaluate. Store derivations are used internally by Nix. They are store paths with extension `.drv` that represent the build-time dependency graph to which a Nix expression evaluates. diff --git a/src/nix/store-copy-log.md b/src/nix/store-copy-log.md index 19ae57079..0937250f2 100644 --- a/src/nix/store-copy-log.md +++ b/src/nix/store-copy-log.md @@ -18,7 +18,9 @@ R""( (The flag `--substituters ''` avoids querying `https://cache.nixos.org` for the log.) -* To copy the log for a specific store derivation via SSH: +* To copy the log for a specific [store derivation] via SSH: + + [store derivation]: ../../glossary.md#gloss-store-derivation ```console # nix store copy-log --to ssh-ng://machine /nix/store/ilgm50plpmcgjhcp33z6n4qbnpqfhxym-glibc-2.33-59.drv -- cgit v1.2.3 From c164d304f3cd6c5e536e33435084c030f018c2ab Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 23 Dec 2022 16:28:26 +0100 Subject: nix develop: Set personality This makes 'nix develop' set the Linux personality in the same way that the actual build does, allowing a command like 'nix develop nix#devShells.i686-linux.default' on x86_64-linux to work correctly. --- src/nix/develop.cc | 10 +++++++++- src/nix/run.cc | 13 +++++++++++-- src/nix/run.hh | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'src/nix') diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 6c3a9c6c6..1d90d1dac 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -164,6 +164,14 @@ struct BuildEnvironment { return vars == other.vars && bashFunctions == other.bashFunctions; } + + std::string getSystem() const + { + if (auto v = get(vars, "system")) + return getString(*v); + else + return settings.thisSystem; + } }; const static std::string getEnvSh = @@ -570,7 +578,7 @@ struct CmdDevelop : Common, MixEnvironment } } - runProgramInStore(store, shell, args); + runProgramInStore(store, shell, args, buildEnvironment.getSystem()); } }; diff --git a/src/nix/run.cc b/src/nix/run.cc index 45d2dfd0d..6fca68047 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -9,6 +9,7 @@ #include "fs-accessor.hh" #include "progress-bar.hh" #include "eval.hh" +#include "build/personality.hh" #if __linux__ #include @@ -24,7 +25,8 @@ namespace nix { void runProgramInStore(ref store, const std::string & program, - const Strings & args) + const Strings & args, + std::optional system) { stopProgressBar(); @@ -44,7 +46,7 @@ void runProgramInStore(ref store, throw Error("store '%s' is not a local store so it does not support command execution", store->getUri()); if (store->storeDir != store2->getRealStoreDir()) { - Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program }; + Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), std::string(system.value_or("")), program }; for (auto & arg : args) helperArgs.push_back(arg); execv(getSelfExe().value_or("nix").c_str(), stringsToCharPtrs(helperArgs).data()); @@ -52,6 +54,9 @@ void runProgramInStore(ref store, throw SysError("could not execute chroot helper"); } + if (system) + setPersonality(*system); + execvp(program.c_str(), stringsToCharPtrs(args).data()); throw SysError("unable to execute '%s'", program); @@ -199,6 +204,7 @@ void chrootHelper(int argc, char * * argv) int p = 1; std::string storeDir = argv[p++]; std::string realStoreDir = argv[p++]; + std::string system = argv[p++]; std::string cmd = argv[p++]; Strings args; while (p < argc) @@ -262,6 +268,9 @@ void chrootHelper(int argc, char * * argv) writeFile("/proc/self/uid_map", fmt("%d %d %d", uid, uid, 1)); writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1)); + if (system != "") + setPersonality(system); + execvp(cmd.c_str(), stringsToCharPtrs(args).data()); throw SysError("unable to exec '%s'", cmd); diff --git a/src/nix/run.hh b/src/nix/run.hh index 6180a87dd..fed360158 100644 --- a/src/nix/run.hh +++ b/src/nix/run.hh @@ -6,6 +6,7 @@ namespace nix { void runProgramInStore(ref store, const std::string & program, - const Strings & args); + const Strings & args, + std::optional system = std::nullopt); } -- cgit v1.2.3 From 9cdf8ededb2049833213bf498b27ed9537358707 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Mon, 2 Jan 2023 13:37:59 +0100 Subject: remove redundant re-definition of store derivations --- src/nix/nix.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nix') diff --git a/src/nix/nix.md b/src/nix/nix.md index 9641cccb2..db60c59ff 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -115,8 +115,7 @@ the Nix store. Here are the recognised types of installables: * **Store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv` - Store derivations are a low-level, internal representation of build tasks in Nix, and have store paths with extension `.drv`. - By default, if you pass the path to a store derivation to a `nix` subcommand, the command will operate on the [output path]s of the derivation. + By default, if you pass a [store derivation] path to a `nix` subcommand, the command will operate on the [output path]s of the derivation. [output path]: ../../glossary.md#gloss-output-path -- cgit v1.2.3 From 105d74eb8177016a1056b6642875c318a148a776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophane=20Hufschmitt?= Date: Mon, 2 Jan 2023 15:44:04 +0100 Subject: Revert "Fix why-depends for CA derivations" This reverts commit b13fd4c58e81b2b2b0d72caa5ce80de861622610. --- src/nix/why-depends.cc | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) (limited to 'src/nix') diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc index 723017497..6512aee03 100644 --- a/src/nix/why-depends.cc +++ b/src/nix/why-depends.cc @@ -95,35 +95,19 @@ struct CmdWhyDepends : SourceExprCommand * to build. */ auto dependency = parseInstallable(store, _dependency); - auto derivedDependency = dependency->toDerivedPath(); - auto optDependencyPath = std::visit(overloaded { - [](const DerivedPath::Opaque & nodrv) -> std::optional { - return { nodrv.path }; - }, - [&](const DerivedPath::Built & hasdrv) -> std::optional { - if (hasdrv.outputs.size() != 1) { - throw Error("argument '%s' should evaluate to one store path", dependency->what()); - } - auto outputMap = store->queryPartialDerivationOutputMap(hasdrv.drvPath); - auto maybePath = outputMap.find(*hasdrv.outputs.begin()); - if (maybePath == outputMap.end()) { - throw Error("unexpected end of iterator"); - } - return maybePath->second; - }, - }, derivedDependency.raw()); + auto dependencyPath = Installable::toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency); + auto dependencyPathHash = dependencyPath.hashPart(); StorePathSet closure; store->computeFSClosure({packagePath}, closure, false, false); - if (!optDependencyPath.has_value() || !closure.count(*optDependencyPath)) { - printError("'%s' does not depend on '%s'", package->what(), dependency->what()); + if (!closure.count(dependencyPath)) { + printError("'%s' does not depend on '%s'", + store->printStorePath(packagePath), + store->printStorePath(dependencyPath)); return; } - auto dependencyPath = *optDependencyPath; - auto dependencyPathHash = dependencyPath.hashPart(); - stopProgressBar(); // FIXME auto accessor = store->getFSAccessor(); -- cgit v1.2.3 From 8cac451fce990151046996a13130bb1b91c6ba19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophane=20Hufschmitt?= Date: Mon, 2 Jan 2023 17:35:48 +0100 Subject: Fix why-depends for CA derivations (again) This has the same goal as b13fd4c58e81b2b2b0d72caa5ce80de861622610,but achieves it in a different way in order to not break `nix why-depends --derivation`. --- src/nix/why-depends.cc | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/nix') diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc index 6512aee03..76125e5e4 100644 --- a/src/nix/why-depends.cc +++ b/src/nix/why-depends.cc @@ -95,19 +95,25 @@ struct CmdWhyDepends : SourceExprCommand * to build. */ auto dependency = parseInstallable(store, _dependency); - auto dependencyPath = Installable::toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency); - auto dependencyPathHash = dependencyPath.hashPart(); + auto optDependencyPath = [&]() -> std::optional { + try { + return {Installable::toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency)}; + } catch (MissingRealisation &) { + return std::nullopt; + } + }(); StorePathSet closure; store->computeFSClosure({packagePath}, closure, false, false); - if (!closure.count(dependencyPath)) { - printError("'%s' does not depend on '%s'", - store->printStorePath(packagePath), - store->printStorePath(dependencyPath)); + if (!optDependencyPath.has_value() || !closure.count(*optDependencyPath)) { + printError("'%s' does not depend on '%s'", package->what(), dependency->what()); return; } + auto dependencyPath = *optDependencyPath; + auto dependencyPathHash = dependencyPath.hashPart(); + stopProgressBar(); // FIXME auto accessor = store->getFSAccessor(); -- cgit v1.2.3 From f1ee4ece806d109df8f6994d9e70eb7f05505709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Thu, 5 Jan 2023 18:23:30 +0100 Subject: Don't check NixOS modules NixOS modules can be paths. Rather than dig further down into the layer violation, don't check anything specific to NixOS modules. --- src/nix/flake.cc | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'src/nix') diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 06fd87ef2..9b4cdf35a 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -381,23 +381,6 @@ struct CmdFlakeCheck : FlakeCommand auto checkModule = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { state->forceValue(v, pos); - if (v.isLambda()) { - if (!v.lambda.fun->hasFormals() || !v.lambda.fun->formals->ellipsis) - throw Error("module must match an open attribute set ('{ config, ... }')"); - } else if (v.type() == nAttrs) { - for (auto & attr : *v.attrs) - try { - state->forceValue(*attr.value, attr.pos); - } catch (Error & e) { - e.addTrace( - state->positions[attr.pos], - hintfmt("while evaluating the option '%s'", state->symbols[attr.name])); - throw; - } - } else - throw Error("module must be a function or an attribute set"); - // FIXME: if we have a 'nixpkgs' input, use it to - // check the module. } catch (Error & e) { e.addTrace(resolve(pos), hintfmt("while checking the NixOS module '%s'", attrPath)); reportError(e); -- cgit v1.2.3