While we expose macros for most of our different option types understood
by the "parse-options" subsystem, not every combination of fields that
has one as that would otherwise quickly lead to an explosion of macros.
Instead, we just initialize structures manually for those variants of
fields that don't have a macro.
Callsites that open-code these structure initialization don't use
designated initializers though and instead just provide values for each
of the fields that they want to initialize. This has three significant
downsides:
- Callsites need to specify all values up to the last field that they
care about. This often includes fields that should simply be left at
their default zero-initialized state, which adds distraction.
- Any reader not deeply familiar with the layout of the structure
has a hard time figuring out what the respective initializers mean.
- Reordering or introducing new fields in the middle of the structure
is impossible without adapting all callsites.
Convert all sites to instead use designated initializers, which we have
started using in our codebase quite a while ago. This allows us to skip
any default-initialized fields, gives the reader context by specifying
the field names and allows us to reorder or introduce new fields where
we want to.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committedApr 17, 2025 at 12:49 UTCd012ceb5f3351af0589a0c82b07059bce8c7b24b
24 files changed+443-158
archive.c
+26-9
index 8be4e7ac8d..67bba3cd30 100644--- a/archive.c+++ b/archive.c@@ -650,20 +650,37 @@ static int parse_archive_args(int argc, const char **argv, OPT_STRING(0, "format", &format, N_("fmt"), N_("archive format")), OPT_STRING(0, "prefix", &base, N_("prefix"), N_("prepend prefix to each pathname in the archive")),- { OPTION_CALLBACK, 0, "add-file", args, N_("file"),- N_("add untracked file to archive"), 0, add_file_cb,- (intptr_t)&base },- { OPTION_CALLBACK, 0, "add-virtual-file", args,- N_("path:content"), N_("add untracked file to archive"), 0,- add_file_cb, (intptr_t)&base },+ {+ .type = OPTION_CALLBACK,+ .long_name = "add-file",+ .value = args,+ .argh = N_("file"),+ .help = N_("add untracked file to archive"),+ .callback = add_file_cb,+ .defval = (intptr_t) &base,+ },+ {+ .type = OPTION_CALLBACK,+ .long_name = "add-virtual-file",+ .value = args,+ .argh = N_("path:content"),+ .help = N_("add untracked file to archive"),+ .callback = add_file_cb,+ .defval = (intptr_t) &base,+ }, OPT_STRING('o', "output", &output, N_("file"), N_("write the archive to this file")), OPT_BOOL(0, "worktree-attributes", &worktree_attributes, N_("read .gitattributes in working directory")), OPT__VERBOSE(&verbose, N_("report archived files on stderr")),- { OPTION_STRING, 0, "mtime", &mtime_option, N_("time"),- N_("set modification time of archive entries"),- PARSE_OPT_NONEG },+ {+ .type = OPTION_STRING,+ .long_name = "mtime",+ .value = &mtime_option,+ .argh = N_("time"),+ .help = N_("set modification time of archive entries"),+ .flags = PARSE_OPT_NONEG,+ }, OPT_NUMBER_CALLBACK(&compression_level, N_("set compression level"), number_callback), OPT_GROUP(""),
builtin/am.c
+20-8
index 3b61bd4c33..4afb519830 100644--- a/builtin/am.c+++ b/builtin/am.c@@ -2400,11 +2400,16 @@ int cmd_am(int argc, OPT_CMDMODE(0, "quit", &resume_mode, N_("abort the patching operation but keep HEAD where it is"), RESUME_QUIT),- { OPTION_CALLBACK, 0, "show-current-patch", &resume_mode,- "(diff|raw)",- N_("show the patch being applied"),- PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,- parse_opt_show_current_patch, RESUME_SHOW_PATCH_RAW },+ {+ .type = OPTION_CALLBACK,+ .long_name = "show-current-patch",+ .value = &resume_mode,+ .argh = "(diff|raw)",+ .help = N_("show the patch being applied"),+ .flags = PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,+ .callback = parse_opt_show_current_patch,+ .defval = RESUME_SHOW_PATCH_RAW,+ }, OPT_CMDMODE(0, "retry", &resume_mode, N_("try to apply current patch again"), RESUME_APPLY),@@ -2417,9 +2422,16 @@ int cmd_am(int argc, OPT_BOOL(0, "ignore-date", &state.ignore_date, N_("use current timestamp for author date")), OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),- { OPTION_STRING, 'S', "gpg-sign", &state.sign_commit, N_("key-id"),- N_("GPG-sign commits"),- PARSE_OPT_OPTARG, NULL, (intptr_t) "" },+ {+ .type = OPTION_STRING,+ .short_name = 'S',+ .long_name = "gpg-sign",+ .value = &state.sign_commit,+ .argh = N_("key-id"),+ .help = N_("GPG-sign commits"),+ .flags = PARSE_OPT_OPTARG,+ .defval = (intptr_t) "",+ }, OPT_CALLBACK_F(0, "empty", &state.empty_type, "(stop|drop|keep)", N_("how to handle empty patches"), PARSE_OPT_NONEG, am_option_parse_empty),
builtin/clone.c
+10-3
index 88276e5b7a..9c3547f41e 100644--- a/builtin/clone.c+++ b/builtin/clone.c@@ -930,9 +930,16 @@ int cmd_clone(int argc, N_("don't use local hardlinks, always copy")), OPT_BOOL('s', "shared", &option_shared, N_("setup as shared repository")),- { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules,- N_("pathspec"), N_("initialize submodules in the clone"),- PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." },+ {+ .type = OPTION_CALLBACK,+ .long_name = "recurse-submodules",+ .value = &option_recurse_submodules,+ .argh = N_("pathspec"),+ .help = N_("initialize submodules in the clone"),+ .flags = PARSE_OPT_OPTARG,+ .callback = recurse_submodules_cb,+ .defval = (intptr_t)".",+ }, OPT_ALIAS(0, "recursive", "recurse-submodules"), OPT_INTEGER('j', "jobs", &max_jobs, N_("number of submodules cloned in parallel")),
index d1427290f7..c4869733e1 100644--- a/builtin/grep.c+++ b/builtin/grep.c@@ -1017,10 +1017,16 @@ int cmd_grep(int argc, OPT_BOOL(0, "all-match", &opt.all_match, N_("show only matches from files that match all patterns")), OPT_GROUP(""),- { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,- N_("pager"), N_("show matching files in the pager"),- PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE,- NULL, (intptr_t)default_pager },+ {+ .type = OPTION_STRING,+ .short_name = 'O',+ .long_name = "open-files-in-pager",+ .value = &show_in_pager,+ .argh = N_("pager"),+ .help = N_("show matching files in the pager"),+ .flags = PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE,+ .defval = (intptr_t)default_pager,+ }, OPT_BOOL_F(0, "ext-grep", &external_grep_allowed__ignored, N_("allow calling of grep(1) (ignored by this build)"), PARSE_OPT_NOCOMPLETE),
builtin/init-db.c
+9-4
index 196dccdd77..4a950e44d8 100644--- a/builtin/init-db.c+++ b/builtin/init-db.c@@ -93,10 +93,15 @@ int cmd_init_db(int argc, N_("directory from which templates will be used")), OPT_SET_INT(0, "bare", &is_bare_repository_cfg, N_("create a bare repository"), 1),- { OPTION_CALLBACK, 0, "shared", &init_shared_repository,- N_("permissions"),- N_("specify that the git repository is to be shared amongst several users"),- PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},+ {+ .type = OPTION_CALLBACK,+ .long_name = "shared",+ .value = &init_shared_repository,+ .argh = N_("permissions"),+ .help = N_("specify that the git repository is to be shared amongst several users"),+ .flags = PARSE_OPT_OPTARG | PARSE_OPT_NONEG,+ .callback = shared_callback+ }, OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET), OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"), N_("separate git dir from working tree")),
builtin/ls-remote.c
+8-3
index 42f34e1236..01a4d4daa1 100644--- a/builtin/ls-remote.c+++ b/builtin/ls-remote.c@@ -67,9 +67,14 @@ int cmd_ls_remote(int argc, OPT__QUIET(&quiet, N_("do not print remote URL")), OPT_STRING(0, "upload-pack", &uploadpack, N_("exec"), N_("path of git-upload-pack on the remote host")),- { OPTION_STRING, 0, "exec", &uploadpack, N_("exec"),- N_("path of git-upload-pack on the remote host"),- PARSE_OPT_HIDDEN },+ {+ .type = OPTION_STRING,+ .long_name = "exec",+ .value = &uploadpack,+ .argh = N_("exec"),+ .help = N_("path of git-upload-pack on the remote host"),+ .flags = PARSE_OPT_HIDDEN,+ }, OPT_BIT('t', "tags", &flags, N_("limit to tags"), REF_TAGS), OPT_BIT('b', "branches", &flags, N_("limit to branches"), REF_BRANCHES), OPT_BIT_F('h', "heads", &flags,
index d2a807a828..a8f352f7cd 100644--- a/builtin/read-tree.c+++ b/builtin/read-tree.c@@ -135,9 +135,14 @@ int cmd_read_tree(int argc, N_("3-way merge in presence of adds and removes")), OPT_BOOL(0, "reset", &opts.reset, N_("same as -m, but discard unmerged entries")),- { OPTION_STRING, 0, "prefix", &opts.prefix, N_("<subdirectory>/"),- N_("read the tree into the index under <subdirectory>/"),- PARSE_OPT_NONEG },+ {+ .type = OPTION_STRING,+ .long_name = "prefix",+ .value = &opts.prefix,+ .argh = N_("<subdirectory>/"),+ .help = N_("read the tree into the index under <subdirectory>/"),+ .flags = PARSE_OPT_NONEG,+ }, OPT_BOOL('u', NULL, &opts.update, N_("update working tree with merge result")), OPT_CALLBACK_F(0, "exclude-per-directory", &opts,
builtin/rebase.c
+19-6
index d4715ed35d..d408335009 100644--- a/builtin/rebase.c+++ b/builtin/rebase.c@@ -1122,9 +1122,15 @@ int cmd_rebase(int argc, OPT_BIT('v', "verbose", &options.flags, N_("display a diffstat of what changed upstream"), REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),- {OPTION_NEGBIT, 'n', "no-stat", &options.flags, NULL,- N_("do not show diffstat of what changed upstream"),- PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },+ {+ .type = OPTION_NEGBIT,+ .short_name = 'n',+ .long_name = "no-stat",+ .value = &options.flags,+ .help = N_("do not show diffstat of what changed upstream"),+ .flags = PARSE_OPT_NOARG,+ .defval = REBASE_DIFFSTAT,+ }, OPT_BOOL(0, "signoff", &options.signoff, N_("add a Signed-off-by trailer to each commit")), OPT_BOOL(0, "committer-date-is-author-date",@@ -1190,9 +1196,16 @@ int cmd_rebase(int argc, OPT_BOOL(0, "update-refs", &options.update_refs, N_("update branches that point to commits " "that are being rebased")),- { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),- N_("GPG-sign commits"),- PARSE_OPT_OPTARG, NULL, (intptr_t) "" },+ {+ .type = OPTION_STRING,+ .short_name = 'S',+ .long_name = "gpg-sign",+ .value = &gpg_sign,+ .argh = N_("key-id"),+ .help = N_("GPG-sign commits"),+ .flags = PARSE_OPT_OPTARG,+ .defval = (intptr_t) "",+ }, OPT_AUTOSTASH(&options.autostash), OPT_STRING_LIST('x', "exec", &options.exec, N_("exec"), N_("add exec lines after each commit of the "