fast-import: introduce 'struct fast_import_state'

"builtin/fast-import.c" uses a large number of global variables. This makes it harder than necessary to reason about and improve. Especially adding new features requires adding more global variables, while modernizing and eventually libifying the code becomes more and more difficult. To start reverting the sad trend to more and more globals and to start cleaning things up, let's introduce a 'struct fast_import_state' and pass an instance of it as the first argument to many functions. This is similar to what was done for "builtin/apply.c" by introducing a 'struct apply_state', see 07d7e290ff (apply: move 'struct apply_state' to a header file, 2016-08-11) and related commits. As a first step only the 'global_argc', 'global_argv' and 'global_prefix' variables are moved into the new struct. More variables will be moved into it in the following commits. Some functions receive the new 'state' parameter only to pass it along or for future use, so they are marked with UNUSED for now to satisfy '-Werror=unused-parameter'. This is a mostly mechanical refactoring with no intended behavior change. 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 36bd8a1e0d2cf6d7a6e35c4b1d895967500aee59
1 file changed +138 -124
builtin/fast-import.c
+138 -124
@@ -184,10 +184,6 @@ static int failure;
184 static FILE *pack_edges;
185 static unsigned int show_stats = 1;
186 static unsigned int quiet;
187 -static int global_argc;
188 -static const char **global_argv;
189 -static const char *global_prefix;
190 -
187 static enum sign_mode signed_tag_mode = SIGN_VERBATIM;
188 static enum sign_mode signed_commit_mode = SIGN_VERBATIM;
189 static const char *signed_commit_keyid;
@@ -276,10 +272,27 @@ static kh_oid_map_t *sub_oid_map;
272 /* Where to write output of cat-blob commands */
273 static int cat_blob_fd = STDOUT_FILENO;
274
279 -static void parse_argv(void);
280 -static void parse_get_mark(const char *p);
281 -static void parse_cat_blob(const char *p);
282 -static void parse_ls(const char *p, struct branch *b);
275 +/* Command state */
276 +struct fast_import_state {
277 + int argc;
278 + const char **argv;
279 + const char *prefix;
280 +};
281 +
282 +static void fast_import_state_init(struct fast_import_state *state,
283 + int argc, const char **argv,
284 + const char *prefix)
285 +{
286 + memset(state, 0, sizeof(*state));
287 + state->argc = argc;
288 + state->argv = argv;
289 + state->prefix = prefix;
290 +}
291 +
292 +static void parse_argv(struct fast_import_state *state);
293 +static void parse_get_mark(struct fast_import_state *state, const char *p);
294 +static void parse_cat_blob(struct fast_import_state *state, const char *p);
295 +static void parse_ls(struct fast_import_state *state, const char *p, struct branch *b);
296
297 static void for_each_mark(struct mark_set *m, uintmax_t base, each_mark_fn_t callback, void *p)
298 {
@@ -1844,7 +1857,7 @@ done:
1857 }
1858
1859
1847 -static int read_next_command(void)
1860 +static int read_next_command(struct fast_import_state *state)
1861 {
1862 static int stdin_eof = 0;
1863
@@ -1866,7 +1879,7 @@ static int read_next_command(void)
1879 if (!seen_data_command
1880 && !starts_with(command_buf.buf, "feature ")
1881 && !starts_with(command_buf.buf, "option ")) {
1869 - parse_argv();
1882 + parse_argv(state);
1883 }
1884
1885 rc = rc_free;
@@ -1898,22 +1911,22 @@ static void skip_optional_lf(void)
1911 ungetc(term_char, stdin);
1912 }
1913
1901 -static void parse_mark(void)
1914 +static void parse_mark(struct fast_import_state *state)
1915 {
1916 const char *v;
1917 if (skip_prefix(command_buf.buf, "mark :", &v)) {
1918 next_mark = strtoumax(v, NULL, 10);
1906 - read_next_command();
1919 + read_next_command(state);
1920 }
1921 else
1922 next_mark = 0;
1923 }
1924
1912 -static void parse_original_identifier(void)
1925 +static void parse_original_identifier(struct fast_import_state *state)
1926 {
1927 const char *v;
1928 if (skip_prefix(command_buf.buf, "original-oid ", &v))
1916 - read_next_command();
1929 + read_next_command(state);
1930 }
1931
1932 static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
@@ -2067,11 +2080,11 @@ static void parse_and_store_blob(
2080 }
2081 }
2082
2070 -static void parse_new_blob(void)
2083 +static void parse_new_blob(struct fast_import_state *state)
2084 {
2072 - read_next_command();
2073 - parse_mark();
2074 - parse_original_identifier();
2085 + read_next_command(state);
2086 + parse_mark(state);
2087 + parse_original_identifier(state);
2088 parse_and_store_blob(&last_blob, NULL, next_mark);
2089 }
2090
@@ -2367,7 +2380,7 @@ static void parse_path_space(struct strbuf *sb, const char *p,
2380 (*endp)++;
2381 }
2382
2370 -static void file_change_m(const char *p, struct branch *b)
2383 +static void file_change_m(struct fast_import_state *state, const char *p, struct branch *b)
2384 {
2385 static struct strbuf path = STRBUF_INIT;
2386 struct object_entry *oe;
@@ -2434,10 +2447,10 @@ static void file_change_m(const char *p, struct branch *b)
2447 if (S_ISDIR(mode))
2448 die(_("directories cannot be specified 'inline': %s"),
2449 command_buf.buf);
2437 - while (read_next_command() != EOF) {
2450 + while (read_next_command(state) != EOF) {
2451 const char *v;
2452 if (skip_prefix(command_buf.buf, "cat-blob ", &v))
2440 - parse_cat_blob(v);
2453 + parse_cat_blob(state, v);
2454 else {
2455 parse_and_store_blob(&last_blob, &oid, 0);
2456 break;
@@ -2511,7 +2524,7 @@ static void file_change_cr(const char *p, struct branch *b, int rename)
2524 leaf.tree);
2525 }
2526
2514 -static void note_change_n(const char *p, struct branch *b, unsigned char *old_fanout)
2527 +static void note_change_n(struct fast_import_state *state, const char *p, struct branch *b, unsigned char *old_fanout)
2528 {
2529 struct object_entry *oe;
2530 struct branch *s;
@@ -2576,7 +2589,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
2589 die(_("invalid ref name or SHA1 expression: %s"), p);
2590
2591 if (inline_data) {
2579 - read_next_command();
2592 + read_next_command(state);
2593 parse_and_store_blob(&last_blob, &oid, 0);
2594 } else if (oe) {
2595 if (oe->type != OBJ_BLOB)
@@ -2643,7 +2656,7 @@ static void parse_from_existing(struct branch *b)
2656 }
2657 }
2658
2646 -static int parse_objectish(struct branch *b, const char *objectish)
2659 +static int parse_objectish(struct fast_import_state *state, struct branch *b, const char *objectish)
2660 {
2661 struct branch *s;
2662 struct object_id oid;
@@ -2686,31 +2699,31 @@ static int parse_objectish(struct branch *b, const char *objectish)
2699 b->branch_tree.tree = NULL;
2700 }
2701
2689 - read_next_command();
2702 + read_next_command(state);
2703 return 1;
2704 }
2705
2693 -static int parse_from(struct branch *b)
2706 +static int parse_from(struct fast_import_state *state, struct branch *b)
2707 {
2708 const char *from;
2709
2710 if (!skip_prefix(command_buf.buf, "from ", &from))
2711 return 0;
2712
2700 - return parse_objectish(b, from);
2713 + return parse_objectish(state, b, from);
2714 }
2715
2703 -static int parse_objectish_with_prefix(struct branch *b, const char *prefix)
2716 +static int parse_objectish_with_prefix(struct fast_import_state *state, struct branch *b, const char *prefix)
2717 {
2718 const char *base;
2719
2720 if (!skip_prefix(command_buf.buf, prefix, &base))
2721 return 0;
2722
2710 - return parse_objectish(b, base);
2723 + return parse_objectish(state, b, base);
2724 }
2725
2713 -static struct hash_list *parse_merge(unsigned int *count)
2726 +static struct hash_list *parse_merge(struct fast_import_state *state, unsigned int *count)
2727 {
2728 struct hash_list *list = NULL, **tail = &list, *n;
2729 const char *from;
@@ -2744,7 +2757,7 @@ static struct hash_list *parse_merge(unsigned int *count)
2757 tail = &n->next;
2758
2759 (*count)++;
2747 - read_next_command();
2760 + read_next_command(state);
2761 }
2762 return list;
2763 }
@@ -2755,7 +2768,7 @@ struct signature_data {
2768 struct strbuf data; /* The actual signature data */
2769 };
2770
2758 -static void parse_one_signature(struct signature_data *sig, const char *v)
2771 +static void parse_one_signature(struct fast_import_state *state, struct signature_data *sig, const char *v)
2772 {
2773 char *args = xstrdup(v); /* Will be freed when sig->hash_algo is freed */
2774 char *space = strchr(args, ' ');
@@ -2780,15 +2793,15 @@ static void parse_one_signature(struct signature_data *sig, const char *v)
2793 warning(_("'unknown' signature format in gpgsig"));
2794
2795 /* Read signature data */
2783 - read_next_command();
2796 + read_next_command(state);
2797 parse_data(&sig->data, 0, NULL);
2798 }
2799
2787 -static void discard_one_signature(void)
2800 +static void discard_one_signature(struct fast_import_state *state)
2801 {
2802 struct strbuf data = STRBUF_INIT;
2803
2791 - read_next_command();
2804 + read_next_command(state);
2805 parse_data(&data, 0, NULL);
2806 strbuf_release(&data);
2807 }
@@ -2826,13 +2839,14 @@ static void store_signature(struct signature_data *stored_sig,
2839 }
2840 }
2841
2829 -static void import_one_signature(struct signature_data *sig_sha1,
2842 +static void import_one_signature(struct fast_import_state *state,
2843 + struct signature_data *sig_sha1,
2844 struct signature_data *sig_sha256,
2845 const char *v)
2846 {
2847 struct signature_data sig = { NULL, NULL, STRBUF_INIT };
2848
2835 - parse_one_signature(&sig, v);
2849 + parse_one_signature(state, &sig, v);
2850
2851 if (!strcmp(sig.hash_algo, "sha1"))
2852 store_signature(sig_sha1, &sig, "SHA-1");
@@ -2946,7 +2960,7 @@ static void handle_signature_if_invalid(struct strbuf *new_data,
2960 strbuf_release(&tmp_buf);
2961 }
2962
2949 -static void parse_new_commit(const char *arg)
2963 +static void parse_new_commit(struct fast_import_state *state, const char *arg)
2964 {
2965 static struct strbuf msg = STRBUF_INIT;
2966 struct signature_data sig_sha1 = { NULL, NULL, STRBUF_INIT };
@@ -2964,16 +2978,16 @@ static void parse_new_commit(const char *arg)
2978 if (!b)
2979 b = new_branch(arg);
2980
2967 - read_next_command();
2968 - parse_mark();
2969 - parse_original_identifier();
2981 + read_next_command(state);
2982 + parse_mark(state);
2983 + parse_original_identifier(state);
2984 if (skip_prefix(command_buf.buf, "author ", &v)) {
2985 author = parse_ident(v);
2972 - read_next_command();
2986 + read_next_command(state);
2987 }
2988 if (skip_prefix(command_buf.buf, "committer ", &v)) {
2989 committer = parse_ident(v);
2976 - read_next_command();
2990 + read_next_command(state);
2991 }
2992 if (!committer)
2993 die(_("expected committer but didn't get one"));
@@ -2989,7 +3003,7 @@ static void parse_new_commit(const char *arg)
3003 warning(_("stripping a commit signature"));
3004 /* fallthru */
3005 case SIGN_STRIP:
2992 - discard_one_signature();
3006 + discard_one_signature(state);
3007 break;
3008
3009 /* Second, modes that parse the signature */
@@ -3000,24 +3014,24 @@ static void parse_new_commit(const char *arg)
3014 case SIGN_STRIP_IF_INVALID:
3015 case SIGN_SIGN_IF_INVALID:
3016 case SIGN_ABORT_IF_INVALID:
3003 - import_one_signature(&sig_sha1, &sig_sha256, v);
3017 + import_one_signature(state, &sig_sha1, &sig_sha256, v);
3018 break;
3019
3020 /* Third, BUG */
3021 default:
3022 BUG("invalid signed_commit_mode value %d", signed_commit_mode);
3023 }
3010 - read_next_command();
3024 + read_next_command(state);
3025 }
3026
3027 if (skip_prefix(command_buf.buf, "encoding ", &v)) {
3028 encoding = xstrdup(v);
3015 - read_next_command();
3029 + read_next_command(state);
3030 }
3031 parse_data(&msg, 0, NULL);
3018 - read_next_command();
3019 - parse_from(b);
3020 - merge_list = parse_merge(&merge_count);
3032 + read_next_command(state);
3033 + parse_from(state, b);
3034 + merge_list = parse_merge(state, &merge_count);
3035
3036 /* ensure the branch is active/loaded */
3037 if (!b->branch_tree.tree || !max_active_branches) {
@@ -3030,7 +3044,7 @@ static void parse_new_commit(const char *arg)
3044 /* file_change* */
3045 while (command_buf.len > 0) {
3046 if (skip_prefix(command_buf.buf, "M ", &v))
3033 - file_change_m(v, b);
3047 + file_change_m(state, v, b);
3048 else if (skip_prefix(command_buf.buf, "D ", &v))
3049 file_change_d(v, b);
3050 else if (skip_prefix(command_buf.buf, "R ", &v))
@@ -3038,18 +3052,18 @@ static void parse_new_commit(const char *arg)
3052 else if (skip_prefix(command_buf.buf, "C ", &v))
3053 file_change_cr(v, b, 0);
3054 else if (skip_prefix(command_buf.buf, "N ", &v))
3041 - note_change_n(v, b, &prev_fanout);
3055 + note_change_n(state, v, b, &prev_fanout);
3056 else if (!strcmp("deleteall", command_buf.buf))
3057 file_change_deleteall(b);
3058 else if (skip_prefix(command_buf.buf, "ls ", &v))
3045 - parse_ls(v, b);
3059 + parse_ls(state, v, b);
3060 else if (skip_prefix(command_buf.buf, "cat-blob ", &v))
3047 - parse_cat_blob(v);
3061 + parse_cat_blob(state, v);
3062 else {
3063 unread_command_buf = 1;
3064 break;
3065 }
3052 - if (read_next_command() == EOF)
3066 + if (read_next_command(state) == EOF)
3067 break;
3068 }
3069
@@ -3187,7 +3201,7 @@ static void handle_tag_signature(struct strbuf *buf, struct strbuf *msg, const c
3201 }
3202 }
3203
3190 -static void parse_new_tag(const char *arg)
3204 +static void parse_new_tag(struct fast_import_state *state, const char *arg)
3205 {
3206 static struct strbuf msg = STRBUF_INIT;
3207 const char *from;
@@ -3206,8 +3220,8 @@ static void parse_new_tag(const char *arg)
3220 else
3221 first_tag = t;
3222 last_tag = t;
3209 - read_next_command();
3210 - parse_mark();
3223 + read_next_command(state);
3224 + parse_mark(state);
3225
3226 /* from ... */
3227 if (!skip_prefix(command_buf.buf, "from ", &from))
@@ -3235,15 +3249,15 @@ static void parse_new_tag(const char *arg)
3249 type = oe->type;
3250 } else
3251 die(_("invalid ref name or SHA1 expression: %s"), from);
3238 - read_next_command();
3252 + read_next_command(state);
3253
3254 /* original-oid ... */
3241 - parse_original_identifier();
3255 + parse_original_identifier(state);
3256
3257 /* tagger ... */
3258 if (skip_prefix(command_buf.buf, "tagger ", &v)) {
3259 tagger = parse_ident(v);
3246 - read_next_command();
3260 + read_next_command(state);
3261 } else
3262 tagger = NULL;
3263
@@ -3274,7 +3288,7 @@ static void parse_new_tag(const char *arg)
3288 t->pack_id = pack_id;
3289 }
3290
3277 -static void parse_reset_branch(const char *arg)
3291 +static void parse_reset_branch(struct fast_import_state *state, const char *arg)
3292 {
3293 struct branch *b;
3294 const char *tag_name;
@@ -3291,8 +3305,8 @@ static void parse_reset_branch(const char *arg)
3305 }
3306 else
3307 b = new_branch(arg);
3294 - read_next_command();
3295 - parse_from(b);
3308 + read_next_command(state);
3309 + parse_from(state, b);
3310 if (b->delete && skip_prefix(b->name, "refs/tags/", &tag_name)) {
3311 /*
3312 * Elsewhere, we call dump_branches() before dump_tags(),
@@ -3377,7 +3391,7 @@ static void cat_blob(struct object_entry *oe, struct object_id *oid)
3391 free(buf);
3392 }
3393
3380 -static void parse_get_mark(const char *p)
3394 +static void parse_get_mark(struct fast_import_state *state UNUSED, const char *p)
3395 {
3396 struct object_entry *oe;
3397 char output[GIT_MAX_HEXSZ + 2];
@@ -3394,7 +3408,7 @@ static void parse_get_mark(const char *p)
3408 cat_blob_write(output, the_hash_algo->hexsz + 1);
3409 }
3410
3397 -static void parse_cat_blob(const char *p)
3411 +static void parse_cat_blob(struct fast_import_state *state UNUSED, const char *p)
3412 {
3413 struct object_entry *oe;
3414 struct object_id oid;
@@ -3559,7 +3573,7 @@ static void print_ls(int mode, const unsigned char *hash, const char *path)
3573 cat_blob_write(line.buf, line.len);
3574 }
3575
3562 -static void parse_ls(const char *p, struct branch *b)
3576 +static void parse_ls(struct fast_import_state *state UNUSED, const char *p, struct branch *b)
3577 {
3578 static struct strbuf path = STRBUF_INIT;
3579 struct tree_entry *root = NULL;
@@ -3606,13 +3620,13 @@ static void checkpoint(void)
3620 dump_marks();
3621 }
3622
3609 -static void parse_checkpoint(void)
3623 +static void parse_checkpoint(struct fast_import_state *state UNUSED)
3624 {
3625 checkpoint_requested = 1;
3626 skip_optional_lf();
3627 }
3628
3615 -static void parse_progress(void)
3629 +static void parse_progress(struct fast_import_state *state UNUSED)
3630 {
3631 fwrite(command_buf.buf, 1, command_buf.len, stdout);
3632 fputc('\n', stdout);
@@ -3620,36 +3634,36 @@ static void parse_progress(void)
3634 skip_optional_lf();
3635 }
3636
3623 -static void parse_alias(void)
3637 +static void parse_alias(struct fast_import_state *state)
3638 {
3639 struct object_entry *e;
3640 struct branch b;
3641
3642 skip_optional_lf();
3629 - read_next_command();
3643 + read_next_command(state);
3644
3645 /* mark ... */
3632 - parse_mark();
3646 + parse_mark(state);
3647 if (!next_mark)
3648 die(_("expected 'mark' command, got %s"), command_buf.buf);
3649
3650 /* to ... */
3651 memset(&b, 0, sizeof(b));
3638 - if (!parse_objectish_with_prefix(&b, "to "))
3652 + if (!parse_objectish_with_prefix(state, &b, "to "))
3653 die(_("expected 'to' command, got %s"), command_buf.buf);
3654 e = find_object(&b.oid);
3655 assert(e);
3656 insert_mark(&marks, next_mark, e);
3657 }
3658
3645 -static char* make_fast_import_path(const char *path)
3659 +static char* make_fast_import_path(struct fast_import_state *state, const char *path)
3660 {
3661 if (!relative_marks_paths || is_absolute_path(path))
3648 - return prefix_filename(global_prefix, path);
3662 + return prefix_filename(state->prefix, path);
3663 return repo_git_path(the_repository, "info/fast-import/%s", path);
3664 }
3665
3652 -static void option_import_marks(const char *marks,
3666 +static void option_import_marks(struct fast_import_state *state, const char *marks,
3667 int from_stream, int ignore_missing)
3668 {
3669 if (import_marks_file) {
@@ -3662,7 +3676,7 @@ static void option_import_marks(const char *marks,
3676 }
3677
3678 free(import_marks_file);
3665 - import_marks_file = make_fast_import_path(marks);
3679 + import_marks_file = make_fast_import_path(state, marks);
3680 import_marks_file_from_stream = from_stream;
3681 import_marks_file_ignore_missing = ignore_missing;
3682 }
@@ -3702,13 +3716,13 @@ static void option_active_branches(const char *branches)
3716 max_active_branches = ulong_arg("--active-branches", branches);
3717 }
3718
3705 -static void option_export_marks(const char *marks)
3719 +static void option_export_marks(struct fast_import_state *state, const char *marks)
3720 {
3721 free(export_marks_file);
3708 - export_marks_file = make_fast_import_path(marks);
3722 + export_marks_file = make_fast_import_path(state, marks);
3723 }
3724
3711 -static void option_cat_blob_fd(const char *fd)
3725 +static void option_cat_blob_fd(struct fast_import_state *state UNUSED, const char *fd)
3726 {
3727 unsigned long n = ulong_arg("--cat-blob-fd", fd);
3728 if (n > (unsigned long) INT_MAX)
@@ -3716,16 +3730,16 @@ static void option_cat_blob_fd(const char *fd)
3730 cat_blob_fd = (int) n;
3731 }
3732
3719 -static void option_export_pack_edges(const char *edges)
3733 +static void option_export_pack_edges(struct fast_import_state *state, const char *edges)
3734 {
3721 - char *fn = prefix_filename(global_prefix, edges);
3735 + char *fn = prefix_filename(state->prefix, edges);
3736 if (pack_edges)
3737 fclose(pack_edges);
3738 pack_edges = xfopen(fn, "a");
3739 free(fn);
3740 }
3741
3728 -static void option_rewrite_submodules(const char *arg, struct string_list *list)
3742 +static void option_rewrite_submodules(struct fast_import_state *state, const char *arg, struct string_list *list)
3743 {
3744 struct mark_set *ms;
3745 FILE *fp;
@@ -3737,7 +3751,7 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list)
3751 f++;
3752 CALLOC_ARRAY(ms, 1);
3753
3740 - f = prefix_filename(global_prefix, f);
3754 + f = prefix_filename(state->prefix, f);
3755 fp = fopen(f, "r");
3756 if (!fp)
3757 die_errno(_("cannot read '%s'"), f);
@@ -3750,7 +3764,7 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list)
3764 free(s);
3765 }
3766
3753 -static int parse_one_option(const char *option)
3767 +static int parse_one_option(struct fast_import_state *state, const char *option)
3768 {
3769 if (skip_prefix(option, "max-pack-size=", &option)) {
3770 unsigned long v;
@@ -3774,7 +3788,7 @@ static int parse_one_option(const char *option)
3788 } else if (skip_prefix(option, "active-branches=", &option)) {
3789 option_active_branches(option);
3790 } else if (skip_prefix(option, "export-pack-edges=", &option)) {
3777 - option_export_pack_edges(option);
3791 + option_export_pack_edges(state, option);
3792 } else if (skip_prefix(option, "signed-commits=", &option)) {
3793 if (parse_sign_mode(option, &signed_commit_mode, &signed_commit_keyid))
3794 usagef(_("unknown --signed-commits mode '%s'"), option);
@@ -3795,34 +3809,34 @@ static int parse_one_option(const char *option)
3809 return 1;
3810 }
3811
3798 -static void check_unsafe_feature(const char *feature, int from_stream)
3812 +static void check_unsafe_feature(struct fast_import_state *state UNUSED, const char *feature, int from_stream)
3813 {
3814 if (from_stream && !allow_unsafe_features)
3815 die(_("feature '%s' forbidden in input without --allow-unsafe-features"),
3816 feature);
3817 }
3818
3805 -static int parse_one_feature(const char *feature, int from_stream)
3819 +static int parse_one_feature(struct fast_import_state *state, const char *feature, int from_stream)
3820 {
3821 const char *arg;
3822
3823 if (skip_prefix(feature, "date-format=", &arg)) {
3824 option_date_format(arg);
3825 } else if (skip_prefix(feature, "import-marks=", &arg)) {
3812 - check_unsafe_feature("import-marks", from_stream);
3813 - option_import_marks(arg, from_stream, 0);
3826 + check_unsafe_feature(state, "import-marks", from_stream);
3827 + option_import_marks(state, arg, from_stream, 0);
3828 } else if (skip_prefix(feature, "import-marks-if-exists=", &arg)) {
3815 - check_unsafe_feature("import-marks-if-exists", from_stream);
3816 - option_import_marks(arg, from_stream, 1);
3829 + check_unsafe_feature(state, "import-marks-if-exists", from_stream);
3830 + option_import_marks(state, arg, from_stream, 1);
3831 } else if (skip_prefix(feature, "export-marks=", &arg)) {
3818 - check_unsafe_feature(feature, from_stream);
3819 - option_export_marks(arg);
3832 + check_unsafe_feature(state, feature, from_stream);
3833 + option_export_marks(state, arg);
3834 } else if (!strcmp(feature, "alias")) {
3835 ; /* Don't die - this feature is supported */
3836 } else if (skip_prefix(feature, "rewrite-submodules-to=", &arg)) {
3823 - option_rewrite_submodules(arg, &sub_marks_to);
3837 + option_rewrite_submodules(state, arg, &sub_marks_to);
3838 } else if (skip_prefix(feature, "rewrite-submodules-from=", &arg)) {
3825 - option_rewrite_submodules(arg, &sub_marks_from);
3839 + option_rewrite_submodules(state, arg, &sub_marks_from);
3840 } else if (!strcmp(feature, "get-mark")) {
3841 ; /* Don't die - this feature is supported */
3842 } else if (!strcmp(feature, "cat-blob")) {
@@ -3844,23 +3858,23 @@ static int parse_one_feature(const char *feature, int from_stream)
3858 return 1;
3859 }
3860
3847 -static void parse_feature(const char *feature)
3861 +static void parse_feature(struct fast_import_state *state, const char *feature)
3862 {
3863 if (seen_data_command)
3864 die(_("got feature command '%s' after data command"), feature);
3865
3852 - if (parse_one_feature(feature, 1))
3866 + if (parse_one_feature(state, feature, 1))
3867 return;
3868
3869 die(_("this version of fast-import does not support feature %s."), feature);
3870 }
3871
3858 -static void parse_option(const char *option)
3872 +static void parse_option(struct fast_import_state *state, const char *option)
3873 {
3874 if (seen_data_command)
3875 die(_("got option command '%s' after data command"), option);
3876
3863 - if (parse_one_option(option))
3877 + if (parse_one_option(state, option))
3878 return;
3879
3880 die(_("this version of fast-import does not support option: %s"), option);
@@ -3896,12 +3910,12 @@ static void git_pack_config(void)
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>]";
3912
3899 -static void parse_argv(void)
3913 +static void parse_argv(struct fast_import_state *state)
3914 {
3915 unsigned int i;
3916
3903 - for (i = 1; i < global_argc; i++) {
3904 - const char *a = global_argv[i];
3917 + for (i = 1; i < state->argc; i++) {
3918 + const char *a = state->argv[i];
3919
3920 if (*a != '-' || !strcmp(a, "--"))
3921 break;
@@ -3909,20 +3923,20 @@ static void parse_argv(void)
3923 if (!skip_prefix(a, "--", &a))
3924 die(_("unknown option %s"), a);
3925
3912 - if (parse_one_option(a))
3926 + if (parse_one_option(state, a))
3927 continue;
3928
3915 - if (parse_one_feature(a, 0))
3929 + if (parse_one_feature(state, a, 0))
3930 continue;
3931
3932 if (skip_prefix(a, "cat-blob-fd=", &a)) {
3919 - option_cat_blob_fd(a);
3933 + option_cat_blob_fd(state, a);
3934 continue;
3935 }
3936
3937 die(_("unknown option --%s"), a);
3938 }
3925 - if (i != global_argc)
3939 + if (i != state->argc)
3940 usage(fast_import_usage);
3941
3942 seen_data_command = 1;
@@ -3936,6 +3950,8 @@ int cmd_fast_import(int argc,
3950 const char *prefix,
3951 struct repository *repo)
3952 {
3953 + struct fast_import_state state;
3954 +
3955 show_usage_if_asked(argc, argv, fast_import_usage);
3956
3957 reset_pack_idx_option(&pack_idx_opts);
@@ -3964,9 +3980,7 @@ int cmd_fast_import(int argc,
3980 allow_unsafe_features = 1;
3981 }
3982
3967 - global_argc = argc;
3968 - global_argv = argv;
3969 - global_prefix = prefix;
3983 + fast_import_state_init(&state, argc, argv, prefix);
3984
3985 rc_free = mem_pool_alloc(&fi_mem_pool, cmd_save * sizeof(*rc_free));
3986 for (unsigned int i = 0; i < (cmd_save - 1); i++)
@@ -3976,34 +3990,34 @@ int cmd_fast_import(int argc,
3990 start_packfile();
3991 set_die_routine(die_nicely);
3992 set_checkpoint_signal();
3979 - while (read_next_command() != EOF) {
3993 + while (read_next_command(&state) != EOF) {
3994 const char *v;
3995 if (!strcmp("blob", command_buf.buf))
3982 - parse_new_blob();
3996 + parse_new_blob(&state);
3997 else if (skip_prefix(command_buf.buf, "commit ", &v))
3984 - parse_new_commit(v);
3998 + parse_new_commit(&state, v);
3999 else if (skip_prefix(command_buf.buf, "tag ", &v))
3986 - parse_new_tag(v);
4000 + parse_new_tag(&state, v);
4001 else if (skip_prefix(command_buf.buf, "reset ", &v))
3988 - parse_reset_branch(v);
4002 + parse_reset_branch(&state, v);
4003 else if (skip_prefix(command_buf.buf, "ls ", &v))
3990 - parse_ls(v, NULL);
4004 + parse_ls(&state, v, NULL);
4005 else if (skip_prefix(command_buf.buf, "cat-blob ", &v))
3992 - parse_cat_blob(v);
4006 + parse_cat_blob(&state, v);
4007 else if (skip_prefix(command_buf.buf, "get-mark ", &v))
3994 - parse_get_mark(v);
4008 + parse_get_mark(&state, v);
4009 else if (!strcmp("checkpoint", command_buf.buf))
3996 - parse_checkpoint();
4010 + parse_checkpoint(&state);
4011 else if (!strcmp("done", command_buf.buf))
4012 break;
4013 else if (!strcmp("alias", command_buf.buf))
4000 - parse_alias();
4014 + parse_alias(&state);
4015 else if (starts_with(command_buf.buf, "progress "))
4002 - parse_progress();
4016 + parse_progress(&state);
4017 else if (skip_prefix(command_buf.buf, "feature ", &v))
4004 - parse_feature(v);
4018 + parse_feature(&state, v);
4019 else if (skip_prefix(command_buf.buf, "option git ", &v))
4006 - parse_option(v);
4020 + parse_option(&state, v);
4021 else if (starts_with(command_buf.buf, "option "))
4022 /* ignore non-git options*/;
4023 else
@@ -4015,7 +4029,7 @@ int cmd_fast_import(int argc,
4029
4030 /* argv hasn't been parsed yet, do so */
4031 if (!seen_data_command)
4018 - parse_argv();
4032 + parse_argv(&state);
4033
4034 if (require_explicit_termination && feof(stdin))
4035 die(_("stream ends early"));