Skip to content

Commit 6267072

Browse files
committed
Merge branch 'ng/submodule-default-remote' into seen
* ng/submodule-default-remote: submodule: fetch missing objects from default remote
2 parents bfe49b6 + 48701ad commit 6267072

File tree

6 files changed

+371
-4
lines changed

6 files changed

+371
-4
lines changed

builtin/submodule--helper.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,43 @@ static int get_default_remote_submodule(const char *module_path, char **default_
113113
return 0;
114114
}
115115

116+
static int module_get_default_remote(int argc, const char **argv, const char *prefix,
117+
struct repository *repo UNUSED)
118+
{
119+
const char *path;
120+
char *resolved_path = NULL;
121+
char *default_remote = NULL;
122+
int code;
123+
struct option options[] = {
124+
OPT_END()
125+
};
126+
const char *const usage[] = {
127+
N_("git submodule--helper get-default-remote <path>"),
128+
NULL
129+
};
130+
131+
argc = parse_options(argc, argv, prefix, options, usage, 0);
132+
if (argc != 1)
133+
usage_with_options(usage, options);
134+
135+
path = argv[0];
136+
if (prefix && *prefix && !is_absolute_path(path)) {
137+
resolved_path = xstrfmt("%s%s", prefix, path);
138+
path = resolved_path;
139+
}
140+
141+
code = get_default_remote_submodule(path, &default_remote);
142+
if (code) {
143+
free(resolved_path);
144+
return code;
145+
}
146+
147+
printf("%s\n", default_remote);
148+
free(default_remote);
149+
free(resolved_path);
150+
return 0;
151+
}
152+
116153
/* the result should be freed by the caller. */
117154
static char *get_submodule_displaypath(const char *path, const char *prefix,
118155
const char *super_prefix)
@@ -3789,6 +3826,7 @@ int cmd_submodule__helper(int argc,
37893826
OPT_SUBCOMMAND("set-url", &fn, module_set_url),
37903827
OPT_SUBCOMMAND("set-branch", &fn, module_set_branch),
37913828
OPT_SUBCOMMAND("create-branch", &fn, module_create_branch),
3829+
OPT_SUBCOMMAND("get-default-remote", &fn, module_get_default_remote),
37923830
OPT_END()
37933831
};
37943832
argc = parse_options(argc, argv, prefix, options, usage, 0);

