1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-17 07:52:43 +01:00

Apply clang-format universally.

* It is tough to contribute to a project that doesn't use a formatter,
* It is extra hard to contribute to a project which has configured the formatter, but ignores it for some files
* Code formatting makes it harder to hide obscure / weird bugs by accident or on purpose,

Let's rip the bandaid off?

Note that PRs currently in flight should be able to be merged relatively easily by applying `clang-format` to their tip prior to merge.
This commit is contained in:
Graham Christensen 2025-07-18 12:47:27 -04:00
parent 41bf87ec70
commit e4f62e4608
587 changed files with 23258 additions and 23135 deletions

View file

@ -10,7 +10,7 @@
#include <string>
#include <regex>
#ifndef _WIN32
# include <glob.h>
# include <glob.h>
#endif
namespace nix {
@ -24,14 +24,16 @@ void Args::addFlag(Flag && flag_)
longFlags[flag->longName] = flag;
for (auto & alias : flag->aliases)
longFlags[alias] = flag;
if (flag->shortName) shortFlags[flag->shortName] = flag;
if (flag->shortName)
shortFlags[flag->shortName] = flag;
}
void Args::removeFlag(const std::string & longName)
{
auto flag = longFlags.find(longName);
assert(flag != longFlags.end());
if (flag->second->shortName) shortFlags.erase(flag->second->shortName);
if (flag->second->shortName)
shortFlags.erase(flag->second->shortName);
longFlags.erase(flag);
}
@ -51,10 +53,7 @@ void Completions::add(std::string completion, std::string description)
if (needs_ellipsis)
description.append(" [...]");
}
completions.insert(Completion {
.completion = completion,
.description = description
});
completions.insert(Completion{.completion = completion, .description = description});
}
auto Completion::operator<=>(const Completion & other) const noexcept = default;
@ -74,7 +73,8 @@ RootArgs & Args::getRoot()
std::optional<std::string> RootArgs::needsCompletion(std::string_view s)
{
if (!completions) return {};
if (!completions)
return {};
auto i = s.find(completionMarker);
if (i != std::string::npos)
return std::string(s.begin(), i);
@ -86,7 +86,8 @@ std::optional<std::string> RootArgs::needsCompletion(std::string_view s)
*
* Except we can't recursively reference the Parser typedef, so we have to write a class.
*/
struct Parser {
struct Parser
{
std::string_view remaining;
/**
@ -94,12 +95,14 @@ struct Parser {
*/
virtual void operator()(std::shared_ptr<Parser> & state, Strings & r) = 0;
Parser(std::string_view s) : remaining(s) {};
Parser(std::string_view s)
: remaining(s) {};
virtual ~Parser() { };
virtual ~Parser() {};
};
struct ParseQuoted : public Parser {
struct ParseQuoted : public Parser
{
/**
* @brief Accumulated string
*
@ -107,13 +110,14 @@ struct ParseQuoted : public Parser {
*/
std::string acc;
ParseQuoted(std::string_view s) : Parser(s) {};
ParseQuoted(std::string_view s)
: Parser(s) {};
virtual void operator()(std::shared_ptr<Parser> & state, Strings & r) override;
};
struct ParseUnquoted : public Parser {
struct ParseUnquoted : public Parser
{
/**
* @brief Accumulated string
*
@ -122,9 +126,11 @@ struct ParseUnquoted : public Parser {
*/
std::string acc;
ParseUnquoted(std::string_view s) : Parser(s) {};
ParseUnquoted(std::string_view s)
: Parser(s) {};
virtual void operator()(std::shared_ptr<Parser> & state, Strings & r) override {
virtual void operator()(std::shared_ptr<Parser> & state, Strings & r) override
{
if (remaining.empty()) {
if (!acc.empty())
r.push_back(acc);
@ -132,111 +138,116 @@ struct ParseUnquoted : public Parser {
return;
}
switch (remaining[0]) {
case ' ': case '\t': case '\n': case '\r':
if (!acc.empty())
r.push_back(acc);
state = std::make_shared<ParseUnquoted>(ParseUnquoted(remaining.substr(1)));
case ' ':
case '\t':
case '\n':
case '\r':
if (!acc.empty())
r.push_back(acc);
state = std::make_shared<ParseUnquoted>(ParseUnquoted(remaining.substr(1)));
return;
case '`':
if (remaining.size() > 1 && remaining[1] == '`') {
state = std::make_shared<ParseQuoted>(ParseQuoted(remaining.substr(2)));
return;
case '`':
if (remaining.size() > 1 && remaining[1] == '`') {
state = std::make_shared<ParseQuoted>(ParseQuoted(remaining.substr(2)));
return;
}
else
throw Error("single backtick is not a supported syntax in the nix shebang.");
} else
throw Error("single backtick is not a supported syntax in the nix shebang.");
// reserved characters
// meaning to be determined, or may be reserved indefinitely so that
// #!nix syntax looks unambiguous
case '$':
case '*':
case '~':
case '<':
case '>':
case '|':
case ';':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '\'':
case '"':
case '\\':
throw Error("unsupported unquoted character in nix shebang: " + std::string(1, remaining[0]) + ". Use double backticks to escape?");
// reserved characters
// meaning to be determined, or may be reserved indefinitely so that
// #!nix syntax looks unambiguous
case '$':
case '*':
case '~':
case '<':
case '>':
case '|':
case ';':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '\'':
case '"':
case '\\':
throw Error(
"unsupported unquoted character in nix shebang: " + std::string(1, remaining[0])
+ ". Use double backticks to escape?");
case '#':
if (acc.empty()) {
throw Error ("unquoted nix shebang argument cannot start with #. Use double backticks to escape?");
} else {
acc += remaining[0];
remaining = remaining.substr(1);
return;
}
default:
case '#':
if (acc.empty()) {
throw Error("unquoted nix shebang argument cannot start with #. Use double backticks to escape?");
} else {
acc += remaining[0];
remaining = remaining.substr(1);
return;
}
default:
acc += remaining[0];
remaining = remaining.substr(1);
return;
}
assert(false);
}
};
void ParseQuoted::operator()(std::shared_ptr<Parser> &state, Strings & r) {
void ParseQuoted::operator()(std::shared_ptr<Parser> & state, Strings & r)
{
if (remaining.empty()) {
throw Error("unterminated quoted string in nix shebang");
}
switch (remaining[0]) {
case ' ':
if ((remaining.size() == 3 && remaining[1] == '`' && remaining[2] == '`')
|| (remaining.size() > 3 && remaining[1] == '`' && remaining[2] == '`' && remaining[3] != '`')) {
// exactly two backticks mark the end of a quoted string, but a preceding space is ignored if present.
state = std::make_shared<ParseUnquoted>(ParseUnquoted(remaining.substr(3)));
r.push_back(acc);
return;
}
else {
// just a normal space
acc += remaining[0];
remaining = remaining.substr(1);
return;
}
case '`':
// exactly two backticks mark the end of a quoted string
if ((remaining.size() == 2 && remaining[1] == '`')
|| (remaining.size() > 2 && remaining[1] == '`' && remaining[2] != '`')) {
state = std::make_shared<ParseUnquoted>(ParseUnquoted(remaining.substr(2)));
r.push_back(acc);
return;
}
// a sequence of at least 3 backticks is one escape-backtick which is ignored, followed by any number of backticks, which are verbatim
else if (remaining.size() >= 3 && remaining[1] == '`' && remaining[2] == '`') {
// ignore "escape" backtick
remaining = remaining.substr(1);
// add the rest
while (remaining.size() > 0 && remaining[0] == '`') {
acc += '`';
remaining = remaining.substr(1);
}
return;
}
else {
acc += remaining[0];
remaining = remaining.substr(1);
return;
}
default:
case ' ':
if ((remaining.size() == 3 && remaining[1] == '`' && remaining[2] == '`')
|| (remaining.size() > 3 && remaining[1] == '`' && remaining[2] == '`' && remaining[3] != '`')) {
// exactly two backticks mark the end of a quoted string, but a preceding space is ignored if present.
state = std::make_shared<ParseUnquoted>(ParseUnquoted(remaining.substr(3)));
r.push_back(acc);
return;
} else {
// just a normal space
acc += remaining[0];
remaining = remaining.substr(1);
return;
}
case '`':
// exactly two backticks mark the end of a quoted string
if ((remaining.size() == 2 && remaining[1] == '`')
|| (remaining.size() > 2 && remaining[1] == '`' && remaining[2] != '`')) {
state = std::make_shared<ParseUnquoted>(ParseUnquoted(remaining.substr(2)));
r.push_back(acc);
return;
}
// a sequence of at least 3 backticks is one escape-backtick which is ignored, followed by any number of
// backticks, which are verbatim
else if (remaining.size() >= 3 && remaining[1] == '`' && remaining[2] == '`') {
// ignore "escape" backtick
remaining = remaining.substr(1);
// add the rest
while (remaining.size() > 0 && remaining[0] == '`') {
acc += '`';
remaining = remaining.substr(1);
}
return;
} else {
acc += remaining[0];
remaining = remaining.substr(1);
return;
}
default:
acc += remaining[0];
remaining = remaining.substr(1);
return;
}
assert(false);
}
Strings parseShebangContent(std::string_view s) {
Strings parseShebangContent(std::string_view s)
{
Strings result;
std::shared_ptr<Parser> parserState(std::make_shared<ParseUnquoted>(ParseUnquoted(s)));
@ -268,22 +279,22 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang)
// if we have at least one argument, it's the name of an
// executable file, and it starts with "#!".
Strings savedArgs;
if (allowShebang){
if (allowShebang) {
auto script = *cmdline.begin();
try {
std::ifstream stream(script);
char shebang[3]={0,0,0};
stream.get(shebang,3);
if (strncmp(shebang,"#!",2) == 0){
for (auto pos = std::next(cmdline.begin()); pos != cmdline.end();pos++)
char shebang[3] = {0, 0, 0};
stream.get(shebang, 3);
if (strncmp(shebang, "#!", 2) == 0) {
for (auto pos = std::next(cmdline.begin()); pos != cmdline.end(); pos++)
savedArgs.push_back(*pos);
cmdline.clear();
std::string line;
std::getline(stream,line);
std::getline(stream, line);
static const std::string commentChars("#/\\%@*-(");
std::string shebangContent;
while (std::getline(stream,line) && !line.empty() && commentChars.find(line[0]) != std::string::npos){
while (std::getline(stream, line) && !line.empty() && commentChars.find(line[0]) != std::string::npos) {
line = chomp(line);
std::smatch match;
@ -297,12 +308,13 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang)
}
cmdline.push_back(script);
commandBaseDir = dirOf(script);
for (auto pos = savedArgs.begin(); pos != savedArgs.end();pos++)
for (auto pos = savedArgs.begin(); pos != savedArgs.end(); pos++)
cmdline.push_back(*pos);
}
} catch (SystemError &) { }
} catch (SystemError &) {
}
}
for (auto pos = cmdline.begin(); pos != cmdline.end(); ) {
for (auto pos = cmdline.begin(); pos != cmdline.end();) {
auto arg = *pos;
@ -310,7 +322,8 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang)
`-j3` -> `-j 3`). */
if (!dashDash && arg.length() > 2 && arg[0] == '-' && arg[1] != '-' && isalpha(arg[1])) {
*pos = (std::string) "-" + arg[1];
auto next = pos; ++next;
auto next = pos;
++next;
for (unsigned int j = 2; j < arg.length(); j++)
if (isalpha(arg[j]))
cmdline.insert(next, (std::string) "-" + arg[j]);
@ -324,12 +337,10 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang)
if (!dashDash && arg == "--") {
dashDash = true;
++pos;
}
else if (!dashDash && std::string(arg, 0, 1) == "-") {
} else if (!dashDash && std::string(arg, 0, 1) == "-") {
if (!processFlag(pos, cmdline.end()))
throw UsageError("unrecognised flag '%1%'", arg);
}
else {
} else {
pos = rewriteArgs(cmdline, pos);
pendingArgs.push_back(*pos++);
if (processArgs(pendingArgs, false))
@ -377,12 +388,12 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
std::vector<std::string> args;
bool anyCompleted = false;
for (size_t n = 0 ; n < flag.handler.arity; ++n) {
for (size_t n = 0; n < flag.handler.arity; ++n) {
if (pos == end) {
if (flag.handler.arity == ArityAny || anyCompleted) break;
if (flag.handler.arity == ArityAny || anyCompleted)
break;
throw UsageError(
"flag '%s' requires %d argument(s), but only %d were given",
name, flag.handler.arity, n);
"flag '%s' requires %d argument(s), but only %d were given", name, flag.handler.arity, n);
}
if (auto prefix = rootArgs.needsCompletion(*pos)) {
anyCompleted = true;
@ -404,9 +415,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
if (std::string(*pos, 0, 2) == "--") {
if (auto prefix = rootArgs.needsCompletion(*pos)) {
for (auto & [name, flag] : longFlags) {
if (!hiddenCategories.count(flag->category)
&& hasPrefix(name, std::string(*prefix, 2)))
{
if (!hiddenCategories.count(flag->category) && hasPrefix(name, std::string(*prefix, 2))) {
if (auto & f = flag->experimentalFeature)
rootArgs.flagExperimentalFeatures.insert(*f);
rootArgs.completions->add("--" + name, flag->description);
@ -415,14 +424,16 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
return false;
}
auto i = longFlags.find(std::string(*pos, 2));
if (i == longFlags.end()) return false;
if (i == longFlags.end())
return false;
return process("--" + i->first, *i->second);
}
if (std::string(*pos, 0, 1) == "-" && pos->size() == 2) {
auto c = (*pos)[1];
auto i = shortFlags.find(c);
if (i == shortFlags.end()) return false;
if (i == shortFlags.end())
return false;
return process(std::string("-") + c, *i->second);
}
@ -452,12 +463,11 @@ bool Args::processArgs(const Strings & args, bool finish)
bool res = false;
if ((exp.handler.arity == ArityAny && finish) ||
(exp.handler.arity != ArityAny && args.size() == exp.handler.arity))
{
if ((exp.handler.arity == ArityAny && finish)
|| (exp.handler.arity != ArityAny && args.size() == exp.handler.arity)) {
std::vector<std::string> ss;
bool anyCompleted = false;
for (const auto &[n, s] : enumerate(args)) {
for (const auto & [n, s] : enumerate(args)) {
if (auto prefix = rootArgs.needsCompletion(s)) {
anyCompleted = true;
ss.push_back(*prefix);
@ -479,11 +489,7 @@ bool Args::processArgs(const Strings & args, bool finish)
except that it will only adjust the next and prev pointers of the list
elements, meaning the actual contents don't move in memory. This is
critical to prevent invalidating internal pointers! */
processedArgs.splice(
processedArgs.end(),
expectedArgs,
expectedArgs.begin(),
++expectedArgs.begin());
processedArgs.splice(processedArgs.end(), expectedArgs, expectedArgs.begin(), ++expectedArgs.begin());
res = true;
}
@ -501,7 +507,8 @@ nlohmann::json Args::toJSON()
for (auto & [name, flag] : longFlags) {
auto j = nlohmann::json::object();
j["hiddenCategory"] = hiddenCategories.count(flag->category) > 0;
if (flag->aliases.count(name)) continue;
if (flag->aliases.count(name))
continue;
if (flag->shortName)
j["shortName"] = std::string(1, flag->shortName);
if (flag->description != "")
@ -531,32 +538,34 @@ nlohmann::json Args::toJSON()
res["flags"] = std::move(flags);
res["args"] = std::move(args);
auto s = doc();
if (s != "") res.emplace("doc", stripIndentation(s));
if (s != "")
res.emplace("doc", stripIndentation(s));
return res;
}
static void _completePath(AddCompletions & completions, std::string_view prefix, bool onlyDirs)
{
completions.setType(Completions::Type::Filenames);
#ifndef _WIN32 // TODO implement globbing completions on Windows
#ifndef _WIN32 // TODO implement globbing completions on Windows
glob_t globbuf;
int flags = GLOB_NOESCAPE;
#ifdef GLOB_ONLYDIR
# ifdef GLOB_ONLYDIR
if (onlyDirs)
flags |= GLOB_ONLYDIR;
#endif
# endif
// using expandTilde here instead of GLOB_TILDE(_CHECK) so that ~<Tab> expands to /home/user/
if (glob((expandTilde(prefix) + "*").c_str(), flags, nullptr, &globbuf) == 0) {
for (size_t i = 0; i < globbuf.gl_pathc; ++i) {
if (onlyDirs) {
auto st = stat(globbuf.gl_pathv[i]);
if (!S_ISDIR(st.st_mode)) continue;
if (!S_ISDIR(st.st_mode))
continue;
}
completions.add(globbuf.gl_pathv[i]);
}
}
globfree(&globbuf);
#endif
#endif
}
void Args::completePath(AddCompletions & completions, size_t, std::string_view prefix)
@ -569,53 +578,56 @@ void Args::completeDir(AddCompletions & completions, size_t, std::string_view pr
_completePath(completions, prefix, true);
}
Strings argvToStrings(int argc, char * * argv)
Strings argvToStrings(int argc, char ** argv)
{
Strings args;
argc--; argv++;
while (argc--) args.push_back(*argv++);
argc--;
argv++;
while (argc--)
args.push_back(*argv++);
return args;
}
std::optional<ExperimentalFeature> Command::experimentalFeature ()
std::optional<ExperimentalFeature> Command::experimentalFeature()
{
return { Xp::NixCommand };
return {Xp::NixCommand};
}
MultiCommand::MultiCommand(std::string_view commandName, const Commands & commands_)
: commands(commands_)
, commandName(commandName)
{
expectArgs({
.label = "subcommand",
.optional = true,
.handler = {[=,this](std::string s) {
assert(!command);
auto i = commands.find(s);
if (i == commands.end()) {
StringSet commandNames;
for (auto & [name, _] : commands)
commandNames.insert(name);
auto suggestions = Suggestions::bestMatches(commandNames, s);
throw UsageError(suggestions, "'%s' is not a recognised command", s);
}
command = {s, i->second()};
command->second->parent = this;
}},
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
for (auto & [name, command] : commands)
if (hasPrefix(name, prefix))
completions.add(name);
}}
});
expectArgs(
{.label = "subcommand",
.optional = true,
.handler = {[=, this](std::string s) {
assert(!command);
auto i = commands.find(s);
if (i == commands.end()) {
StringSet commandNames;
for (auto & [name, _] : commands)
commandNames.insert(name);
auto suggestions = Suggestions::bestMatches(commandNames, s);
throw UsageError(suggestions, "'%s' is not a recognised command", s);
}
command = {s, i->second()};
command->second->parent = this;
}},
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
for (auto & [name, command] : commands)
if (hasPrefix(name, prefix))
completions.add(name);
}}});
categories[Command::catDefault] = "Available commands";
}
bool MultiCommand::processFlag(Strings::iterator & pos, Strings::iterator end)
{
if (Args::processFlag(pos, end)) return true;
if (command && command->second->processFlag(pos, end)) return true;
if (Args::processFlag(pos, end))
return true;
if (command && command->second->processFlag(pos, end))
return true;
return false;
}
@ -652,14 +664,15 @@ Strings::iterator MultiCommand::rewriteArgs(Strings & args, Strings::iterator po
if (command)
return command->second->rewriteArgs(args, pos);
if (aliasUsed || pos == args.end()) return pos;
if (aliasUsed || pos == args.end())
return pos;
auto arg = *pos;
auto i = aliases.find(arg);
if (i == aliases.end()) return pos;
if (i == aliases.end())
return pos;
auto & info = i->second;
if (info.status == AliasStatus::Deprecated) {
warn("'%s' is a deprecated alias for '%s'",
arg, concatStringsSep(" ", info.replacement));
warn("'%s' is a deprecated alias for '%s'", arg, concatStringsSep(" ", info.replacement));
}
pos = args.erase(pos);
for (auto j = info.replacement.rbegin(); j != info.replacement.rend(); ++j)
@ -668,4 +681,4 @@ Strings::iterator MultiCommand::rewriteArgs(Strings & args, Strings::iterator po
return pos;
}
}
} // namespace nix