Skip to content

Commit 5ac781a

Browse files
pks-tgitster
authored andcommitted
builtin/submodule: allow cloning with different ref storage format
As submodules are proper self-contained repositories, it is perfectly valid for them to have a different ref storage format than their parent repository. There is no obvious way for users to ask for the ref storage format when initializing submodules though. Whether the setup of such mixed-ref-storage-format constellations is all that useful remains to be seen. But there is no good reason to not expose such an option, and we will require it in a subsequent patch. Introduce a new `--ref-format=` option for git-submodule(1) that allows the user to pick the ref storage format. This option will also be used in a subsequent commit, where we start to propagate the same flag from git-clone(1) to cloning submodules with the `--recursive` switch. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d9ab878 commit 5ac781a

File tree

4 files changed

+84
-1
lines changed

4 files changed

+84
-1
lines changed

Documentation/git-submodule.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ If you really want to remove a submodule from the repository and commit
136136
that use linkgit:git-rm[1] instead. See linkgit:gitsubmodules[7] for removal
137137
options.
138138

139-
update [--init] [--remote] [-N|--no-fetch] [--[no-]recommend-shallow] [-f|--force] [--checkout|--rebase|--merge] [--reference <repository>] [--depth <depth>] [--recursive] [--jobs <n>] [--[no-]single-branch] [--filter <filter-spec>] [--] [<path>...]::
139+
update [--init] [--remote] [-N|--no-fetch] [--[no-]recommend-shallow] [-f|--force] [--checkout|--rebase|--merge] [--reference <repository>] [--ref-format <format>] [--depth <depth>] [--recursive] [--jobs <n>] [--[no-]single-branch] [--filter <filter-spec>] [--] [<path>...]::
140140
+
141141
--
142142
Update the registered submodules to match what the superproject
@@ -185,6 +185,9 @@ submodule with the `--init` option.
185185
If `--recursive` is specified, this command will recurse into the
186186
registered submodules, and update any nested submodules within.
187187

188+
If `--ref-format <format>` is specified, the ref storage format of newly
189+
cloned submodules will be set accordingly.
190+
188191
If `--filter <filter-spec>` is specified, the given partial clone filter will be
189192
applied to the submodule. See linkgit:git-rev-list[1] for details on filter
190193
specifications.

builtin/submodule--helper.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,6 +1532,7 @@ struct module_clone_data {
15321532
const char *url;
15331533
const char *depth;
15341534
struct list_objects_filter_options *filter_options;
1535+
enum ref_storage_format ref_storage_format;
15351536
unsigned int quiet: 1;
15361537
unsigned int progress: 1;
15371538
unsigned int dissociate: 1;
@@ -1540,6 +1541,7 @@ struct module_clone_data {
15401541
};
15411542
#define MODULE_CLONE_DATA_INIT { \
15421543
.single_branch = -1, \
1544+
.ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN, \
15431545
}
15441546

