Skip to content

Commit 925f10d

Browse files
authored
Merge pull request #14087 from NixOS/required-args
Args::Flag: Add `required` attribute
2 parents 090f7fb + eec4dec commit 925f10d

File tree

3 files changed

+32
-6
lines changed

3 files changed

+32
-6
lines changed

src/libutil/args.cc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang)
318318
} catch (SystemError &) {
319319
}
320320
}
321+
321322
for (auto pos = cmdline.begin(); pos != cmdline.end();) {
322323

323324
auto arg = *pos;
@@ -354,6 +355,9 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang)
354355

355356
processArgs(pendingArgs, true);
356357

358+
if (!completions)
359+
checkArgs();
360+
357361
initialFlagsProcessed();
358362

359363
/* Now that we are done parsing, make sure that any experimental
@@ -384,7 +388,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
384388

385389
auto & rootArgs = getRoot();
386390

387-
auto process = [&](const std::string & name, const Flag & flag) -> bool {
391+
auto process = [&](const std::string & name, Flag & flag) -> bool {
388392
++pos;
389393

390394
if (auto & f = flag.experimentalFeature)
@@ -413,6 +417,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
413417
}
414418
if (!anyCompleted)
415419
flag.handler.fun(std::move(args));
420+
flag.timesUsed++;
416421
return true;
417422
};
418423

@@ -504,6 +509,14 @@ bool Args::processArgs(const Strings & args, bool finish)
504509
return res;
505510
}
506511

512+
void Args::checkArgs()
513+
{
514+
for (auto & [name, flag] : longFlags) {
515+
if (flag->required && flag->timesUsed == 0)
516+
throw UsageError("required argument '--%s' is missing", name);
517+
}
518+
}
519+
507520
nlohmann::json Args::toJSON()
508521
{
509522
auto flags = nlohmann::json::object();
@@ -643,6 +656,13 @@ bool MultiCommand::processArgs(const Strings & args, bool finish)
643656
return Args::processArgs(args, finish);
644657
}
645658

659+
void MultiCommand::checkArgs()
660+
{
661+
Args::checkArgs();
662+
if (command)
663+
command->second->checkArgs();
664+
}
665+
646666
nlohmann::json MultiCommand::toJSON()
647667
{
648668
auto cmds = nlohmann::json::object();

src/libutil/include/nix/util/args.hh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,12 @@ public:
202202
Strings labels;
203203
Handler handler;
204204
CompleterClosure completer;
205+
bool required = false;
205206

206207
std::optional<ExperimentalFeature> experimentalFeature;
208+
209+
// FIXME: this should be private, but that breaks designated initializers.
210+
size_t timesUsed = 0;
207211
};
208212

209213
protected:
@@ -283,6 +287,8 @@ protected:
283287

284288
StringSet hiddenCategories;
285289

290+
virtual void checkArgs();
291+
286292
/**
287293
* Called after all command line flags before the first non-flag
288294
* argument (if any) have been processed.
@@ -428,6 +434,8 @@ public:
428434
protected:
429435
std::string commandName = "";
430436
bool aliasUsed = false;
437+
438+
void checkArgs() override;
431439
};
432440

433441
Strings argvToStrings(int argc, char ** argv);

src/nix/sigs.cc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ static auto rCmdSign = registerCommand2<CmdSign>({"store", "sign"});
144144

145145
struct CmdKeyGenerateSecret : Command
146146
{
147-
std::optional<std::string> keyName;
147+
std::string keyName;
148148

149149
CmdKeyGenerateSecret()
150150
{
@@ -153,6 +153,7 @@ struct CmdKeyGenerateSecret : Command
153153
.description = "Identifier of the key (e.g. `cache.example.org-1`).",
154154
.labels = {"name"},
155155
.handler = {&keyName},
156+
.required = true,
156157
});
157158
}
158159

@@ -170,11 +171,8 @@ struct CmdKeyGenerateSecret : Command
170171

171172
void run() override
172173
{
173-
if (!keyName)
174-
throw UsageError("required argument '--key-name' is missing");
175-
176174
logger->stop();
177-
writeFull(getStandardOutput(), SecretKey::generate(*keyName).to_string());
175+
writeFull(getStandardOutput(), SecretKey::generate(keyName).to_string());
178176
}
179177
};
180178

0 commit comments

Comments
 (0)