Skip to content

Commit e0a862f

Browse files
stefanbellergitster
authored andcommitted
submodule helper: convert relative URL to absolute URL if needed
The submodule helper update_clone called by "git submodule update", clones submodules if needed. As submodules used to have the URL indicating if they were active, the step to resolve relative URLs was done in the "submodule init" step. Nowadays submodules can be configured active without calling an explicit init, e.g. via configuring submodule.active. When trying to obtain submodules that are set active this way, we'll fallback to the URL found in the .gitmodules, which may be relative to the superproject, but we do not resolve it, yet: git clone https://gerrit.googlesource.com/gerrit cd gerrit && grep url .gitmodules url = ../plugins/codemirror-editor ... git config submodule.active . git submodule update fatal: repository '../plugins/codemirror-editor' does not exist fatal: clone of '../plugins/codemirror-editor' into submodule path '/tmp/gerrit/plugins/codemirror-editor' failed Failed to clone 'plugins/codemirror-editor'. Retry scheduled [...] fatal: clone of '../plugins/codemirror-editor' into submodule path '/tmp/gerrit/plugins/codemirror-editor' failed Failed to clone 'plugins/codemirror-editor' a second time, aborting [...] To resolve the issue, factor out the function that resolves the relative URLs in "git submodule init" (in the submodule helper in the init_submodule function) and call it at the appropriate place in the update_clone helper. Reported-by: Jaewoong Jung <[email protected]> Signed-off-by: Stefan Beller <[email protected]> Reviewed-by: Jonathan Nieder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cae598d commit e0a862f

File tree

2 files changed

+58
-17
lines changed

2 files changed

+58
-17
lines changed

builtin/submodule--helper.c

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,26 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
584584
return 0;
585585
}
586586

587+
static char *compute_submodule_clone_url(const char *rel_url)
588+
{
589+
char *remoteurl, *relurl;
590+
char *remote = get_default_remote();
591+
struct strbuf remotesb = STRBUF_INIT;
592+
593+
strbuf_addf(&remotesb, "remote.%s.url", remote);
594+
if (git_config_get_string(remotesb.buf, &remoteurl)) {
595+
warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
596+
remoteurl = xgetcwd();
597+
}
598+
relurl = relative_url(remoteurl, rel_url, NULL);
599+
600+
free(remote);
601+
free(remoteurl);
602+
strbuf_release(&remotesb);
603+
604+
return relurl;
605+
}
606+
587607
struct init_cb {
588608
const char *prefix;
589609
unsigned int flags;
@@ -634,21 +654,9 @@ static void init_submodule(const char *path, const char *prefix,
634654
/* Possibly a url relative to parent */
635655
if (starts_with_dot_dot_slash(url) ||
636656
starts_with_dot_slash(url)) {
637-
char *remoteurl, *relurl;
638-
char *remote = get_default_remote();
639-
struct strbuf remotesb = STRBUF_INIT;
640-
strbuf_addf(&remotesb, "remote.%s.url", remote);
641-
free(remote);
642-
643-
if (git_config_get_string(remotesb.buf, &remoteurl)) {
644-
warning(_("could not lookup configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
645-
remoteurl = xgetcwd();
646-
}
647-
relurl = relative_url(remoteurl, url, NULL);
648-
strbuf_release(&remotesb);
649-
free(remoteurl);
650-
free(url);
651-
url = relurl;
657+
char *oldurl = url;
658+
url = compute_submodule_clone_url(oldurl);
659+
free(oldurl);
652660
}
653661

654662
if (git_config_set_gently(sb.buf, url))
@@ -1515,6 +1523,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
15151523
struct strbuf sb = STRBUF_INIT;
15161524
const char *displaypath = NULL;
15171525
int needs_cloning = 0;
1526+
int need_free_url = 0;
15181527

15191528
if (ce_stage(ce)) {
15201529
if (suc->recursive_prefix)
@@ -1563,8 +1572,14 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
15631572

15641573
strbuf_reset(&sb);
15651574
strbuf_addf(&sb, "submodule.%s.url", sub->name);
1566-
if (repo_config_get_string_const(the_repository, sb.buf, &url))
1567-
url = sub->url;
1575+
if (repo_config_get_string_const(the_repository, sb.buf, &url)) {
1576+
if (starts_with_dot_slash(sub->url) ||
1577+
starts_with_dot_dot_slash(sub->url)) {
1578+
url = compute_submodule_clone_url(sub->url);
1579+
need_free_url = 1;
1580+
} else
1581+
url = sub->url;
1582+
}
15681583

15691584
strbuf_reset(&sb);
15701585
strbuf_addf(&sb, "%s/.git", ce->name);
@@ -1609,6 +1624,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
16091624
cleanup:
16101625
strbuf_reset(&displaypath_sb);
16111626
strbuf_reset(&sb);
1627+
if (need_free_url)
1628+
free((void*)url);
16121629

16131630
return needs_cloning;
16141631
}

t/t7400-submodule-basic.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,30 @@ test_expect_success 'submodule update and setting submodule.<name>.active' '
12241224
test_cmp expect actual
12251225
'
12261226

1227+
test_expect_success 'clone active submodule without submodule url set' '
1228+
test_when_finished "rm -rf test/test" &&
1229+
mkdir test &&
1230+
# another dir breaks accidental relative paths still being correct
1231+
git clone file://"$pwd"/multisuper test/test &&
1232+
(
1233+
cd test/test &&
1234+
git config submodule.active "." &&
1235+
1236+
# do not pass --init flag, as the submodule is already active:
1237+
git submodule update &&
1238+
git submodule status >actual_raw &&
1239+
1240+
cut -c 1,43- actual_raw >actual &&
1241+
cat >expect <<-\EOF &&
1242+
sub0 (test2)
1243+
sub1 (test2)
1244+
sub2 (test2)
1245+
sub3 (test2)
1246+
EOF
1247+
test_cmp expect actual
1248+
)
1249+
'
1250+
12271251
test_expect_success 'clone --recurse-submodules with a pathspec works' '
12281252
test_when_finished "rm -rf multisuper_clone" &&
12291253
cat >expected <<-\EOF &&

0 commit comments

Comments
 (0)