Skip to content

Commit 4ab701b

Browse files
committed
Merge branch 'km/empty-repo-is-still-a-repo'
Running "git add" on a repository created inside the current repository is an explicit indication that the user wants to add it as a submodule, but when the HEAD of the inner repository is on an unborn branch, it cannot be added as a submodule. Worse, the files in its working tree can be added as if they are a part of the outer repository, which is not what the user wants. These problems are being addressed. * km/empty-repo-is-still-a-repo: add: error appropriately on repository with no commits dir: do not traverse repositories with no commits submodule: refuse to add repository with no commits
2 parents a198562 + f937bc2 commit 4ab701b

File tree

7 files changed

+88
-4
lines changed

7 files changed

+88
-4
lines changed

builtin/add.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,11 +374,12 @@ static int add_files(struct dir_struct *dir, int flags)
374374
}
375375

376376
for (i = 0; i < dir->nr; i++) {
377-
check_embedded_repo(dir->entries[i]->name);
378377
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
379378
if (!ignore_add_errors)
380379
die(_("adding files failed"));
381380
exit_status = 1;
381+
} else {
382+
check_embedded_repo(dir->entries[i]->name);
382383
}
383384
}
384385
return exit_status;

dir.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,9 +1466,11 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
14661466
return path_none;
14671467
}
14681468
if (!(dir->flags & DIR_NO_GITLINKS)) {
1469-
struct object_id oid;
1470-
if (resolve_gitlink_ref(dirname, "HEAD", &oid) == 0)
1469+
struct strbuf sb = STRBUF_INIT;
1470+
strbuf_addstr(&sb, dirname);
1471+
if (is_nonbare_repository_dir(&sb))
14711472
return exclude ? path_excluded : path_untracked;
1473+
strbuf_release(&sb);
14721474
}
14731475
return path_recurse;
14741476
}

git-submodule.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,13 @@ cmd_add()
232232
die "$(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
233233
fi
234234

235+
if test -d "$sm_path" &&
236+
test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
237+
then
238+
git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
239+
die "$(eval_gettext "'\$sm_path' does not have a commit checked out")"
240+
fi
241+
235242
if test -z "$force" &&
236243
! git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" > /dev/null 2>&1
237244
then

read-cache.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
709709
int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
710710
(intent_only ? ADD_CACHE_NEW_ONLY : 0));
711711
int hash_flags = HASH_WRITE_OBJECT;
712+
struct object_id oid;
712713

713714
if (flags & ADD_CACHE_RENORMALIZE)
714715
hash_flags |= HASH_RENORMALIZE;
@@ -718,6 +719,8 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
718719

719720
namelen = strlen(path);
720721
if (S_ISDIR(st_mode)) {
722+
if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
723+
return error(_("'%s' does not have a commit checked out"), path);
721724
while (namelen && path[namelen-1] == '/')
722725
namelen--;
723726
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/sh
2+
3+
test_description='test git ls-files --others with non-submodule repositories
4+
5+
This test runs git ls-files --others with the following working tree:
6+
7+
nonrepo-no-files/
8+
plain directory with no files
9+
nonrepo-untracked-file/
10+
plain directory with an untracked file
11+
repo-no-commit-no-files/
12+
git repository without a commit or a file
13+
repo-no-commit-untracked-file/
14+
git repository without a commit but with an untracked file
15+
repo-with-commit-no-files/
16+
git repository with a commit and no untracked files
17+
repo-with-commit-untracked-file/
18+
git repository with a commit and an untracked file
19+
'
20+
21+
. ./test-lib.sh
22+
23+
test_expect_success 'setup: directories' '
24+
mkdir nonrepo-no-files/ &&
25+
mkdir nonrepo-untracked-file &&
26+
: >nonrepo-untracked-file/untracked &&
27+
git init repo-no-commit-no-files &&
28+
git init repo-no-commit-untracked-file &&
29+
: >repo-no-commit-untracked-file/untracked &&
30+
git init repo-with-commit-no-files &&
31+
git -C repo-with-commit-no-files commit --allow-empty -mmsg &&
32+
git init repo-with-commit-untracked-file &&
33+
test_commit -C repo-with-commit-untracked-file msg &&
34+
: >repo-with-commit-untracked-file/untracked
35+
'
36+
37+
test_expect_success 'ls-files --others handles untracked git repositories' '
38+
git ls-files -o >output &&
39+
cat >expect <<-EOF &&
40+
nonrepo-untracked-file/untracked
41+
output
42+
repo-no-commit-no-files/
43+
repo-no-commit-untracked-file/
44+
repo-with-commit-no-files/
45+
repo-with-commit-untracked-file/
46+
EOF
47+
test_cmp expect output
48+
'
49+
50+
test_done

t/t3700-add.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,17 @@ test_expect_success '"git add ." in empty repo' '
296296
)
297297
'
298298

299+
test_expect_success 'error on a repository with no commits' '
300+
rm -fr empty &&
301+
git init empty &&
302+
test_must_fail git add empty >actual 2>&1 &&
303+
cat >expect <<-EOF &&
304+
error: '"'empty/'"' does not have a commit checked out
305+
fatal: adding files failed
306+
EOF
307+
test_i18ncmp expect actual
308+
'
309+
299310
test_expect_success 'git add --dry-run of existing changed file' "
300311
echo new >>track-this &&
301312
git add --dry-run track-this >actual 2>&1 &&
@@ -396,6 +407,7 @@ test_expect_success 'no file status change if no pathspec is given in subdir' '
396407
'
397408

398409
test_expect_success 'all statuses changed in folder if . is given' '
410+
rm -fr empty &&
399411
git add --chmod=+x . &&
400412
test $(git ls-files --stage | grep ^100644 | wc -l) -eq 0 &&
401413
git add --chmod=-x . &&

t/t7400-submodule-basic.sh

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ test_expect_success 'submodule update aborts on missing gitmodules url' '
4646
test_must_fail git submodule init
4747
'
4848

49+
test_expect_success 'add aborts on repository with no commits' '
50+
cat >expect <<-\EOF &&
51+
'"'repo-no-commits'"' does not have a commit checked out
52+
EOF
53+
git init repo-no-commits &&
54+
test_must_fail git submodule add ../a ./repo-no-commits 2>actual &&
55+
test_i18ncmp expect actual
56+
'
57+
4958
test_expect_success 'setup - repository in init subdirectory' '
5059
mkdir init &&
5160
(
@@ -809,7 +818,7 @@ test_expect_success '../bar/a/b/c works with relative local path - ../foo/bar.gi
809818
cp pristine-.git-config .git/config &&
810819
cp pristine-.gitmodules .gitmodules &&
811820
mkdir -p a/b/c &&
812-
(cd a/b/c && git init) &&
821+
(cd a/b/c && git init && test_commit msg) &&
813822
git config remote.origin.url ../foo/bar.git &&
814823
git submodule add ../bar/a/b/c ./a/b/c &&
815824
git submodule init &&

0 commit comments

Comments
 (0)