submodule.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,8 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err,
17081708
if (spf->oid_fetch_tasks_nr) {
17091709
struct fetch_task *task =
17101710
spf->oid_fetch_tasks[spf->oid_fetch_tasks_nr - 1];
1711+
struct child_process cp_remote = CHILD_PROCESS_INIT;
1712+
struct strbuf remote_name = STRBUF_INIT;
17111713
spf->oid_fetch_tasks_nr--;
17121714

17131715
child_process_init(cp);
@@ -1721,8 +1723,19 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err,
17211723
strvec_pushf(&cp->args, "--submodule-prefix=%s%s/",
17221724
spf->prefix, task->sub->path);
17231725

1724-
/* NEEDSWORK: have get_default_remote from submodule--helper */
1725-
strvec_push(&cp->args, "origin");
1726+
cp_remote.git_cmd = 1;
1727+
strvec_pushl(&cp_remote.args, "submodule--helper",
1728+
"get-default-remote", task->sub->path, NULL);
1729+
1730+
if (!capture_command(&cp_remote, &remote_name, 0)) {
1731+
strbuf_trim_trailing_newline(&remote_name);
1732+
strvec_push(&cp->args, remote_name.buf);
1733+
} else {
1734+
/* Fallback to "origin" if the helper fails */
1735+
strvec_push(&cp->args, "origin");
1736+
}
1737+
strbuf_release(&remote_name);
1738+
17261739
oid_array_for_each_unique(task->commits,
17271740
append_oid_to_argv, &cp->args);
17281741

t/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,7 @@ integration_tests = [
900900
't7423-submodule-symlinks.sh',
901901
't7424-submodule-mixed-ref-formats.sh',
902902
't7425-submodule-gitdir-path-extension.sh',
903+
't7426-submodule-get-default-remote.sh',
903904
't7450-bad-git-dotfiles.sh',
904905
't7500-commit-template-squash-signoff.sh',
905906
't7501-commit-basic-functionality.sh',

t/t5526-fetch-submodules.sh

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -834,11 +834,37 @@ test_expect_success "fetch new submodule commits on-demand outside standard refs
834834
git commit -m "updated submodules outside of refs/heads" &&
835835
E=$(git rev-parse HEAD) &&
836836
git update-ref refs/changes/3 $E &&
837+
FETCH_TRACE="$(pwd)/trace.out" &&
838+
test_when_finished "rm -f \"$FETCH_TRACE\"" &&
837839
(
838840
cd downstream &&
839-
git fetch --recurse-submodules origin refs/changes/3:refs/heads/my_branch &&
841+
DEEP_START=$(git -C submodule/subdir/deepsubmodule rev-parse --short origin/deep) &&
842+
DEEP_END=$(git -C "$pwd/deepsubmodule" rev-parse --short deep) &&
843+
cat >"expect_fetch" <<-EOF &&
844+
From $pwd/.
845+
* [new ref] refs/changes/3 -> my_branch
846+
Fetching submodule sub1
847+
Fetching submodule sub1/subdir/deepsubmodule
848+
Fetching submodule submodule
849+
Fetching submodule submodule/subdir/deepsubmodule
850+
From $pwd/deepsubmodule
851+
$DEEP_START..$DEEP_END deep -> origin/deep
852+
From $pwd/./sub1
853+
* branch $D -> FETCH_HEAD
854+
Fetching submodule sub1/subdir/deepsubmodule
855+
From $pwd/submodule
856+
* branch $C -> FETCH_HEAD
857+
Fetching submodule submodule/subdir/deepsubmodule
858+
EOF
859+
GIT_TRACE="$FETCH_TRACE" git fetch --recurse-submodules origin \
860+
refs/changes/3:refs/heads/my_branch 2>actual_fetch &&
861+
test_cmp expect_fetch actual_fetch &&
840862
git -C submodule cat-file -t $C &&
841863
git -C sub1 cat-file -t $D &&
864+
test_grep "trace: built-in: git submodule--helper get-default-remote sub1" \
865+
"$FETCH_TRACE" &&
866+
test_grep "trace: built-in: git fetch .* --submodule-prefix=sub1/ origin" \
867+
"$FETCH_TRACE" &&
842868
git checkout --recurse-submodules FETCH_HEAD
843869
)
844870
'
@@ -929,6 +955,90 @@ test_expect_success 'fetch new submodule commit intermittently referenced by sup
929955
)
930956
'
931957

958+
test_expect_success 'fetch new submodule commits on-demand outside standard refspec with custom remote name' '
959+
# depends on the previous test for setup
960+
961+
# Rename the remote in sub1 from "origin" to "custom_remote"
962+
git -C downstream/sub1 remote rename origin custom_remote &&
963+
964+
# Create new commits in the original submodules
965+
C=$(git -C submodule commit-tree \
966+
-m "change outside refs/heads for custom remote" HEAD^{tree}) &&
967+
git -C submodule update-ref refs/changes/custom1 $C &&
968+
git update-index --cacheinfo 160000 $C submodule &&
969+
test_tick &&
970+
971+
D=$(git -C sub1 commit-tree \
972+
-m "change outside refs/heads for custom remote" HEAD^{tree}) &&
973+
git -C sub1 update-ref refs/changes/custom2 $D &&
974+
git update-index --cacheinfo 160000 $D sub1 &&
975+
976+
git commit \
977+
-m "updated submodules outside of refs/heads for custom remote" &&
978+
E=$(git rev-parse HEAD) &&
979+
git update-ref refs/changes/custom3 $E &&
980+
FETCH_TRACE="$(pwd)/trace.out" &&
981+
test_when_finished "rm -f \"$FETCH_TRACE\"" &&
982+
(
983+
cd downstream &&
984+
DEEP_START=$(git -C submodule/subdir/deepsubmodule rev-parse --short \
985+
origin/deep) &&
986+
DEEP_END=$(git -C "$pwd/deepsubmodule" rev-parse --short deep) &&
987+
cat >"expect_fetch_custom" <<-EOF &&
988+
From $pwd/.
989+
* [new ref] refs/changes/custom3 -> my_other_branch
990+
Fetching submodule sub1
991+
Fetching submodule sub1/subdir/deepsubmodule
992+
Fetching submodule submodule
993+
Fetching submodule submodule/subdir/deepsubmodule
994+
From $pwd/./sub1
995+
* branch $D -> FETCH_HEAD
996+
Fetching submodule sub1/subdir/deepsubmodule
997+
From $pwd/submodule
998+
* branch $C -> FETCH_HEAD
999+
Fetching submodule submodule/subdir/deepsubmodule
1000+
EOF
1001+
GIT_TRACE="$FETCH_TRACE" git fetch --recurse-submodules origin \
1002+
refs/changes/custom3:refs/heads/my_other_branch \
1003+
2>actual_fetch_custom &&
1004+
# the without .gitmodules test above causes warnings
1005+
grep -v "^warning: " actual_fetch_custom >actual_fetch_warnings_removed &&
1006+
test_cmp expect_fetch_custom actual_fetch_warnings_removed &&
1007+
1008+
git -C submodule cat-file -t $C &&
1009+
git -C sub1 cat-file -t $D &&
1010+
test_grep "trace: built-in: git submodule--helper get-default-remote sub1" \
1011+
"$FETCH_TRACE" &&
1012+
test_grep "trace: built-in: git fetch .* --submodule-prefix=sub1/ custom_remote $D" \
1013+
"$FETCH_TRACE" &&
1014+
git checkout --recurse-submodules FETCH_HEAD
1015+
)
1016+
'
1017+
1018+
test_expect_success 'fetch new submodule commit on-demand in FETCH_HEAD from custom remote' '
1019+
# depends on the previous test for setup
1020+
1021+
C=$(git -C submodule commit-tree -m "another change outside refs/heads for custom remote" HEAD^{tree}) &&
1022+
git -C submodule update-ref refs/changes/custom4 $C &&
1023+
git update-index --cacheinfo 160000 $C submodule &&
1024+
test_tick &&
1025+
1026+
D=$(git -C sub1 commit-tree -m "another change outside refs/heads for custom remote" HEAD^{tree}) &&
1027+
git -C sub1 update-ref refs/changes/custom5 $D &&
1028+
git update-index --cacheinfo 160000 $D sub1 &&
1029+
1030+
git commit -m "updated submodules outside of refs/heads" &&
1031+
E=$(git rev-parse HEAD) &&
1032+
git update-ref refs/changes/custom6 $E &&
1033+
(
1034+
cd downstream &&
1035+
git fetch --recurse-submodules origin refs/changes/custom6 &&
1036+
git -C submodule cat-file -t $C &&
1037+
git -C sub1 cat-file -t $D &&
1038+
git checkout --recurse-submodules FETCH_HEAD
1039+
)
1040+
'
1041+
9321042
add_commit_push () {
9331043
dir="$1" &&
9341044
msg="$2" &&

t/t5572-pull-submodule.sh

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,26 @@ test_expect_success 'fetch submodule remote of different name from superproject'
257257
git -C a-submodule reset --hard HEAD^^ &&
258258
259259
git -C child pull --no-recurse-submodules &&
260-
git -C child submodule update
260+
git -C child submodule update &&
261+
test_path_is_file child/a-submodule/moreecho.t
262+
'
263+
264+
test_expect_success 'fetch non-origin submodule remote named different from superproject' '
265+
git -C child/a-submodule remote rename origin o2 &&
266+
267+
# Create commit that is unreachable from current master branch
268+
# newmain is already reset in the previous test
269+
test_commit -C a-submodule echo_o2 &&
270+
test_commit -C a-submodule moreecho_o2 &&
271+
subc=$(git -C a-submodule rev-parse --short HEAD) &&
272+
273+
git -C parent/a-submodule fetch &&
274+
git -C parent/a-submodule checkout "$subc" &&
275+
git -C parent commit -m "update submodule o2" a-submodule &&
276+
git -C a-submodule reset --hard HEAD^^ &&
277+
278+
git -C child pull --recurse-submodules &&
279+
test_path_is_file child/a-submodule/moreecho_o2.t
261280
'
262281

263282
test_done

0 commit comments

Comments
 (0)