Skip to content

Commit deef3cd

Browse files
committed
Merge branch 'sb/submodule-helper-clone-regression-fix'
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 e6ac6e1 + 1f15ba1 commit deef3cd

File tree

2 files changed

+57
-24
lines changed

2 files changed

+57
-24
lines changed

builtin/submodule--helper.c

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,11 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
196196

197197
static int module_clone(int argc, const char **argv, const char *prefix)
198198
{
199-
const char *path = NULL, *name = NULL, *url = NULL;
199+
const char *name = NULL, *url = NULL;
200200
const char *reference = NULL, *depth = NULL;
201201
int quiet = 0;
202202
FILE *submodule_dot_git;
203-
char *sm_gitdir, *cwd, *p;
203+
char *p, *path = NULL, *sm_gitdir;
204204
struct strbuf rel_path = STRBUF_INIT;
205205
struct strbuf sb = STRBUF_INIT;
206206

@@ -237,12 +237,19 @@ static int module_clone(int argc, const char **argv, const char *prefix)
237237
argc = parse_options(argc, argv, prefix, module_clone_options,
238238
git_submodule_helper_usage, 0);
239239

240-
if (argc || !url || !path)
240+
if (argc || !url || !path || !*path)
241241
usage_with_options(git_submodule_helper_usage,
242242
module_clone_options);
243243

244244
strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
245-
sm_gitdir = strbuf_detach(&sb, NULL);
245+
sm_gitdir = xstrdup(absolute_path(sb.buf));
246+
strbuf_reset(&sb);
247+
248+
if (!is_absolute_path(path)) {
249+
strbuf_addf(&sb, "%s/%s", get_git_work_tree(), path);
250+
path = strbuf_detach(&sb, NULL);
251+
} else
252+
path = xstrdup(path);
246253

247254
if (!file_exists(sm_gitdir)) {
248255
if (safe_create_leading_directories_const(sm_gitdir) < 0)
@@ -259,45 +266,30 @@ static int module_clone(int argc, const char **argv, const char *prefix)
259266
}
260267

261268
/* Write a .git file in the submodule to redirect to the superproject. */
262-
if (safe_create_leading_directories_const(path) < 0)
263-
die(_("could not create directory '%s'"), path);
264-
265-
if (path && *path)
266-
strbuf_addf(&sb, "%s/.git", path);
267-
else
268-
strbuf_addstr(&sb, ".git");
269-
269+
strbuf_addf(&sb, "%s/.git", path);
270270
if (safe_create_leading_directories_const(sb.buf) < 0)
271271
die(_("could not create leading directories of '%s'"), sb.buf);
272272
submodule_dot_git = fopen(sb.buf, "w");
273273
if (!submodule_dot_git)
274274
die_errno(_("cannot open file '%s'"), sb.buf);
275275

276-
fprintf(submodule_dot_git, "gitdir: %s\n",
277-
relative_path(sm_gitdir, path, &rel_path));
276+
fprintf_or_die(submodule_dot_git, "gitdir: %s\n",
277+
relative_path(sm_gitdir, path, &rel_path));
278278
if (fclose(submodule_dot_git))
279279
die(_("could not close file %s"), sb.buf);
280280
strbuf_reset(&sb);
281281
strbuf_reset(&rel_path);
282282

283-
cwd = xgetcwd();
284283
/* Redirect the worktree of the submodule in the superproject's config */
285-
if (!is_absolute_path(sm_gitdir)) {
286-
strbuf_addf(&sb, "%s/%s", cwd, sm_gitdir);
287-
free(sm_gitdir);
288-
sm_gitdir = strbuf_detach(&sb, NULL);
289-
}
290-
291-
strbuf_addf(&sb, "%s/%s", cwd, path);
292284
p = git_pathdup_submodule(path, "config");
293285
if (!p)
294286
die(_("could not get submodule directory for '%s'"), path);
295287
git_config_set_in_file(p, "core.worktree",
296-
relative_path(sb.buf, sm_gitdir, &rel_path));
288+
relative_path(path, sm_gitdir, &rel_path));
297289
strbuf_release(&sb);
298290
strbuf_release(&rel_path);
299291
free(sm_gitdir);
300-
free(cwd);
292+
free(path);
301293
free(p);
302294
return 0;
303295
}

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)