From 06d57ce7597fc1b49ce1cdc721edc64eaafe38fb Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Wed, 22 Dec 2021 15:36:08 -0700 Subject: [PATCH 01/18] 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(-) 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); } } From 81567a096258026148b42f3048be9b2ba295b41a Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 18 Feb 2022 18:33:03 -0500 Subject: [PATCH 02/18] repl: allow loading installables from CLI repl: search installable with findAlongAttrPath repl: refactor handling of args repl: temp --- src/libcmd/command.hh | 1 + src/libcmd/installables.cc | 5 ++- src/nix/repl.cc | 87 ++++++++++++++++++++++---------------- 3 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 078e2a2ce..65626e33f 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -132,6 +132,7 @@ struct InstallableCommand : virtual Args, SourceExprCommand InstallableCommand(bool supportReadOnlyMode = false); void prepare() override; + std::shared_ptr load(); std::optional getFlakeRefForCompletion() override { diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 635ce19b6..7d2ff0f68 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -1054,10 +1054,13 @@ InstallableCommand::InstallableCommand(bool supportReadOnlyMode) }} }); } +std::shared_ptr InstallableCommand::load() { + return parseInstallable(getStore(), _installable); +} void InstallableCommand::prepare() { - installable = parseInstallable(getStore(), _installable); + installable = load(); } } 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(); } }; From 5640b528349c43717aa501797a4f337373ebf3e4 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 11 Mar 2022 13:26:08 -0500 Subject: [PATCH 03/18] repl: use installables --- src/libcmd/command.hh | 2 +- src/libcmd/installables.cc | 12 +++++++----- src/libcmd/installables.hh | 1 + src/nix/repl.cc | 23 ++++++++++++----------- src/nix/repl.md | 30 +++++++++++++++++++++++++++--- 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 65626e33f..65eb0c4a0 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -114,6 +114,7 @@ struct InstallablesCommand : virtual Args, SourceExprCommand InstallablesCommand(); void prepare() override; + Installables load(); virtual bool useDefaultInstallables() { return true; } @@ -132,7 +133,6 @@ struct InstallableCommand : virtual Args, SourceExprCommand InstallableCommand(bool supportReadOnlyMode = false); void prepare() override; - std::shared_ptr load(); std::optional getFlakeRefForCompletion() override { diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 7d2ff0f68..c29fbeec9 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -1025,11 +1025,16 @@ InstallablesCommand::InstallablesCommand() void InstallablesCommand::prepare() { + installables = load(); +} + +Installables InstallablesCommand::load() { + Installables installables; if (_installables.empty() && useDefaultInstallables()) // FIXME: commands like "nix profile install" should not have a // default, probably. _installables.push_back("."); - installables = parseInstallables(getStore(), _installables); + return parseInstallables(getStore(), _installables); } std::optional InstallablesCommand::getFlakeRefForCompletion() @@ -1054,13 +1059,10 @@ InstallableCommand::InstallableCommand(bool supportReadOnlyMode) }} }); } -std::shared_ptr InstallableCommand::load() { - return parseInstallable(getStore(), _installable); -} void InstallableCommand::prepare() { - installable = load(); + installable = parseInstallable(getStore(), _installable); } } diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index 5d715210e..b97888db6 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -131,6 +131,7 @@ struct Installable OperateOn operateOn, const std::vector> & installables); }; +typedef std::vector> Installables; struct InstallableValue : Installable { 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" From 1ca3f6035da4e82647382405c774e43e02de3fa1 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 11 Mar 2022 13:52:08 -0500 Subject: [PATCH 04/18] repl: update docs with installables --- doc/manual/src/release-notes/rl-next.md | 5 +++++ src/nix/repl.cc | 16 +++------------- src/nix/repl.md | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index efd893662..096499bc3 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -24,3 +24,8 @@ Selecting derivation outputs using the attribute selection syntax (e.g. `nixpkgs#glibc.dev`) no longer works. + +* `nix repl` now takes installables on the command line, unifying the usage + with other commands that use `--file` and `--expr`. Primary breaking change + is for the common usage of `nix repl ''` which can be recovered with + `nix repl nixpkgs` or `nix repl --expr 'import {}'` 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. From 9f8c1183fa10aa9d95bce0ca2f3337532ad7981b Mon Sep 17 00:00:00 2001 From: tomberek Date: Wed, 18 May 2022 21:18:07 -0400 Subject: [PATCH 05/18] 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(-) 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(); } From 7534798eedb696226101f2c8793ba9ace049f5e4 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Wed, 18 May 2022 21:33:41 -0400 Subject: [PATCH 06/18] refactor: factor out getValue --- src/nix/repl.cc | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) 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(); } From e1f308a1ec3c395cd4978b45400f7a45adcea0dc Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Wed, 18 May 2022 22:28:15 -0400 Subject: [PATCH 07/18] repl: provide backward compat with legacy usage --- src/libcmd/command.hh | 2 +- src/nix/repl.cc | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 65eb0c4a0..2c88e1526 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -120,7 +120,7 @@ struct InstallablesCommand : virtual Args, SourceExprCommand std::optional getFlakeRefForCompletion() override; -private: +protected: std::vector _installables; }; 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 { From f21dec5befc9ee273a5210dec322d30c3c3be595 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Thu, 19 May 2022 01:01:45 -0400 Subject: [PATCH 08/18] repl: hide flake behavior behind flag and provide warning --- src/nix/repl.cc | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) 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; }; From 7d7e00272a2f47f68b3809296992db84ae871e09 Mon Sep 17 00:00:00 2001 From: tomberek Date: Fri, 20 May 2022 01:28:20 -0400 Subject: [PATCH 09/18] 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(-) 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; From db613a85fb7fb8c8a0f476f83db92523cce327f7 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 20 May 2022 01:35:06 -0400 Subject: [PATCH 10/18] repl: allow --file to always utilize autoargs --- src/nix/repl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); From 542e36c6e7ed5efa3d60e5adfc37ff7bb7e90a41 Mon Sep 17 00:00:00 2001 From: tomberek Date: Fri, 20 May 2022 01:48:24 -0400 Subject: [PATCH 11/18] Apply suggestions from code review Co-authored-by: Eelco Dolstra --- src/libcmd/installables.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index b97888db6..948f78919 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -131,6 +131,7 @@ struct Installable OperateOn operateOn, const std::vector> & installables); }; + typedef std::vector> Installables; struct InstallableValue : Installable From 82c4af41e3348a87ebc9fb583df09070beadc019 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 20 May 2022 01:49:49 -0400 Subject: [PATCH 12/18] repl: clarify change and usage of --- doc/manual/src/release-notes/rl-next.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index 096499bc3..6dbf6adae 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -28,4 +28,4 @@ * `nix repl` now takes installables on the command line, unifying the usage with other commands that use `--file` and `--expr`. Primary breaking change is for the common usage of `nix repl ''` which can be recovered with - `nix repl nixpkgs` or `nix repl --expr 'import {}'` + `nix repl --file ''` or `nix repl --expr 'import {}'` From 938150472d8373395f6f09cd76d4b0bde271ffda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophane=20Hufschmitt?= Date: Fri, 20 May 2022 08:12:02 +0200 Subject: [PATCH 13/18] Add some tests for the new REPL cli - Test that without the XP feature things work as before - Test that with or without the XP feature `--file file` works - Test that with XP feature passing a flakeref works - Test `:reload` with a flake --- tests/repl.sh | 55 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/tests/repl.sh b/tests/repl.sh index b6937b9e9..e879319fa 100644 --- a/tests/repl.sh +++ b/tests/repl.sh @@ -50,15 +50,17 @@ testRepl testRepl --store "$TEST_ROOT/store?real=$NIX_STORE_DIR" testReplResponse () { - local response="$(nix repl <<< "$1")" - echo "$response" | grep -qs "$2" \ + local commands="$1"; shift + local expectedResponse="$1"; shift + local response="$(nix repl "$@" <<< "$commands")" + echo "$response" | grep -qs "$expectedResponse" \ || fail "repl command set: -$1 +$commands does not respond with: -$2 +$expectedResponse but with: @@ -71,3 +73,48 @@ testReplResponse ' :a { a = "2"; } "result: ${a}" ' "result: 2" + +testReplResponse ' +drvPath +' '"/tmp/nix-test/default/store/qlksh7k4a72107vc054ilywq4rcmy9if-simple.drv"' \ +$testDir/simple.nix --experimental-features '' + +testReplResponse ' +drvPath +' '"/tmp/nix-test/default/store/qlksh7k4a72107vc054ilywq4rcmy9if-simple.drv"' \ +--file $testDir/simple.nix --experimental-features '' + +testReplResponse ' +drvPath +' '"/tmp/nix-test/default/store/qlksh7k4a72107vc054ilywq4rcmy9if-simple.drv"' \ +--file $testDir/simple.nix --experimental-features 'flakes' + +mkdir -p flake && cat < flake/flake.nix +{ + outputs = { self }: { + foo = 1; + bar.baz = 2; + + changingThing = "beforeChange"; + }; +} +EOF +testReplResponse ' +foo + baz +' "3" \ + ./flake ./flake\#bar + +# Test the `:reload` mechansim with flakes: +# - Eval `./flake#changingThing` +# - Modify the flake +# - Re-eval it +# - Check that the result has changed +replResult=$( ( +echo "changingThing" +sleep 1 # Leave the repl the time to eval 'foo' +sed -i 's/beforeChange/afterChange/' flake/flake.nix +echo ":reload" +echo "changingThing" +) | nix repl ./flake) +echo "$replResult" | grep -qs beforeChange +echo "$replResult" | grep -qs afterChange From 0053dab43f9ca350c27235f8a58b5d550bfffd38 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 20 May 2022 08:03:41 -0400 Subject: [PATCH 14/18] repl: fix tests to run on any testing store --- tests/repl.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/repl.sh b/tests/repl.sh index e879319fa..07f647585 100644 --- a/tests/repl.sh +++ b/tests/repl.sh @@ -76,17 +76,17 @@ testReplResponse ' testReplResponse ' drvPath -' '"/tmp/nix-test/default/store/qlksh7k4a72107vc054ilywq4rcmy9if-simple.drv"' \ +' '".*-simple.drv"' \ $testDir/simple.nix --experimental-features '' testReplResponse ' drvPath -' '"/tmp/nix-test/default/store/qlksh7k4a72107vc054ilywq4rcmy9if-simple.drv"' \ +' '".*-simple.drv"' \ --file $testDir/simple.nix --experimental-features '' testReplResponse ' drvPath -' '"/tmp/nix-test/default/store/qlksh7k4a72107vc054ilywq4rcmy9if-simple.drv"' \ +' '".*-simple.drv"' \ --file $testDir/simple.nix --experimental-features 'flakes' mkdir -p flake && cat < flake/flake.nix From 7a04fb1c56ca60652c2a44019b31fe8cf2e2bc46 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 20 May 2022 08:20:00 -0400 Subject: [PATCH 15/18] repl: add repl-flake experimental feature for gating --- src/libutil/experimental-features.cc | 1 + src/libutil/experimental-features.hh | 1 + src/nix/repl.cc | 2 +- tests/repl.sh | 6 +++--- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc index 315de64a4..fa79cca6b 100644 --- a/src/libutil/experimental-features.cc +++ b/src/libutil/experimental-features.cc @@ -13,6 +13,7 @@ std::map stringifiedXpFeatures = { { Xp::RecursiveNix, "recursive-nix" }, { Xp::NoUrlLiterals, "no-url-literals" }, { Xp::FetchClosure, "fetch-closure" }, + { Xp::ReplFlake, "repl-flake" }, }; const std::optional parseExperimentalFeature(const std::string_view & name) diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh index 57512830c..d09ab025c 100644 --- a/src/libutil/experimental-features.hh +++ b/src/libutil/experimental-features.hh @@ -22,6 +22,7 @@ enum struct ExperimentalFeature RecursiveNix, NoUrlLiterals, FetchClosure, + ReplFlake, }; /** 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"); diff --git a/tests/repl.sh b/tests/repl.sh index 07f647585..5caf0a58a 100644 --- a/tests/repl.sh +++ b/tests/repl.sh @@ -87,7 +87,7 @@ drvPath testReplResponse ' drvPath ' '".*-simple.drv"' \ ---file $testDir/simple.nix --experimental-features 'flakes' +--file $testDir/simple.nix --experimental-features 'repl-flake' mkdir -p flake && cat < flake/flake.nix { @@ -102,7 +102,7 @@ EOF testReplResponse ' foo + baz ' "3" \ - ./flake ./flake\#bar + ./flake ./flake\#bar --experimental-features 'flakes repl-flake' # Test the `:reload` mechansim with flakes: # - Eval `./flake#changingThing` @@ -115,6 +115,6 @@ sleep 1 # Leave the repl the time to eval 'foo' sed -i 's/beforeChange/afterChange/' flake/flake.nix echo ":reload" echo "changingThing" -) | nix repl ./flake) +) | nix repl ./flake --experimental-features 'flakes repl-flake') echo "$replResult" | grep -qs beforeChange echo "$replResult" | grep -qs afterChange From 8c3939af14106c753bbb963663ad1cfb4fa6de80 Mon Sep 17 00:00:00 2001 From: tomberek Date: Fri, 20 May 2022 12:09:41 -0400 Subject: [PATCH 16/18] 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> --- tests/repl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/repl.sh b/tests/repl.sh index 5caf0a58a..e9e41558a 100644 --- a/tests/repl.sh +++ b/tests/repl.sh @@ -77,7 +77,7 @@ testReplResponse ' testReplResponse ' drvPath ' '".*-simple.drv"' \ -$testDir/simple.nix --experimental-features '' +$testDir/simple.nix testReplResponse ' drvPath @@ -87,7 +87,7 @@ drvPath testReplResponse ' drvPath ' '".*-simple.drv"' \ ---file $testDir/simple.nix --experimental-features 'repl-flake' +--file $testDir/simple.nix --extra-experimental-features 'repl-flake' mkdir -p flake && cat < flake/flake.nix { From dae4a8a6c8d8dfde3292d3e9e05977bc13648bda Mon Sep 17 00:00:00 2001 From: tomberek Date: Wed, 15 Jun 2022 09:02:36 -0400 Subject: [PATCH 17/18] 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> --- doc/manual/src/release-notes/rl-next.md | 2 ++ src/nix/repl.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index 5749f3924..9684a70d4 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -7,3 +7,5 @@ with other commands that use `--file` and `--expr`. Primary breaking change is for the common usage of `nix repl ''` which can be recovered with `nix repl --file ''` or `nix repl --expr 'import {}'` + + This is currently guarded by the 'repl-flake' experimental feature 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. From f801d70ba70c130a26747aa5b60d233f37d34bfa Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 24 Jun 2022 11:17:29 -0400 Subject: [PATCH 18/18] tests: enable ca-derivations for simple.nix in repl tests --- tests/repl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/repl.sh b/tests/repl.sh index 30921af04..c555560cc 100644 --- a/tests/repl.sh +++ b/tests/repl.sh @@ -87,12 +87,12 @@ $testDir/simple.nix testReplResponse ' drvPath ' '".*-simple.drv"' \ ---file $testDir/simple.nix --experimental-features '' +--file $testDir/simple.nix --experimental-features 'ca-derivations' testReplResponse ' drvPath ' '".*-simple.drv"' \ ---file $testDir/simple.nix --extra-experimental-features 'repl-flake' +--file $testDir/simple.nix --extra-experimental-features 'repl-flake ca-derivations' mkdir -p flake && cat < flake/flake.nix {