Skip to content

Commit f5e16b2

Browse files
committed
Merge branch 'sb/submodule-helper-clone-regression-fix' into maint
A partial rewrite of "git submodule" in the 2.7 timeframe changed the way the gitdir: pointer in the submodules point at the real repository location to use absolute paths by accident. This has been corrected. * sb/submodule-helper-clone-regression-fix: submodule--helper, module_clone: catch fprintf failure submodule--helper: do not borrow absolute_path() result for too long submodule--helper, module_clone: always operate on absolute paths submodule--helper clone: create the submodule path just once submodule--helper: fix potential NULL-dereference recursive submodules: test for relative paths
2 parents 75375ea + 1f15ba1 commit f5e16b2

File tree

2 files changed

+59
-23
lines changed

2 files changed

+59
-23
lines changed

builtin/submodule--helper.c

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,11 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
147147

148148
static int module_clone(int argc, const char **argv, const char *prefix)
149149
{
150-
const char *path = NULL, *name = NULL, *url = NULL;
150+
const char *name = NULL, *url = NULL;
151151
const char *reference = NULL, *depth = NULL;
152152
int quiet = 0;
153153
FILE *submodule_dot_git;
154-
char *sm_gitdir, *cwd, *p;
154+
char *p, *path = NULL, *sm_gitdir;
155155
struct strbuf rel_path = STRBUF_INIT;
156156
struct strbuf sb = STRBUF_INIT;
157157

@@ -188,8 +188,18 @@ static int module_clone(int argc, const char **argv, const char *prefix)
188188
argc = parse_options(argc, argv, prefix, module_clone_options,
189189
git_submodule_helper_usage, 0);
190190

191+
if (!path || !*path)
192+
die(_("submodule--helper: unspecified or empty --path"));
193+
191194
strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
192-
sm_gitdir = strbuf_detach(&sb, NULL);
195+
sm_gitdir = xstrdup(absolute_path(sb.buf));
196+
strbuf_reset(&sb);
197+
198+
if (!is_absolute_path(path)) {
199+
strbuf_addf(&sb, "%s/%s", get_git_work_tree(), path);
200+
path = strbuf_detach(&sb, NULL);
201+
} else
202+
path = xstrdup(path);
193203

194204
if (!file_exists(sm_gitdir)) {
195205
if (safe_create_leading_directories_const(sm_gitdir) < 0)
@@ -206,45 +216,30 @@ static int module_clone(int argc, const char **argv, const char *prefix)
206216
}
207217

208218
/* Write a .git file in the submodule to redirect to the superproject. */
209-
if (safe_create_leading_directories_const(path) < 0)
210-
die(_("could not create directory '%s'"), path);
211-
212-
if (path && *path)
213-
strbuf_addf(&sb, "%s/.git", path);
214-
else
215-
strbuf_addstr(&sb, ".git");
216-
219+
strbuf_addf(&sb, "%s/.git", path);
217220
if (safe_create_leading_directories_const(sb.buf) < 0)
218221
die(_("could not create leading directories of '%s'"), sb.buf);
219222
submodule_dot_git = fopen(sb.buf, "w");
220223
if (!submodule_dot_git)
221224
die_errno(_("cannot open file '%s'"), sb.buf);
222225

223-
fprintf(submodule_dot_git, "gitdir: %s\n",
224-
relative_path(sm_gitdir, path, &rel_path));
226+
fprintf_or_die(submodule_dot_git, "gitdir: %s\n",
227+
relative_path(sm_gitdir, path, &rel_path));
225228
if (fclose(submodule_dot_git))
226229
die(_("could not close file %s"), sb.buf);
227230
strbuf_reset(&sb);
228231
strbuf_reset(&rel_path);
229232

230-
cwd = xgetcwd();
231233
/* Redirect the worktree of the submodule in the superproject's config */
232-
if (!is_absolute_path(sm_gitdir)) {
233-
strbuf_addf(&sb, "%s/%s", cwd, sm_gitdir);
234-
free(sm_gitdir);
235-
sm_gitdir = strbuf_detach(&sb, NULL);
236-
}
237-
238-
strbuf_addf(&sb, "%s/%s", cwd, path);
239234
p = git_pathdup_submodule(path, "config");
240235
if (!p)
241236
die(_("could not get submodule directory for '%s'"), path);
242237
git_config_set_in_file(p, "core.worktree",
243-
relative_path(sb.buf, sm_gitdir, &rel_path));
238+
relative_path(path, sm_gitdir, &rel_path));
244239
strbuf_release(&sb);
245240
strbuf_release(&rel_path);
246241
free(sm_gitdir);
247-
free(cwd);
242+
free(path);
248243
free(p);
249244
return 0;
250245
}

t/t7400-submodule-basic.sh

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,47 @@ test_expect_success 'submodule add --name allows to replace a submodule with ano
818818
)
819819
'
820820

821+
test_expect_success 'recursive relative submodules stay relative' '
822+
test_when_finished "rm -rf super clone2 subsub sub3" &&
823+
mkdir subsub &&
824+
(
825+
cd subsub &&
826+
git init &&
827+
>t &&
828+
git add t &&
829+
git commit -m "initial commit"
830+
) &&
831+
mkdir sub3 &&
832+
(
833+
cd sub3 &&
834+
git init &&
835+
>t &&
836+
git add t &&
837+
git commit -m "initial commit" &&
838+
git submodule add ../subsub dirdir/subsub &&
839+
git commit -m "add submodule subsub"
840+
) &&
841+
mkdir super &&
842+
(
843+
cd super &&
844+
git init &&
845+
>t &&
846+
git add t &&
847+
git commit -m "initial commit" &&
848+
git submodule add ../sub3 &&
849+
git commit -m "add submodule sub"
850+
) &&
851+
git clone super clone2 &&
852+
(
853+
cd clone2 &&
854+
git submodule update --init --recursive &&
855+
echo "gitdir: ../.git/modules/sub3" >./sub3/.git_expect &&
856+
echo "gitdir: ../../../.git/modules/sub3/modules/dirdir/subsub" >./sub3/dirdir/subsub/.git_expect
857+
) &&
858+
test_cmp clone2/sub3/.git_expect clone2/sub3/.git &&
859+
test_cmp clone2/sub3/dirdir/subsub/.git_expect clone2/sub3/dirdir/subsub/.git
860+
'
861+
821862
test_expect_success 'submodule add with an existing name fails unless forced' '
822863
(
823864
cd addtest2 &&

0 commit comments

Comments
 (0)