fast-import: use struct option for usage string

Currently `git fast-import -h` shows the following on a single line: usage : git fast-import [--date-format=<f>] [--max-pack-size=<n>] \ [--big-file-threshold=<n>] [--depth=<n>] \ [--active-branches=<n>] \ [--export-marks=<marks.file>] This output has a number of issues like: - It's missing a lot of options. - It's not consistent with the SYNOPSIS section of the doc. - With `--help-all` instead of `-h` additional hidden options should be shown, but that's not the case. - It's not standard style anymore. - Most other Git commands show additional lines for most of the options they support. Also while most commands use the parse-options API to handle their options, "builtin/fast-import.c" still doesn't use it. Let's improve on that by using the parse-options API to display the options when `-h` and `--help-all` are used. While at it, let's make the SYNOPSIS section of "Documentation/git-fast-import.adoc" consistent with the new usage string. This deliberately leaves it to future work to also use the parse-options API to actually parse the options. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Christian Couder committed Jul 16, 2026 at 18:55 UTC 84631f0695e08a298809da0cd3db1db0c07bdb35
3 files changed +81 -8
Documentation/git-fast-import.adoc
+1 -1
@@ -9,7 +9,7 @@ git-fast-import - Backend for fast Git data importers
9 SYNOPSIS
10 --------
11 [verse]
12 -frontend | 'git fast-import' [<options>]
12 +'git fast-import' [<options>]
13
14 DESCRIPTION
15 -----------
builtin/fast-import.c
+80 -6
@@ -30,6 +30,7 @@
30 #include "khash.h"
31 #include "date.h"
32 #include "gpg-interface.h"
33 +#include "parse-options.h"
34
35 #define PACK_ID_BITS 16
36 #define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
@@ -277,16 +278,18 @@ struct fast_import_state {
278 const char *prefix;
279 int seen_data_command;
280 int allow_unsafe_features;
281 + struct option *option;
282 };
283
284 static void fast_import_state_init(struct fast_import_state *state,
285 int argc, const char **argv,
284 - const char *prefix)
286 + const char *prefix, struct option *option)
287 {
288 memset(state, 0, sizeof(*state));
289 state->argc = argc;
290 state->argv = argv;
291 state->prefix = prefix;
292 + state->option = option;
293 }
294
295 static void parse_argv(struct fast_import_state *state);
@@ -3907,8 +3910,10 @@ static void git_pack_config(void)
3910 repo_config(the_repository, git_default_config, NULL);
3911 }
3912
3910 -static const char fast_import_usage[] =
3911 -"git fast-import [--date-format=<f>] [--max-pack-size=<n>] [--big-file-threshold=<n>] [--depth=<n>] [--active-branches=<n>] [--export-marks=<marks.file>]";
3913 +static const char *const fast_import_usage[] = {
3914 + N_("git fast-import [<options>]"),
3915 + NULL
3916 +};
3917
3918 static void parse_argv(struct fast_import_state *state)
3919 {
@@ -3937,7 +3942,7 @@ static void parse_argv(struct fast_import_state *state)
3942 die(_("unknown option --%s"), a);
3943 }
3944 if (i != state->argc)
3940 - usage(fast_import_usage);
3945 + usage_with_options(fast_import_usage, state->option);
3946
3947 state->seen_data_command = 1;
3948 if (import_marks_file)
@@ -3952,9 +3957,78 @@ int cmd_fast_import(int argc,
3957 {
3958 struct fast_import_state state;
3959
3955 - show_usage_if_asked(argc, argv, fast_import_usage);
3960 + unsigned long pack_size_limit, big_file_threshold, depth, active_branches;
3961 + char *edges, *signed_commits, *signed_tags, *date_format, *import_marks;
3962 + char *import_marks_if_exists, *export_marks, *submodules_from, *submodules_to;
3963 + int opt_quiet, opt_show_stats, opt_relative_marks, opt_force, opt_done;
3964 + int opt_allow_unsafe;
3965 + int cat_blob;
3966
3957 - fast_import_state_init(&state, argc, argv, prefix);
3967 + /*
3968 + * NEEDSWORK: For now this is used only to render
3969 + * `-h`/`--help-all` usage messages. The actual parsing is
3970 + * done by parse_one_option()/parse_one_feature().
3971 + */
3972 + struct option fast_import_options[] = {
3973 + OPT_GROUP(N_("Common")),
3974 + OPT_STRING_F(0, "date-format", &date_format, N_("fmt"),
3975 + N_("format of the commit/tag dates"), PARSE_OPT_NONEG),
3976 + OPT_BOOL_F(0, "stats", &opt_show_stats,
3977 + N_("display some basic statistics (objects, packfiles and memory)"),
3978 + PARSE_OPT_NONEG),
3979 + OPT_BOOL_F(0, "quiet", &opt_quiet,
3980 + N_("disable the output shown by --stats"), PARSE_OPT_NONEG),
3981 + OPT_BOOL_F(0, "force", &opt_force,
3982 + N_("force updating modified existing branches"), PARSE_OPT_NONEG),
3983 + OPT_BOOL_F(0, "done", &opt_done,
3984 + N_("require a terminating 'done' command"), PARSE_OPT_NONEG),
3985 + OPT_UNSIGNED(0, "max-pack-size", &pack_size_limit,
3986 + N_("maximum size of each output pack file")),
3987 + OPT_UNSIGNED(0, "big-file-threshold", &big_file_threshold,
3988 + N_("maximum size of a blob that will be deltified")),
3989 + OPT_UNSIGNED(0, "depth", &depth,
3990 + N_("maximum delta depth")),
3991 + OPT_UNSIGNED(0, "active-branches", &active_branches,
3992 + N_("maximum number of branches to maintain active")),
3993 + OPT_GROUP(N_("Marks")),
3994 + OPT_STRING_F(0, "import-marks", &import_marks, N_("file"),
3995 + N_("import marks from <file>"), PARSE_OPT_NONEG),
3996 + OPT_STRING_F(0, "import-marks-if-exists", &import_marks_if_exists, N_("file"),
3997 + N_("import marks from <file> if it exists"), PARSE_OPT_NONEG),
3998 + OPT_STRING_F(0, "export-marks", &export_marks, N_("file"),
3999 + N_("dump marks to <file>"), PARSE_OPT_NONEG),
4000 + OPT_BOOL(0, "relative-marks", &opt_relative_marks,
4001 + N_("are --(import|export)-marks= paths relative to '.git/info/fast-import'?")),
4002 + OPT_GROUP(N_("Submodule rewrite")),
4003 + OPT_STRING_F(0, "rewrite-submodules-from", &submodules_from, N_("name:filename"),
4004 + N_("rewrite object IDs for submodule <name> from <filename>"),
4005 + PARSE_OPT_NONEG),
4006 + OPT_STRING_F(0, "rewrite-submodules-to", &submodules_to, N_("name:filename"),
4007 + N_("rewrite object IDs for submodule <name> to <filename>"),
4008 + PARSE_OPT_NONEG),
4009 + OPT_GROUP(N_("Signing")),
4010 + OPT_STRING_F(0, "signed-commits", &signed_commits, N_("mode"),
4011 + N_("how to handle signed commits"),
4012 + PARSE_OPT_NONEG),
4013 + OPT_STRING_F(0, "signed-tags", &signed_tags, N_("mode"),
4014 + N_("how to handle signed tags"),
4015 + PARSE_OPT_NONEG),
4016 + OPT_HIDDEN_GROUP(N_("Advanced")),
4017 + OPT_BOOL_F(0, "allow-unsafe-features", &opt_allow_unsafe,
4018 + N_("allow unsafe mark commands from the stream"),
4019 + PARSE_OPT_HIDDEN | PARSE_OPT_NONEG),
4020 + OPT_STRING_F(0, "export-pack-edges", &edges, N_("file"),
4021 + N_("dump edge commits to <file>"),
4022 + PARSE_OPT_HIDDEN | PARSE_OPT_NONEG),
4023 + OPT_INTEGER_F(0, "cat-blob-fd", &cat_blob,
4024 + N_("write some responses to <fd> instead of stdout"),
4025 + PARSE_OPT_HIDDEN | PARSE_OPT_NONEG),
4026 + OPT_END()
4027 + };
4028 +
4029 + show_usage_with_options_if_asked(argc, argv, fast_import_usage, fast_import_options);
4030 +
4031 + fast_import_state_init(&state, argc, argv, prefix, fast_import_options);
4032
4033 reset_pack_idx_option(&pack_idx_opts);
4034 git_pack_config();
t/t0450/adoc-help-mismatches
-1
@@ -13,7 +13,6 @@ credential
13 credential-cache
14 credential-store
15 fast-export
16 -fast-import
16 fetch-pack
17 fmt-merge-msg
18 format-patch