15451547
struct submodule_alternate_setup {
@@ -1738,6 +1740,9 @@ static int clone_submodule(const struct module_clone_data *clone_data,
17381740
strvec_pushl(&cp.args, "--reference",
17391741
item->string, NULL);
17401742
}
1743+
if (clone_data->ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN)
1744+
strvec_pushf(&cp.args, "--ref-format=%s",
1745+
ref_storage_format_to_name(clone_data->ref_storage_format));
17411746
if (clone_data->dissociate)
17421747
strvec_push(&cp.args, "--dissociate");
17431748
if (sm_gitdir && *sm_gitdir)
@@ -1832,6 +1837,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
18321837
struct string_list reference = STRING_LIST_INIT_NODUP;
18331838
struct list_objects_filter_options filter_options =
18341839
LIST_OBJECTS_FILTER_INIT;
1840+
const char *ref_storage_format = NULL;
18351841

18361842
struct option module_clone_options[] = {
18371843
OPT_STRING(0, "prefix", &clone_data.prefix,
@@ -1849,6 +1855,8 @@ static int module_clone(int argc, const char **argv, const char *prefix)
18491855
OPT_STRING_LIST(0, "reference", &reference,
18501856
N_("repo"),
18511857
N_("reference repository")),
1858+
OPT_STRING(0, "ref-format", &ref_storage_format, N_("format"),
1859+
N_("specify the reference format to use")),
18521860
OPT_BOOL(0, "dissociate", &dissociate,
18531861
N_("use --reference only while cloning")),
18541862
OPT_STRING(0, "depth", &clone_data.depth,
@@ -1875,6 +1883,11 @@ static int module_clone(int argc, const char **argv, const char *prefix)
18751883
argc = parse_options(argc, argv, prefix, module_clone_options,
18761884
git_submodule_helper_usage, 0);
18771885

1886+
if (ref_storage_format) {
1887+
clone_data.ref_storage_format = ref_storage_format_by_name(ref_storage_format);
1888+
if (clone_data.ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
1889+
die(_("unknown ref storage format '%s'"), ref_storage_format);
1890+
}
18781891
clone_data.dissociate = !!dissociate;
18791892
clone_data.quiet = !!quiet;
18801893
clone_data.progress = !!progress;
@@ -1974,6 +1987,7 @@ struct update_data {
19741987
struct submodule_update_strategy update_strategy;
19751988
struct list_objects_filter_options *filter_options;
19761989
struct module_list list;
1990+
enum ref_storage_format ref_storage_format;
19771991
int depth;
19781992
int max_jobs;
19791993
int single_branch;
@@ -1997,6 +2011,7 @@ struct update_data {
19972011
#define UPDATE_DATA_INIT { \
19982012
.update_strategy = SUBMODULE_UPDATE_STRATEGY_INIT, \
19992013
.list = MODULE_LIST_INIT, \
2014+
.ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN, \
20002015
.recommend_shallow = -1, \
20012016
.references = STRING_LIST_INIT_DUP, \
20022017
.single_branch = -1, \
@@ -2132,6 +2147,9 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
21322147
expand_list_objects_filter_spec(suc->update_data->filter_options));
21332148
if (suc->update_data->require_init)
21342149
strvec_push(&child->args, "--require-init");
2150+
if (suc->update_data->ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN)
2151+
strvec_pushf(&child->args, "--ref-format=%s",
2152+
ref_storage_format_to_name(suc->update_data->ref_storage_format));
21352153
strvec_pushl(&child->args, "--path", sub->path, NULL);
21362154
strvec_pushl(&child->args, "--name", sub->name, NULL);
21372155
strvec_pushl(&child->args, "--url", url, NULL);
@@ -2562,6 +2580,9 @@ static void update_data_to_args(const struct update_data *update_data,
25622580
for_each_string_list_item(item, &update_data->references)
25632581
strvec_pushl(args, "--reference", item->string, NULL);
25642582
}
2583+
if (update_data->ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN)
2584+
strvec_pushf(args, "--ref-format=%s",
2585+
ref_storage_format_to_name(update_data->ref_storage_format));
25652586
if (update_data->filter_options && update_data->filter_options->choice)
25662587
strvec_pushf(args, "--filter=%s",
25672588
expand_list_objects_filter_spec(
@@ -2737,6 +2758,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
27372758
struct update_data opt = UPDATE_DATA_INIT;
27382759
struct list_objects_filter_options filter_options =
27392760
LIST_OBJECTS_FILTER_INIT;
2761+
const char *ref_storage_format = NULL;
27402762
int ret;
27412763
struct option module_update_options[] = {
27422764
OPT__SUPER_PREFIX(&opt.super_prefix),
@@ -2760,6 +2782,8 @@ static int module_update(int argc, const char **argv, const char *prefix)
27602782
SM_UPDATE_REBASE),
27612783
OPT_STRING_LIST(0, "reference", &opt.references, N_("repo"),
27622784
N_("reference repository")),
2785+
OPT_STRING(0, "ref-format", &ref_storage_format, N_("format"),
2786+
N_("specify the reference format to use")),
27632787
OPT_BOOL(0, "dissociate", &opt.dissociate,
27642788
N_("use --reference only while cloning")),
27652789
OPT_INTEGER(0, "depth", &opt.depth,
@@ -2803,6 +2827,12 @@ static int module_update(int argc, const char **argv, const char *prefix)
28032827
module_update_options);
28042828
}
28052829

2830+
if (ref_storage_format) {
2831+
opt.ref_storage_format = ref_storage_format_by_name(ref_storage_format);
2832+
if (opt.ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
2833+
die(_("unknown ref storage format '%s'"), ref_storage_format);
2834+
}
2835+
28062836
opt.filter_options = &filter_options;
28072837
opt.prefix = prefix;
28082838

git-submodule.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,14 @@ cmd_update()
290290
-r|--rebase)
291291
rebase=1
292292
;;
293+
--ref-format)
294+
case "$2" in '') usage ;; esac
295+
ref_format="--ref-format=$2"
296+
shift
297+
;;
298+
--ref-format=*)
299+
ref_format="$1"
300+
;;
293301
--reference)
294302
case "$2" in '') usage ;; esac
295303
reference="--reference=$2"
@@ -371,6 +379,7 @@ cmd_update()
371379
${rebase:+--rebase} \
372380
${merge:+--merge} \
373381
${checkout:+--checkout} \
382+
${ref_format:+"$ref_format"} \
374383
${reference:+"$reference"} \
375384
${dissociate:+"--dissociate"} \
376385
${depth:+"$depth"} \
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/bin/sh
2+
3+
test_description='submodules handle mixed ref storage formats'
4+
5+
. ./test-lib.sh
6+
7+
test_ref_format () {
8+
echo "$2" >expect &&
9+
git -C "$1" rev-parse --show-ref-format >actual &&
10+
test_cmp expect actual
11+
}
12+
13+
for OTHER_FORMAT in files reftable
14+
do
15+
if test "$OTHER_FORMAT" = "$GIT_DEFAULT_REF_FORMAT"
16+
then
17+
continue
18+
fi
19+
20+
test_expect_success 'setup' '
21+
git config set --global protocol.file.allow always
22+
'
23+
24+
test_expect_success 'clone submodules with different ref storage format' '
25+
test_when_finished "rm -rf submodule upstream downstream" &&
26+
27+
git init submodule &&
28+
test_commit -C submodule submodule-initial &&
29+
git init upstream &&
30+
git -C upstream submodule add "file://$(pwd)/submodule" &&
31+
git -C upstream commit -m "upstream submodule" &&
32+
33+
git clone --no-recurse-submodules "file://$(pwd)/upstream" downstream &&
34+
test_ref_format downstream "$GIT_DEFAULT_REF_FORMAT" &&
35+
git -C downstream submodule update --init --ref-format=$OTHER_FORMAT &&
36+
test_ref_format downstream/submodule "$OTHER_FORMAT"
37+
'
38+
39+
done
40+
41+
test_done

0 commit comments

Comments
 (0)