nix-super/src/libmain/shared.hh

148 lines
3.9 KiB
C++
Raw Normal View History

#pragma once
///@file
#include "file-descriptor.hh"
#include "processes.hh"
#include "args.hh"
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
#include "args/root.hh"
#include "common-args.hh"
#include "path.hh"
#include "derived-path.hh"
#include <signal.h>
2014-08-13 04:50:44 +03:00
namespace nix {
int handleExceptions(const std::string & programName, std::function<void()> fun);
/**
* Don't forget to call initPlugins() after settings are initialized!
* @param loadConfig Whether to load configuration from `nix.conf`, `NIX_CONFIG`, etc. May be disabled for unit tests.
*/
void initNix(bool loadConfig = true);
2014-08-13 04:50:44 +03:00
void parseCmdLine(int argc, char * * argv,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg);
2009-11-24 14:26:25 +02:00
void parseCmdLine(const std::string & programName, const Strings & args,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg);
void printVersion(const std::string & programName);
/**
* Ugh. No better place to put this.
*/
void printGCWarning();
class Store;
void printMissing(
ref<Store> store,
2021-04-05 16:48:18 +03:00
const std::vector<DerivedPath> & paths,
Verbosity lvl = lvlInfo);
void printMissing(ref<Store> store, const StorePathSet & willBuild,
const StorePathSet & willSubstitute, const StorePathSet & unknown,
2020-07-30 14:10:49 +03:00
uint64_t downloadSize, uint64_t narSize, Verbosity lvl = lvlInfo);
std::string getArg(const std::string & opt,
2014-08-13 04:50:44 +03:00
Strings::iterator & i, const Strings::iterator & end);
template<class N> N getIntArg(const std::string & opt,
Strings::iterator & i, const Strings::iterator & end, bool allowUnit)
2009-11-24 14:26:25 +02:00
{
++i;
if (i == end) throw UsageError("'%1%' requires an argument", opt);
return string2IntWithUnitPrefix<N>(*i);
2009-11-24 14:26:25 +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
struct LegacyArgs : public MixCommonArgs, public RootArgs
{
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg;
LegacyArgs(const std::string & programName,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg);
bool processFlag(Strings::iterator & pos, Strings::iterator end) override;
bool processArgs(const Strings & args, bool finish) override;
};
/**
* Show the manual page for the specified program.
*/
void showManPage(const std::string & name);
/**
* The constructor of this class starts a pager if standard output is a
* terminal and $PAGER is set. Standard output is redirected to the
* pager.
*/
class RunPager
{
public:
RunPager();
~RunPager();
private:
#ifndef _WIN32 // TODO re-enable on Windows, once we can start processes.
Pid pid;
#endif
Descriptor std_out;
};
extern volatile ::sig_atomic_t blockInt;
/* GC helpers. */
std::string showBytes(uint64_t bytes);
2015-09-18 02:22:06 +03:00
struct GCResults;
struct PrintFreed
{
bool show;
const GCResults & results;
PrintFreed(bool show, const GCResults & results)
: show(show), results(results) { }
~PrintFreed();
};
#ifndef _WIN32
/**
* Install a SIGSEGV handler to detect stack overflows.
*/
void detectStackOverflow();
/**
* Pluggable behavior to run in case of a stack overflow.
*
* Default value: defaultStackOverflowHandler.
*
* This is called by the handler installed by detectStackOverflow().
*
* This gives Nix library consumers a limit opportunity to report the error
* condition. The handler should exit the process.
* See defaultStackOverflowHandler() for a reference implementation.
*
* NOTE: Use with diligence, because this runs in the signal handler, with very
* limited stack space and a potentially a corrupted heap, all while the failed
* thread is blocked indefinitely. All functions called must be reentrant.
*/
2022-10-14 13:25:41 +03:00
extern std::function<void(siginfo_t * info, void * ctx)> stackOverflowHandler;
/**
* The default, robust implementation of stackOverflowHandler.
*
* Prints an error message directly to stderr using a syscall instead of the
* logger. Exits the process immediately after.
*/
2022-10-14 13:25:41 +03:00
void defaultStackOverflowHandler(siginfo_t * info, void * ctx);
#endif
}