read-tree: add "--super-prefix" option, eliminate global

The "--super-prefix" option to "git" was initially added in [1] for use with "ls-files"[2], and shortly thereafter "submodule--helper"[3] and "grep"[4]. It wasn't until [5] that "read-tree" made use of it. At the time [5] made sense, but since then we've made "ls-files" recurse in-process in [6], "grep" in [7], and finally "submodule--helper" in the preceding commits. Let's also remove it from "read-tree", which allows us to remove the option to "git" itself. We can do this because the only remaining user of it is the submodule API, which will now invoke "read-tree" with its new "--super-prefix" option. It will only do so when the "submodule_move_head()" function is called. That "submodule_move_head()" function was then only invoked by "read-tree" itself, but now rather than setting an environment variable to pass "--super-prefix" between cmd_read_tree() we: - Set a new "super_prefix" in "struct unpack_trees_options". The "super_prefixed()" function in "unpack-trees.c" added in [5] will now use this, rather than get_super_prefix() looking up the environment variable we set earlier in the same process. - Add the same field to the "struct checkout", which is only needed to ferry the "super_prefix" in the "struct unpack_trees_options" all the way down to the "entry.c" callers of "submodule_move_head()". Those calls which used the super prefix all originated in "cmd_read_tree()". The only other caller is the "unlink_entry()" caller in "builtin/checkout.c", which now passes a "NULL". 1. 74866d75793 (git: make super-prefix option, 2016-10-07) 2. e77aa336f11 (ls-files: optionally recurse into submodules, 2016-10-07) 3. 89c86265576 (submodule helper: support super prefix, 2016-12-08) 4. 0281e487fd9 (grep: optionally recurse into submodules, 2016-12-16) 5. 3d415425c7b (unpack-trees: support super-prefix option, 2017-01-17) 6. 188dce131fa (ls-files: use repository object, 2017-06-22) 7. f9ee2fcdfa0 (grep: recurse in-process using 'struct repository', 2017-08-02) Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Dec 20, 2022 at 13:39 UTC 4002ec3dcf0f89db46fbdf56549218c573a9c0f2
15 files changed +48 -100
Documentation/git.txt
+1 -7
@@ -13,8 +13,7 @@ SYNOPSIS
13 [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
14 [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
15 [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
16 - [--super-prefix=<path>] [--config-env=<name>=<envvar>]
17 - <command> [<args>]
16 + [--config-env=<name>=<envvar>] <command> [<args>]
17
18 DESCRIPTION
19 -----------
@@ -169,11 +168,6 @@ If you just want to run git as if it was started in `<path>` then use
168 details. Equivalent to setting the `GIT_NAMESPACE` environment
169 variable.
170
172 ---super-prefix=<path>::
173 - Currently for internal use only. Set a prefix which gives a path from
174 - above a repository down to its root. One use is to give submodules
175 - context about the superproject that invoked it.
176 -
171 --bare::
172 Treat the repository as a bare repository. If GIT_DIR
173 environment is not set, it is set to the current working
builtin.h
-4
@@ -51,10 +51,6 @@
51 * on bare repositories.
52 * This only makes sense when `RUN_SETUP` is also set.
53 *
54 - * `SUPPORT_SUPER_PREFIX`:
55 - *
56 - * The built-in supports `--super-prefix`.
57 - *
54 * `DELAY_PAGER_CONFIG`:
55 *
56 * If RUN_SETUP or RUN_SETUP_GENTLY is set, git.c normally handles
builtin/checkout.c
+1 -1
@@ -232,7 +232,7 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
232 pos++;
233 }
234 if (!overlay_mode) {
235 - unlink_entry(ce);
235 + unlink_entry(ce, NULL);
236 return 0;
237 }
238 if (stage == 2)
builtin/read-tree.c
+1
@@ -114,6 +114,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
114 int prefix_set = 0;
115 struct lock_file lock_file = LOCK_INIT;
116 const struct option read_tree_options[] = {
117 + OPT__SUPER_PREFIX(&opts.super_prefix),
118 OPT_CALLBACK_F(0, "index-output", NULL, N_("file"),
119 N_("write resulting index to <file>"),
120 PARSE_OPT_NONEG, index_output_cb),
cache.h
-2
@@ -480,7 +480,6 @@ static inline enum object_type object_type(unsigned int mode)
480 #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
481 #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
482 #define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
483 -#define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX"
483 #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
484 #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
485 #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
@@ -566,7 +565,6 @@ int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
565 int get_common_dir(struct strbuf *sb, const char *gitdir);
566 const char *get_git_namespace(void);
567 const char *strip_namespace(const char *namespaced_ref);
569 -const char *get_super_prefix(void);
568 const char *get_git_work_tree(void);
569
570 /*
entry.c
+6 -6
@@ -383,7 +383,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca
383 return error("cannot create submodule directory %s", path);
384 sub = submodule_from_ce(ce);
385 if (sub)
386 - return submodule_move_head(ce->name,
386 + return submodule_move_head(ce->name, state->super_prefix,
387 NULL, oid_to_hex(&ce->oid),
388 state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
389 break;
@@ -476,7 +476,7 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
476 * no pathname to return.
477 */
478 BUG("Can't remove entry to a path");
479 - unlink_entry(ce);
479 + unlink_entry(ce, state->super_prefix);
480 return 0;
481 }
482
@@ -510,10 +510,10 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
510 if (!(st.st_mode & S_IFDIR))
511 unlink_or_warn(ce->name);
512
513 - return submodule_move_head(ce->name,
513 + return submodule_move_head(ce->name, state->super_prefix,
514 NULL, oid_to_hex(&ce->oid), 0);
515 } else
516 - return submodule_move_head(ce->name,
516 + return submodule_move_head(ce->name, state->super_prefix,
517 "HEAD", oid_to_hex(&ce->oid),
518 state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
519 }
@@ -560,12 +560,12 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
560 return write_entry(ce, path.buf, ca, state, 0, nr_checkouts);
561 }
562
563 -void unlink_entry(const struct cache_entry *ce)
563 +void unlink_entry(const struct cache_entry *ce, const char *super_prefix)
564 {
565 const struct submodule *sub = submodule_from_ce(ce);
566 if (sub) {
567 /* state.force is set at the caller. */
568 - submodule_move_head(ce->name, "HEAD", NULL,
568 + submodule_move_head(ce->name, super_prefix, "HEAD", NULL,
569 SUBMODULE_MOVE_HEAD_FORCE);
570 }
571 if (check_leading_path(ce->name, ce_namelen(ce), 1) >= 0)
entry.h
+5 -1
@@ -8,6 +8,7 @@ struct checkout {
8 struct index_state *istate;
9 const char *base_dir;
10 int base_dir_len;
11 + const char *super_prefix;
12 struct delayed_checkout *delayed_checkout;
13 struct checkout_metadata meta;
14 unsigned force:1,
@@ -48,8 +49,11 @@ int finish_delayed_checkout(struct checkout *state, int show_progress);
49 /*
50 * Unlink the last component and schedule the leading directories for
51 * removal, such that empty directories get removed.
52 + *
53 + * The "super_prefix" is either NULL, or the "--super-prefix" passed
54 + * down from "read-tree" et al.
55 */
52 -void unlink_entry(const struct cache_entry *ce);
56 +void unlink_entry(const struct cache_entry *ce, const char *super_prefix);
57
58 void *read_blob_entry(const struct cache_entry *ce, size_t *size);
59 int fstat_checkout_output(int fd, const struct checkout *state, struct stat *st);
environment.c
-13
@@ -102,8 +102,6 @@ char *git_work_tree_cfg;
102
103 static char *git_namespace;
104
105 -static char *super_prefix;
106 -
105 /*
106 * Repository-local GIT_* environment variables; see cache.h for details.
107 */
@@ -121,7 +119,6 @@ const char * const local_repo_env[] = {
119 NO_REPLACE_OBJECTS_ENVIRONMENT,
120 GIT_REPLACE_REF_BASE_ENVIRONMENT,
121 GIT_PREFIX_ENVIRONMENT,
124 - GIT_SUPER_PREFIX_ENVIRONMENT,
122 GIT_SHALLOW_FILE_ENVIRONMENT,
123 GIT_COMMON_DIR_ENVIRONMENT,
124 NULL
@@ -234,16 +231,6 @@ const char *strip_namespace(const char *namespaced_ref)
231 return NULL;
232 }
233
237 -const char *get_super_prefix(void)
238 -{
239 - static int initialized;
240 - if (!initialized) {
241 - super_prefix = xstrdup_or_null(getenv(GIT_SUPER_PREFIX_ENVIRONMENT));
242 - initialized = 1;
243 - }
244 - return super_prefix;
245 -}
246 -
234 static int git_work_tree_initialized;
235
236 /*
git.c
+5 -32
@@ -14,9 +14,8 @@
14 * RUN_SETUP for reading from the configuration file.
15 */
16 #define NEED_WORK_TREE (1<<3)
17 -#define SUPPORT_SUPER_PREFIX (1<<4)
18 -#define DELAY_PAGER_CONFIG (1<<5)
19 -#define NO_PARSEOPT (1<<6) /* parse-options is not used */
17 +#define DELAY_PAGER_CONFIG (1<<4)
18 +#define NO_PARSEOPT (1<<5) /* parse-options is not used */
19
20 struct cmd_struct {
21 const char *cmd;
@@ -29,8 +28,7 @@ const char git_usage_string[] =
28 " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
29 " [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n"
30 " [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
32 - " [--super-prefix=<path>] [--config-env=<name>=<envvar>]\n"
33 - " <command> [<args>]");
31 + " [--config-env=<name>=<envvar>] <command> [<args>]");
32
33 const char git_more_info_string[] =
34 N_("'git help -a' and 'git help -g' list available subcommands and some\n"
@@ -226,20 +224,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
224 setenv(GIT_WORK_TREE_ENVIRONMENT, cmd, 1);
225 if (envchanged)
226 *envchanged = 1;
229 - } else if (!strcmp(cmd, "--super-prefix")) {
230 - if (*argc < 2) {
231 - fprintf(stderr, _("no prefix given for --super-prefix\n" ));
232 - usage(git_usage_string);
233 - }
234 - setenv(GIT_SUPER_PREFIX_ENVIRONMENT, (*argv)[1], 1);
235 - if (envchanged)
236 - *envchanged = 1;
237 - (*argv)++;
238 - (*argc)--;
239 - } else if (skip_prefix(cmd, "--super-prefix=", &cmd)) {
240 - setenv(GIT_SUPER_PREFIX_ENVIRONMENT, cmd, 1);
241 - if (envchanged)
242 - *envchanged = 1;
227 } else if (!strcmp(cmd, "--bare")) {
228 char *cwd = xgetcwd();
229 is_bare_repository_cfg = 1;
@@ -449,11 +433,6 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
433 trace_repo_setup(prefix);
434 commit_pager_choice();
435
452 - if (!help && get_super_prefix()) {
453 - if (!(p->option & SUPPORT_SUPER_PREFIX))
454 - die(_("%s doesn't support --super-prefix"), p->cmd);
455 - }
456 -
436 if (!help && p->option & NEED_WORK_TREE)
437 setup_work_tree();
438
@@ -504,7 +483,7 @@ static struct cmd_struct commands[] = {
483 { "check-ref-format", cmd_check_ref_format, NO_PARSEOPT },
484 { "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
485 { "checkout--worker", cmd_checkout__worker,
507 - RUN_SETUP | NEED_WORK_TREE | SUPPORT_SUPER_PREFIX },
486 + RUN_SETUP | NEED_WORK_TREE },
487 { "checkout-index", cmd_checkout_index,
488 RUN_SETUP | NEED_WORK_TREE},
489 { "cherry", cmd_cherry, RUN_SETUP },
@@ -583,7 +562,7 @@ static struct cmd_struct commands[] = {
562 { "pull", cmd_pull, RUN_SETUP | NEED_WORK_TREE },
563 { "push", cmd_push, RUN_SETUP },
564 { "range-diff", cmd_range_diff, RUN_SETUP | USE_PAGER },
586 - { "read-tree", cmd_read_tree, RUN_SETUP | SUPPORT_SUPER_PREFIX},
565 + { "read-tree", cmd_read_tree, RUN_SETUP },
566 { "rebase", cmd_rebase, RUN_SETUP | NEED_WORK_TREE },
567 { "receive-pack", cmd_receive_pack },
568 { "reflog", cmd_reflog, RUN_SETUP },
@@ -727,9 +706,6 @@ static void execv_dashed_external(const char **argv)
706 struct child_process cmd = CHILD_PROCESS_INIT;
707 int status;
708
730 - if (get_super_prefix())
731 - die(_("%s doesn't support --super-prefix"), argv[0]);
732 -
709 if (use_pager == -1 && !is_builtin(argv[0]))
710 use_pager = check_pager_config(argv[0]);
711 commit_pager_choice();
@@ -799,9 +775,6 @@ static int run_argv(int *argcp, const char ***argv)
775 */
776 trace2_cmd_name("_run_git_alias_");
777
802 - if (get_super_prefix())
803 - die("%s doesn't support --super-prefix", **argv);
804 -
778 commit_pager_choice();
779
780 strvec_push(&cmd.args, "git");
submodule.c
+10 -19
@@ -2054,14 +2054,6 @@ void submodule_unset_core_worktree(const struct submodule *sub)
2054 strbuf_release(&config_path);
2055 }
2056
2057 -static const char *get_super_prefix_or_empty(void)
2058 -{
2059 - const char *s = get_super_prefix();
2060 - if (!s)
2061 - s = "";
2062 - return s;
2063 -}
2064 -
2057 static int submodule_has_dirty_index(const struct submodule *sub)
2058 {
2059 struct child_process cp = CHILD_PROCESS_INIT;
@@ -2080,7 +2072,7 @@ static int submodule_has_dirty_index(const struct submodule *sub)
2072 return finish_command(&cp);
2073 }
2074
2083 -static void submodule_reset_index(const char *path)
2075 +static void submodule_reset_index(const char *path, const char *super_prefix)
2076 {
2077 struct child_process cp = CHILD_PROCESS_INIT;
2078 prepare_submodule_repo_env(&cp.env);
@@ -2089,10 +2081,10 @@ static void submodule_reset_index(const char *path)
2081 cp.no_stdin = 1;
2082 cp.dir = path;
2083
2092 - strvec_pushf(&cp.args, "--super-prefix=%s%s/",
2093 - get_super_prefix_or_empty(), path);
2084 /* TODO: determine if this might overwright untracked files */
2085 strvec_pushl(&cp.args, "read-tree", "-u", "--reset", NULL);
2086 + strvec_pushf(&cp.args, "--super-prefix=%s%s/",
2087 + (super_prefix ? super_prefix : ""), path);
2088
2089 strvec_push(&cp.args, empty_tree_oid_hex());
2090
@@ -2105,10 +2097,9 @@ static void submodule_reset_index(const char *path)
2097 * For edge cases (a submodule coming into existence or removing a submodule)
2098 * pass NULL for old or new respectively.
2099 */
2108 -int submodule_move_head(const char *path,
2109 - const char *old_head,
2110 - const char *new_head,
2111 - unsigned flags)
2100 +int submodule_move_head(const char *path, const char *super_prefix,
2101 + const char *old_head, const char *new_head,
2102 + unsigned flags)
2103 {
2104 int ret = 0;
2105 struct child_process cp = CHILD_PROCESS_INIT;
@@ -2146,7 +2137,7 @@ int submodule_move_head(const char *path,
2137 if (old_head) {
2138 if (!submodule_uses_gitfile(path))
2139 absorb_git_dir_into_superproject(path,
2149 - get_super_prefix());
2140 + super_prefix);
2141 } else {
2142 struct strbuf gitdir = STRBUF_INIT;
2143 submodule_name_to_gitdir(&gitdir, the_repository,
@@ -2155,7 +2146,7 @@ int submodule_move_head(const char *path,
2146 strbuf_release(&gitdir);
2147
2148 /* make sure the index is clean as well */
2158 - submodule_reset_index(path);
2149 + submodule_reset_index(path, super_prefix);
2150 }
2151
2152 if (old_head && (flags & SUBMODULE_MOVE_HEAD_FORCE)) {
@@ -2173,9 +2164,9 @@ int submodule_move_head(const char *path,
2164 cp.no_stdin = 1;
2165 cp.dir = path;
2166
2176 - strvec_pushf(&cp.args, "--super-prefix=%s%s/",
2177 - get_super_prefix_or_empty(), path);
2167 strvec_pushl(&cp.args, "read-tree", "--recurse-submodules", NULL);
2168 + strvec_pushf(&cp.args, "--super-prefix=%s%s/",
2169 + (super_prefix ? super_prefix : ""), path);
2170
2171 if (flags & SUBMODULE_MOVE_HEAD_DRY_RUN)
2172 strvec_push(&cp.args, "-n");
submodule.h
+2 -3
@@ -150,9 +150,8 @@ int validate_submodule_git_dir(char *git_dir, const char *submodule_name);
150
151 #define SUBMODULE_MOVE_HEAD_DRY_RUN (1<<0)
152 #define SUBMODULE_MOVE_HEAD_FORCE (1<<1)
153 -int submodule_move_head(const char *path,
154 - const char *old,
155 - const char *new_head,
153 +int submodule_move_head(const char *path, const char *super_prefix,
154 + const char *old_head, const char *new_head,
155 unsigned flags);
156
157 void submodule_unset_core_worktree(const struct submodule *sub);
t/t1001-read-tree-m-2way.sh
+1 -1
@@ -370,7 +370,7 @@ test_expect_success 'read-tree supports the super-prefix' '
370 cat <<-EOF >expect &&
371 error: Updating '\''fictional/a'\'' would lose untracked files in it
372 EOF
373 - test_must_fail git --super-prefix fictional/ read-tree -u -m "$treeH" "$treeM" 2>actual &&
373 + test_must_fail git read-tree --super-prefix fictional/ -u -m "$treeH" "$treeM" 2>actual &&
374 test_cmp expect actual
375 '
376
t/t5616-partial-clone.sh
+1 -1
@@ -644,7 +644,7 @@ test_expect_success 'repack does not loosen promisor objects' '
644 grep "loosen_unused_packed_objects/loosened:0" trace
645 '
646
647 -test_expect_failure 'lazy-fetch in submodule succeeds' '
647 +test_expect_success 'lazy-fetch in submodule succeeds' '
648 # setup
649 test_config_global protocol.file.allow always &&
650
unpack-trees.c
+14 -10
@@ -71,7 +71,7 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_WARNING_TYPES] = {
71 ? ((o)->msgs[(type)]) \
72 : (unpack_plumbing_errors[(type)]) )
73
74 -static const char *super_prefixed(const char *path)
74 +static const char *super_prefixed(const char *path, const char *super_prefix)
75 {
76 /*
77 * It is necessary and sufficient to have two static buffers
@@ -83,7 +83,6 @@ static const char *super_prefixed(const char *path)
83 static unsigned idx = ARRAY_SIZE(buf) - 1;
84
85 if (super_prefix_len < 0) {
86 - const char *super_prefix = get_super_prefix();
86 if (!super_prefix) {
87 super_prefix_len = 0;
88 } else {
@@ -236,7 +235,8 @@ static int add_rejected_path(struct unpack_trees_options *o,
235 return -1;
236
237 if (!o->show_all_errors)
239 - return error(ERRORMSG(o, e), super_prefixed(path));
238 + return error(ERRORMSG(o, e), super_prefixed(path,
239 + o->super_prefix));
240
241 /*
242 * Otherwise, insert in a list for future display by
@@ -263,7 +263,8 @@ static void display_error_msgs(struct unpack_trees_options *o)
263 error_displayed = 1;
264 for (i = 0; i < rejects->nr; i++)
265 strbuf_addf(&path, "\t%s\n", rejects->items[i].string);
266 - error(ERRORMSG(o, e), super_prefixed(path.buf));
266 + error(ERRORMSG(o, e), super_prefixed(path.buf,
267 + o->super_prefix));
268 strbuf_release(&path);
269 }
270 string_list_clear(rejects, 0);
@@ -290,7 +291,8 @@ static void display_warning_msgs(struct unpack_trees_options *o)
291 warning_displayed = 1;
292 for (i = 0; i < rejects->nr; i++)
293 strbuf_addf(&path, "\t%s\n", rejects->items[i].string);
293 - warning(ERRORMSG(o, e), super_prefixed(path.buf));
294 + warning(ERRORMSG(o, e), super_prefixed(path.buf,
295 + o->super_prefix));
296 strbuf_release(&path);
297 }
298 string_list_clear(rejects, 0);
@@ -312,7 +314,8 @@ static int check_submodule_move_head(const struct cache_entry *ce,
314 if (o->reset)
315 flags |= SUBMODULE_MOVE_HEAD_FORCE;
316
315 - if (submodule_move_head(ce->name, old_id, new_id, flags))
317 + if (submodule_move_head(ce->name, o->super_prefix, old_id, new_id,
318 + flags))
319 return add_rejected_path(o, ERROR_WOULD_LOSE_SUBMODULE, ce->name);
320 return 0;
321 }
@@ -415,6 +418,7 @@ static int check_updates(struct unpack_trees_options *o,
418 int i, pc_workers, pc_threshold;
419
420 trace_performance_enter();
421 + state.super_prefix = o->super_prefix;
422 state.force = 1;
423 state.quiet = 1;
424 state.refresh_cache = 1;
@@ -445,7 +449,7 @@ static int check_updates(struct unpack_trees_options *o,
449
450 if (ce->ce_flags & CE_WT_REMOVE) {
451 display_progress(progress, ++cnt);
448 - unlink_entry(ce);
452 + unlink_entry(ce, o->super_prefix);
453 }
454 }
455
@@ -2959,8 +2963,8 @@ int bind_merge(const struct cache_entry * const *src,
2963 if (a && old)
2964 return o->quiet ? -1 :
2965 error(ERRORMSG(o, ERROR_BIND_OVERLAP),
2962 - super_prefixed(a->name),
2963 - super_prefixed(old->name));
2966 + super_prefixed(a->name, o->super_prefix),
2967 + super_prefixed(old->name, o->super_prefix));
2968 if (!a)
2969 return keep_entry(old, o);
2970 else
@@ -3021,7 +3025,7 @@ int stash_worktree_untracked_merge(const struct cache_entry * const *src,
3025
3026 if (worktree && untracked)
3027 return error(_("worktree and untracked commit have duplicate entries: %s"),
3024 - super_prefixed(worktree->name));
3028 + super_prefixed(worktree->name, o->super_prefix));
3029
3030 return merged_entry(worktree ? worktree : untracked, NULL, o);
3031 }
unpack-trees.h
+1
@@ -75,6 +75,7 @@ struct unpack_trees_options {
75 skip_cache_tree_update;
76 enum unpack_trees_reset_type reset;
77 const char *prefix;
78 + const char *super_prefix;
79 int cache_bottom;
80 struct pathspec *pathspec;
81 merge_fn_t fn;