2016-02-09 22:28:29 +02:00
|
|
|
#pragma once
|
2023-04-01 06:18:41 +03:00
|
|
|
///@file
|
2016-02-09 22:28:29 +02:00
|
|
|
|
2023-02-06 06:28:18 +02:00
|
|
|
#include "installable-value.hh"
|
2016-02-09 22:28:29 +02:00
|
|
|
#include "args.hh"
|
2017-10-24 13:45:11 +03:00
|
|
|
#include "common-eval-args.hh"
|
2019-12-05 20:11:09 +02:00
|
|
|
#include "path.hh"
|
2020-01-29 15:57:57 +02:00
|
|
|
#include "flake/lockfile.hh"
|
2019-10-14 15:40:16 +03:00
|
|
|
|
2019-03-21 10:30:16 +02:00
|
|
|
#include <optional>
|
2016-02-09 22:28:29 +02:00
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2018-01-31 17:14:47 +02:00
|
|
|
extern std::string programPath;
|
|
|
|
|
2021-01-14 01:05:04 +02:00
|
|
|
extern char * * savedArgv;
|
|
|
|
|
2017-04-25 13:06:32 +03:00
|
|
|
class EvalState;
|
2019-11-08 16:13:32 +02:00
|
|
|
struct Pos;
|
2016-02-09 22:28:29 +02:00
|
|
|
class Store;
|
2019-05-29 16:31:07 +03:00
|
|
|
|
2023-03-21 15:43:58 +02:00
|
|
|
static constexpr Command::Category catHelp = -1;
|
2020-05-05 16:18:23 +03:00
|
|
|
static constexpr Command::Category catSecondary = 100;
|
|
|
|
static constexpr Command::Category catUtility = 101;
|
|
|
|
static constexpr Command::Category catNixInstallation = 102;
|
|
|
|
|
2022-12-01 02:57:02 +02:00
|
|
|
static constexpr auto installablesCategory = "Options that change the interpretation of [installables](@docroot@/command-ref/new-cli/nix.md#installables)";
|
2021-01-25 20:03:13 +02:00
|
|
|
|
2020-08-17 18:44:52 +03:00
|
|
|
struct NixMultiCommand : virtual MultiCommand, virtual Command
|
|
|
|
{
|
|
|
|
nlohmann::json toJSON() override;
|
|
|
|
};
|
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
// For the overloaded run methods
|
|
|
|
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* A command that requires a \ref Store "Nix store".
|
|
|
|
*/
|
2016-02-09 22:28:29 +02:00
|
|
|
struct StoreCommand : virtual Command
|
|
|
|
{
|
2016-03-21 19:03:36 +02:00
|
|
|
StoreCommand();
|
2016-02-09 22:28:29 +02:00
|
|
|
void run() override;
|
2017-04-25 12:20:37 +03:00
|
|
|
ref<Store> getStore();
|
2017-03-16 15:25:54 +02:00
|
|
|
virtual ref<Store> createStore();
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* Main entry point, with a `Store` provided
|
|
|
|
*/
|
2016-02-09 22:28:29 +02:00
|
|
|
virtual void run(ref<Store>) = 0;
|
2017-04-25 12:20:37 +03:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::shared_ptr<Store> _store;
|
2016-02-09 22:28:29 +02:00
|
|
|
};
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* A command that copies something between `--from` and `--to` \ref
|
|
|
|
* Store stores.
|
|
|
|
*/
|
2022-01-17 20:45:21 +02:00
|
|
|
struct CopyCommand : virtual StoreCommand
|
|
|
|
{
|
|
|
|
std::string srcUri, dstUri;
|
|
|
|
|
|
|
|
CopyCommand();
|
|
|
|
|
|
|
|
ref<Store> createStore() override;
|
|
|
|
|
|
|
|
ref<Store> getDstStore();
|
|
|
|
};
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* A command that needs to evaluate Nix language expressions.
|
|
|
|
*/
|
2019-05-16 23:48:16 +03:00
|
|
|
struct EvalCommand : virtual StoreCommand, MixEvalArgs
|
|
|
|
{
|
2020-08-05 22:26:17 +03:00
|
|
|
bool startReplOnEvalErrors = false;
|
2022-06-02 19:26:46 +03:00
|
|
|
bool ignoreExceptionsDuringTry = false;
|
2020-08-05 22:26:17 +03:00
|
|
|
|
2021-06-29 22:09:48 +03:00
|
|
|
EvalCommand();
|
|
|
|
|
|
|
|
~EvalCommand();
|
|
|
|
|
|
|
|
ref<Store> getEvalStore();
|
|
|
|
|
2019-05-16 23:48:16 +03:00
|
|
|
ref<EvalState> getEvalState();
|
|
|
|
|
2021-06-29 22:09:48 +03:00
|
|
|
private:
|
|
|
|
std::shared_ptr<Store> evalStore;
|
2020-08-05 22:26:17 +03:00
|
|
|
|
2019-05-16 23:48:16 +03:00
|
|
|
std::shared_ptr<EvalState> evalState;
|
|
|
|
};
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* A mixin class for commands that process flakes, adding a few standard
|
|
|
|
* flake-related options/flags.
|
|
|
|
*/
|
2020-06-08 17:20:00 +03:00
|
|
|
struct MixFlakeOptions : virtual Args, EvalCommand
|
2017-04-25 13:06:32 +03:00
|
|
|
{
|
2020-01-29 15:57:57 +02:00
|
|
|
flake::LockFlags lockFlags;
|
|
|
|
|
2019-05-22 14:46:07 +03:00
|
|
|
MixFlakeOptions();
|
2020-06-08 17:20:00 +03:00
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* The completion for some of these flags depends on the flake(s) in
|
|
|
|
* question.
|
|
|
|
*
|
|
|
|
* This method should be implemented to gather all flakerefs the
|
|
|
|
* command is operating with (presumably specified via some other
|
|
|
|
* arguments) so that the completions for these flags can use them.
|
|
|
|
*/
|
Overhaul completions, redo #6693 (#8131)
As I complained in
https://github.com/NixOS/nix/pull/6784#issuecomment-1421777030 (a
comment on the wrong PR, sorry again!), #6693 introduced a second
completions mechanism to fix a bug. Having two completion mechanisms
isn't so nice.
As @thufschmitt also pointed out, it was a bummer to go from `FlakeRef`
to `std::string` when collecting flake refs. Now it is `FlakeRefs`
again.
The underlying issue that sought to work around was that completion of
arguments not at the end can still benefit from the information from
latter arguments.
To fix this better, we rip out that change and simply defer all
completion processing until after all the (regular, already-complete)
arguments have been passed.
In addition, I noticed the original completion logic used some global
variables. I do not like global variables, because even if they save
lines of code, they also obfuscate the architecture of the code.
I got rid of them moved them to a new `RootArgs` class, which now has
`parseCmdline` instead of `Args`. The idea is that we have many argument
parsers from subcommands and what-not, but only one root args that owns
the other per actual parsing invocation. The state that was global is
now part of the root args instead.
This did, admittedly, add a bunch of new code. And I do feel bad about
that. So I went and added a lot of API docs to try to at least make the
current state of things clear to the next person.
--
This is needed for RFC 134 (tracking issue #7868). It was very hard to
modularize `Installable` parsing when there were two completion
arguments. I wouldn't go as far as to say it is *easy* now, but at least
it is less hard (and the completions test finally passed).
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
2023-10-23 16:03:11 +03:00
|
|
|
virtual std::vector<FlakeRef> getFlakeRefsForCompletion()
|
2020-06-08 17:20:00 +03:00
|
|
|
{ return {}; }
|
2019-05-22 14:46:07 +03:00
|
|
|
};
|
|
|
|
|
2020-06-08 17:20:00 +03:00
|
|
|
struct SourceExprCommand : virtual Args, MixFlakeOptions
|
2019-05-22 14:46:07 +03:00
|
|
|
{
|
|
|
|
std::optional<Path> file;
|
2019-11-27 01:05:30 +02:00
|
|
|
std::optional<std::string> expr;
|
2019-05-22 14:46:07 +03:00
|
|
|
|
2023-02-05 03:45:40 +02:00
|
|
|
SourceExprCommand();
|
2019-05-14 12:34:45 +03:00
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
Installables parseInstallables(
|
2019-04-08 17:11:17 +03:00
|
|
|
ref<Store> store, std::vector<std::string> ss);
|
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
ref<Installable> parseInstallable(
|
2019-04-08 17:11:17 +03:00
|
|
|
ref<Store> store, const std::string & installable);
|
|
|
|
|
Support non-x86_64-linux system types in flakes
A command like
$ nix run nixpkgs#hello
will now build the attribute 'packages.${system}.hello' rather than
'packages.hello'. Note that this does mean that the flake needs to
export an attribute for every system type it supports, and you can't
build on unsupported systems. So 'packages' typically looks like this:
packages = nixpkgs.lib.genAttrs ["x86_64-linux" "i686-linux"] (system: {
hello = ...;
});
The 'checks', 'defaultPackage', 'devShell', 'apps' and 'defaultApp'
outputs similarly are now attrsets that map system types to
derivations/apps. 'nix flake check' checks that the derivations for
all platforms evaluate correctly, but only builds the derivations in
'checks.${system}'.
Fixes #2861. (That issue also talks about access to ~/.config/nixpkgs
and --arg, but I think it's reasonable to say that flakes shouldn't
support those.)
The alternative to attribute selection is to pass the system type as
an argument to the flake's 'outputs' function, e.g. 'outputs = { self,
nixpkgs, system }: ...'. However, that approach would be at odds with
hermetic evaluation and make it impossible to enumerate the packages
provided by a flake.
2019-10-15 18:52:10 +03:00
|
|
|
virtual Strings getDefaultFlakeAttrPaths();
|
2019-06-17 17:58:59 +03:00
|
|
|
|
Support non-x86_64-linux system types in flakes
A command like
$ nix run nixpkgs#hello
will now build the attribute 'packages.${system}.hello' rather than
'packages.hello'. Note that this does mean that the flake needs to
export an attribute for every system type it supports, and you can't
build on unsupported systems. So 'packages' typically looks like this:
packages = nixpkgs.lib.genAttrs ["x86_64-linux" "i686-linux"] (system: {
hello = ...;
});
The 'checks', 'defaultPackage', 'devShell', 'apps' and 'defaultApp'
outputs similarly are now attrsets that map system types to
derivations/apps. 'nix flake check' checks that the derivations for
all platforms evaluate correctly, but only builds the derivations in
'checks.${system}'.
Fixes #2861. (That issue also talks about access to ~/.config/nixpkgs
and --arg, but I think it's reasonable to say that flakes shouldn't
support those.)
The alternative to attribute selection is to pass the system type as
an argument to the flake's 'outputs' function, e.g. 'outputs = { self,
nixpkgs, system }: ...'. However, that approach would be at odds with
hermetic evaluation and make it impossible to enumerate the packages
provided by a flake.
2019-10-15 18:52:10 +03:00
|
|
|
virtual Strings getDefaultFlakeAttrPathPrefixes();
|
2020-05-11 22:49:02 +03:00
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* Complete an installable from the given prefix.
|
|
|
|
*/
|
Overhaul completions, redo #6693 (#8131)
As I complained in
https://github.com/NixOS/nix/pull/6784#issuecomment-1421777030 (a
comment on the wrong PR, sorry again!), #6693 introduced a second
completions mechanism to fix a bug. Having two completion mechanisms
isn't so nice.
As @thufschmitt also pointed out, it was a bummer to go from `FlakeRef`
to `std::string` when collecting flake refs. Now it is `FlakeRefs`
again.
The underlying issue that sought to work around was that completion of
arguments not at the end can still benefit from the information from
latter arguments.
To fix this better, we rip out that change and simply defer all
completion processing until after all the (regular, already-complete)
arguments have been passed.
In addition, I noticed the original completion logic used some global
variables. I do not like global variables, because even if they save
lines of code, they also obfuscate the architecture of the code.
I got rid of them moved them to a new `RootArgs` class, which now has
`parseCmdline` instead of `Args`. The idea is that we have many argument
parsers from subcommands and what-not, but only one root args that owns
the other per actual parsing invocation. The state that was global is
now part of the root args instead.
This did, admittedly, add a bunch of new code. And I do feel bad about
that. So I went and added a lot of API docs to try to at least make the
current state of things clear to the next person.
--
This is needed for RFC 134 (tracking issue #7868). It was very hard to
modularize `Installable` parsing when there were two completion
arguments. I wouldn't go as far as to say it is *easy* now, but at least
it is less hard (and the completions test finally passed).
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
2023-10-23 16:03:11 +03:00
|
|
|
void completeInstallable(AddCompletions & completions, std::string_view prefix);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience wrapper around the underlying function to make setting the
|
|
|
|
* callback easier.
|
|
|
|
*/
|
|
|
|
CompleterClosure getCompleteInstallable();
|
2017-07-17 20:02:56 +03:00
|
|
|
};
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* A mixin class for commands that need a read-only flag.
|
|
|
|
*
|
|
|
|
* What exactly is "read-only" is unspecified, but it will usually be
|
|
|
|
* the \ref Store "Nix store".
|
|
|
|
*/
|
2023-02-05 03:45:40 +02:00
|
|
|
struct MixReadOnlyOption : virtual Args
|
|
|
|
{
|
|
|
|
MixReadOnlyOption();
|
|
|
|
};
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* Like InstallablesCommand but the installables are not loaded.
|
|
|
|
*
|
|
|
|
* This is needed by `CmdRepl` which wants to load (and reload) the
|
|
|
|
* installables itself.
|
|
|
|
*/
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
struct RawInstallablesCommand : virtual Args, SourceExprCommand
|
2017-07-17 20:02:56 +03:00
|
|
|
{
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
RawInstallablesCommand();
|
2017-07-17 20:02:56 +03:00
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
virtual void run(ref<Store> store, std::vector<std::string> && rawInstallables) = 0;
|
2017-07-17 20:02:56 +03:00
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
void run(ref<Store> store) override;
|
2017-04-25 13:06:32 +03:00
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
// FIXME make const after `CmdRepl`'s override is fixed up
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
virtual void applyDefaultInstallables(std::vector<std::string> & rawInstallables);
|
2019-04-19 17:07:37 +03:00
|
|
|
|
2023-03-08 14:53:20 +02:00
|
|
|
bool readFromStdIn = false;
|
2023-01-12 21:35:22 +02:00
|
|
|
|
Overhaul completions, redo #6693 (#8131)
As I complained in
https://github.com/NixOS/nix/pull/6784#issuecomment-1421777030 (a
comment on the wrong PR, sorry again!), #6693 introduced a second
completions mechanism to fix a bug. Having two completion mechanisms
isn't so nice.
As @thufschmitt also pointed out, it was a bummer to go from `FlakeRef`
to `std::string` when collecting flake refs. Now it is `FlakeRefs`
again.
The underlying issue that sought to work around was that completion of
arguments not at the end can still benefit from the information from
latter arguments.
To fix this better, we rip out that change and simply defer all
completion processing until after all the (regular, already-complete)
arguments have been passed.
In addition, I noticed the original completion logic used some global
variables. I do not like global variables, because even if they save
lines of code, they also obfuscate the architecture of the code.
I got rid of them moved them to a new `RootArgs` class, which now has
`parseCmdline` instead of `Args`. The idea is that we have many argument
parsers from subcommands and what-not, but only one root args that owns
the other per actual parsing invocation. The state that was global is
now part of the root args instead.
This did, admittedly, add a bunch of new code. And I do feel bad about
that. So I went and added a lot of API docs to try to at least make the
current state of things clear to the next person.
--
This is needed for RFC 134 (tracking issue #7868). It was very hard to
modularize `Installable` parsing when there were two completion
arguments. I wouldn't go as far as to say it is *easy* now, but at least
it is less hard (and the completions test finally passed).
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
2023-10-23 16:03:11 +03:00
|
|
|
std::vector<FlakeRef> getFlakeRefsForCompletion() override;
|
2020-06-08 17:20:00 +03:00
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
private:
|
|
|
|
|
|
|
|
std::vector<std::string> rawInstallables;
|
|
|
|
};
|
2023-10-16 17:42:15 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A command that operates on a list of "installables", which can be
|
|
|
|
* store paths, attribute paths, Nix expressions, etc.
|
|
|
|
*/
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
struct InstallablesCommand : RawInstallablesCommand
|
|
|
|
{
|
|
|
|
virtual void run(ref<Store> store, Installables && installables) = 0;
|
2017-04-25 13:06:32 +03:00
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
void run(ref<Store> store, std::vector<std::string> && rawInstallables) override;
|
2017-04-25 13:06:32 +03:00
|
|
|
};
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* A command that operates on exactly one "installable".
|
|
|
|
*/
|
2017-08-29 17:18:00 +03:00
|
|
|
struct InstallableCommand : virtual Args, SourceExprCommand
|
|
|
|
{
|
2023-02-05 03:45:40 +02:00
|
|
|
InstallableCommand();
|
2017-08-29 17:18:00 +03:00
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
virtual void run(ref<Store> store, ref<Installable> installable) = 0;
|
|
|
|
|
|
|
|
void run(ref<Store> store) override;
|
2017-08-29 17:18:00 +03:00
|
|
|
|
Overhaul completions, redo #6693 (#8131)
As I complained in
https://github.com/NixOS/nix/pull/6784#issuecomment-1421777030 (a
comment on the wrong PR, sorry again!), #6693 introduced a second
completions mechanism to fix a bug. Having two completion mechanisms
isn't so nice.
As @thufschmitt also pointed out, it was a bummer to go from `FlakeRef`
to `std::string` when collecting flake refs. Now it is `FlakeRefs`
again.
The underlying issue that sought to work around was that completion of
arguments not at the end can still benefit from the information from
latter arguments.
To fix this better, we rip out that change and simply defer all
completion processing until after all the (regular, already-complete)
arguments have been passed.
In addition, I noticed the original completion logic used some global
variables. I do not like global variables, because even if they save
lines of code, they also obfuscate the architecture of the code.
I got rid of them moved them to a new `RootArgs` class, which now has
`parseCmdline` instead of `Args`. The idea is that we have many argument
parsers from subcommands and what-not, but only one root args that owns
the other per actual parsing invocation. The state that was global is
now part of the root args instead.
This did, admittedly, add a bunch of new code. And I do feel bad about
that. So I went and added a lot of API docs to try to at least make the
current state of things clear to the next person.
--
This is needed for RFC 134 (tracking issue #7868). It was very hard to
modularize `Installable` parsing when there were two completion
arguments. I wouldn't go as far as to say it is *easy* now, but at least
it is less hard (and the completions test finally passed).
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
2023-10-23 16:03:11 +03:00
|
|
|
std::vector<FlakeRef> getFlakeRefsForCompletion() override;
|
2020-06-08 17:20:00 +03:00
|
|
|
|
2017-08-29 17:18:00 +03:00
|
|
|
private:
|
|
|
|
|
2019-12-15 00:15:36 +02:00
|
|
|
std::string _installable{"."};
|
2017-08-29 17:18:00 +03:00
|
|
|
};
|
|
|
|
|
2023-02-05 01:27:17 +02:00
|
|
|
struct MixOperateOnOptions : virtual Args
|
|
|
|
{
|
|
|
|
OperateOn operateOn = OperateOn::Output;
|
|
|
|
|
|
|
|
MixOperateOnOptions();
|
|
|
|
};
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* A command that operates on zero or more extant store paths.
|
|
|
|
*
|
|
|
|
* If the argument the user passes is a some sort of recipe for a path
|
|
|
|
* not yet built, it must be built first.
|
|
|
|
*/
|
2023-02-05 01:27:17 +02:00
|
|
|
struct BuiltPathsCommand : InstallablesCommand, virtual MixOperateOnOptions
|
2017-04-25 14:20:26 +03:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
bool recursive = false;
|
|
|
|
bool all = false;
|
|
|
|
|
2018-03-30 01:56:13 +03:00
|
|
|
protected:
|
|
|
|
|
2020-07-15 21:05:42 +03:00
|
|
|
Realise realiseMode = Realise::Derivation;
|
2018-03-30 01:56:13 +03:00
|
|
|
|
2017-04-25 14:20:26 +03:00
|
|
|
public:
|
|
|
|
|
2021-05-17 09:45:08 +03:00
|
|
|
BuiltPathsCommand(bool recursive = false);
|
2017-04-25 14:20:26 +03:00
|
|
|
|
2021-09-27 11:53:09 +03:00
|
|
|
virtual void run(ref<Store> store, BuiltPaths && paths) = 0;
|
2017-04-25 14:20:26 +03:00
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
void run(ref<Store> store, Installables && installables) override;
|
2019-04-19 17:07:37 +03:00
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
void applyDefaultInstallables(std::vector<std::string> & rawInstallables) override;
|
2017-04-25 14:20:26 +03:00
|
|
|
};
|
|
|
|
|
2021-05-17 09:45:08 +03:00
|
|
|
struct StorePathsCommand : public BuiltPathsCommand
|
2020-12-14 18:24:30 +02:00
|
|
|
{
|
|
|
|
StorePathsCommand(bool recursive = false);
|
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
virtual void run(ref<Store> store, StorePaths && storePaths) = 0;
|
2020-12-14 18:24:30 +02:00
|
|
|
|
2021-09-27 11:53:09 +03:00
|
|
|
void run(ref<Store> store, BuiltPaths && paths) override;
|
2020-12-14 18:24:30 +02:00
|
|
|
};
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* A command that operates on exactly one store path.
|
|
|
|
*/
|
2021-02-12 19:33:28 +02:00
|
|
|
struct StorePathCommand : public StorePathsCommand
|
2017-05-04 15:16:26 +03:00
|
|
|
{
|
2019-12-05 20:11:09 +02:00
|
|
|
virtual void run(ref<Store> store, const StorePath & storePath) = 0;
|
2017-05-04 15:16:26 +03:00
|
|
|
|
Make command infra less stateful and more regular
Already, we had classes like `BuiltPathsCommand` and `StorePathsCommand`
which provided alternative `run` virtual functions providing the
implementation with more arguments. This was a very nice and easy way to
make writing command; just fill in the virtual functions and it is
fairly clear what to do.
However, exception to this pattern were `Installable{,s}Command`. These
two classes instead just had a field where the installables would be
stored, and various side-effecting `prepare` and `load` machinery too
fill them in. Command would wish out those fields.
This isn't so clear to use.
What this commit does is make those command classes like the others,
with richer `run` functions.
Not only does this restore the pattern making commands easier to write,
it has a number of other benefits:
- `prepare` and `load` are gone entirely! One command just hands just
hands off to the next.
- `useDefaultInstallables` because `defaultInstallables`. This takes
over `prepare` for the one case that needs it, and provides enough
flexiblity to handle `nix repl`'s idiosyncratic migration.
- We can use `ref` instead of `std::shared_ptr`. The former must be
initialized (so it is like Rust's `Box` rather than `Option<Box>`,
This expresses the invariant that the installable are in fact
initialized much better.
This is possible because since we just have local variables not
fields, we can stop worrying about the not-yet-initialized case.
- Fewer lines of code! (Finally I have a large refactor that makes the
number go down not up...)
- `nix repl` is now implemented in a clearer way.
The last item deserves further mention. `nix repl` is not like the other
installable commands because instead working from once-loaded
installables, it needs to be able to load them again and again.
To properly support this, we make a new superclass
`RawInstallablesCommand`. This class has the argument parsing and
completion logic, but does *not* hand off parsed installables but
instead just the raw string arguments.
This is exactly what `nix repl` needs, and allows us to instead of
having the logic awkwardly split between `prepare`,
`useDefaultInstallables,` and `load`, have everything right next to each
other. I think this will enable future simplifications of that argument
defaulting logic, but I am saving those for a future PR --- best to keep
code motion and more complicated boolean expression rewriting separate
steps.
The "diagnostic ignored `-Woverloaded-virtual`" pragma helps because C++
doesn't like our many `run` methods. In our case, we don't mind the
shadowing it all --- it is *intentional* that the derived class only
provides a `run` method, and doesn't call any of the overridden `run`
methods.
Helps with https://github.com/NixOS/rfcs/pull/134
2023-02-04 19:03:47 +02:00
|
|
|
void run(ref<Store> store, StorePaths && storePaths) override;
|
2017-05-04 15:16:26 +03:00
|
|
|
};
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/**
|
|
|
|
* A helper class for registering \ref Command commands globally.
|
|
|
|
*/
|
2016-02-09 22:28:29 +02:00
|
|
|
struct RegisterCommand
|
|
|
|
{
|
2020-12-03 18:55:27 +02:00
|
|
|
typedef std::map<std::vector<std::string>, std::function<ref<Command>()>> Commands;
|
2019-06-18 17:01:35 +03:00
|
|
|
static Commands * commands;
|
2016-02-09 22:28:29 +02:00
|
|
|
|
2020-12-03 18:55:27 +02:00
|
|
|
RegisterCommand(std::vector<std::string> && name,
|
2019-06-18 17:01:35 +03:00
|
|
|
std::function<ref<Command>()> command)
|
2016-02-09 22:28:29 +02:00
|
|
|
{
|
2019-06-18 17:01:35 +03:00
|
|
|
if (!commands) commands = new Commands;
|
|
|
|
commands->emplace(name, command);
|
2016-02-09 22:28:29 +02:00
|
|
|
}
|
2020-12-03 18:55:27 +02:00
|
|
|
|
|
|
|
static nix::Commands getCommandsFor(const std::vector<std::string> & prefix);
|
2016-02-09 22:28:29 +02:00
|
|
|
};
|
|
|
|
|
2019-06-18 17:01:35 +03:00
|
|
|
template<class T>
|
|
|
|
static RegisterCommand registerCommand(const std::string & name)
|
|
|
|
{
|
2020-12-03 18:55:27 +02:00
|
|
|
return RegisterCommand({name}, [](){ return make_ref<T>(); });
|
2019-06-18 17:01:35 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 18:55:27 +02:00
|
|
|
template<class T>
|
|
|
|
static RegisterCommand registerCommand2(std::vector<std::string> && name)
|
|
|
|
{
|
|
|
|
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
|
2019-06-18 17:01:35 +03:00
|
|
|
}
|
|
|
|
|
2020-03-30 20:14:17 +03:00
|
|
|
struct MixProfile : virtual StoreCommand
|
2019-07-12 16:32:17 +03:00
|
|
|
{
|
|
|
|
std::optional<Path> profile;
|
|
|
|
|
|
|
|
MixProfile();
|
|
|
|
|
|
|
|
/* If 'profile' is set, make it point at 'storePath'. */
|
2019-12-11 15:53:30 +02:00
|
|
|
void updateProfile(const StorePath & storePath);
|
2019-07-12 16:32:17 +03:00
|
|
|
|
|
|
|
/* If 'profile' is set, make it point at the store path produced
|
|
|
|
by 'buildables'. */
|
2021-05-12 17:19:51 +03:00
|
|
|
void updateProfile(const BuiltPaths & buildables);
|
2019-07-12 16:32:17 +03:00
|
|
|
};
|
|
|
|
|
2019-10-22 01:21:58 +03:00
|
|
|
struct MixDefaultProfile : MixProfile
|
|
|
|
{
|
|
|
|
MixDefaultProfile();
|
|
|
|
};
|
|
|
|
|
2019-11-08 01:16:48 +02:00
|
|
|
struct MixEnvironment : virtual Args {
|
|
|
|
|
|
|
|
StringSet keep, unset;
|
|
|
|
Strings stringsEnv;
|
|
|
|
std::vector<char*> vectorEnv;
|
|
|
|
bool ignoreEnvironment;
|
|
|
|
|
|
|
|
MixEnvironment();
|
|
|
|
|
2023-10-16 17:42:15 +03:00
|
|
|
/***
|
|
|
|
* Modify global environ based on `ignoreEnvironment`, `keep`, and
|
|
|
|
* `unset`. It's expected that exec will be called before this class
|
|
|
|
* goes out of scope, otherwise `environ` will become invalid.
|
|
|
|
*/
|
2019-11-08 01:16:48 +02:00
|
|
|
void setEnviron();
|
|
|
|
};
|
|
|
|
|
2023-08-12 21:51:19 +03:00
|
|
|
void completeFlakeInputPath(
|
|
|
|
AddCompletions & completions,
|
|
|
|
ref<EvalState> evalState,
|
|
|
|
const std::vector<FlakeRef> & flakeRefs,
|
|
|
|
std::string_view prefix);
|
|
|
|
|
Overhaul completions, redo #6693 (#8131)
As I complained in
https://github.com/NixOS/nix/pull/6784#issuecomment-1421777030 (a
comment on the wrong PR, sorry again!), #6693 introduced a second
completions mechanism to fix a bug. Having two completion mechanisms
isn't so nice.
As @thufschmitt also pointed out, it was a bummer to go from `FlakeRef`
to `std::string` when collecting flake refs. Now it is `FlakeRefs`
again.
The underlying issue that sought to work around was that completion of
arguments not at the end can still benefit from the information from
latter arguments.
To fix this better, we rip out that change and simply defer all
completion processing until after all the (regular, already-complete)
arguments have been passed.
In addition, I noticed the original completion logic used some global
variables. I do not like global variables, because even if they save
lines of code, they also obfuscate the architecture of the code.
I got rid of them moved them to a new `RootArgs` class, which now has
`parseCmdline` instead of `Args`. The idea is that we have many argument
parsers from subcommands and what-not, but only one root args that owns
the other per actual parsing invocation. The state that was global is
now part of the root args instead.
This did, admittedly, add a bunch of new code. And I do feel bad about
that. So I went and added a lot of API docs to try to at least make the
current state of things clear to the next person.
--
This is needed for RFC 134 (tracking issue #7868). It was very hard to
modularize `Installable` parsing when there were two completion
arguments. I wouldn't go as far as to say it is *easy* now, but at least
it is less hard (and the completions test finally passed).
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
2023-10-23 16:03:11 +03:00
|
|
|
void completeFlakeRef(AddCompletions & completions, ref<Store> store, std::string_view prefix);
|
2020-06-05 15:09:12 +03:00
|
|
|
|
|
|
|
void completeFlakeRefWithFragment(
|
Overhaul completions, redo #6693 (#8131)
As I complained in
https://github.com/NixOS/nix/pull/6784#issuecomment-1421777030 (a
comment on the wrong PR, sorry again!), #6693 introduced a second
completions mechanism to fix a bug. Having two completion mechanisms
isn't so nice.
As @thufschmitt also pointed out, it was a bummer to go from `FlakeRef`
to `std::string` when collecting flake refs. Now it is `FlakeRefs`
again.
The underlying issue that sought to work around was that completion of
arguments not at the end can still benefit from the information from
latter arguments.
To fix this better, we rip out that change and simply defer all
completion processing until after all the (regular, already-complete)
arguments have been passed.
In addition, I noticed the original completion logic used some global
variables. I do not like global variables, because even if they save
lines of code, they also obfuscate the architecture of the code.
I got rid of them moved them to a new `RootArgs` class, which now has
`parseCmdline` instead of `Args`. The idea is that we have many argument
parsers from subcommands and what-not, but only one root args that owns
the other per actual parsing invocation. The state that was global is
now part of the root args instead.
This did, admittedly, add a bunch of new code. And I do feel bad about
that. So I went and added a lot of API docs to try to at least make the
current state of things clear to the next person.
--
This is needed for RFC 134 (tracking issue #7868). It was very hard to
modularize `Installable` parsing when there were two completion
arguments. I wouldn't go as far as to say it is *easy* now, but at least
it is less hard (and the completions test finally passed).
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
2023-10-23 16:03:11 +03:00
|
|
|
AddCompletions & completions,
|
2020-06-05 15:09:12 +03:00
|
|
|
ref<EvalState> evalState,
|
|
|
|
flake::LockFlags lockFlags,
|
|
|
|
Strings attrPathPrefixes,
|
|
|
|
const Strings & defaultFlakeAttrPaths,
|
|
|
|
std::string_view prefix);
|
|
|
|
|
2021-01-13 00:51:07 +02:00
|
|
|
std::string showVersions(const std::set<std::string> & versions);
|
|
|
|
|
2020-07-16 18:00:42 +03:00
|
|
|
void printClosureDiff(
|
|
|
|
ref<Store> store,
|
|
|
|
const StorePath & beforePath,
|
|
|
|
const StorePath & afterPath,
|
|
|
|
std::string_view indent);
|
|
|
|
|
2016-02-09 22:28:29 +02:00
|
|
|
}
|