Skip to content

Commit b228270

Browse files
kyleamgitster
authored andcommitted
dir: do not traverse repositories with no commits
When treat_directory() encounters a directory that is not in the index and DIR_NO_GITLINKS is unset, it calls resolve_gitlink_ref() to decide if a directory looks like a repository, in which case the directory won't be traversed. As a result, 'status -uall' and 'ls-files -o' will show only the directory, even when there are untracked files within the directory. For the unusual case where a repository doesn't have a commit checked out, resolve_gitlink_ref() returns -1 because HEAD cannot be resolved, and the directory is treated as a normal directory (i.e. traversal does not stop at the repository boundary). The status and ls-files commands above list untracked files within the repository rather than showing only the top-level directory. And if 'git add' is called on a repository with no commit checked out, any untracked files under the repository are added as blobs in the top-level project, a behavior that is unlikely to be what the caller intended. The above case is a corner case in an already unusual situation of the working tree containing a repository that is not a tracked submodule, but we might as well treat anything that looks like a repository consistently. Loosen the "looks like a repository" criteria in treat_directory() by replacing resolve_gitlink_ref() with is_nonbare_repository_dir(), one of the checks that is performed downstream when resolve_gitlink_ref() is called. As the required update to t3700-add shows, calling 'git add' on a repository with no commit checked out will now raise an error. While this is the desired behavior, note that the output isn't yet appropriate. The next commit will improve this output. Signed-off-by: Kyle Meyer <kyle@kyleam.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent e138111 commit b228270

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

dir.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,9 +1467,11 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
14671467
return path_none;
14681468
}
14691469
if (!(dir->flags & DIR_NO_GITLINKS)) {
1470-
struct object_id oid;
1471-
if (resolve_gitlink_ref(dirname, "HEAD", &oid) == 0)
1470+
struct strbuf sb = STRBUF_INIT;
1471+
strbuf_addstr(&sb, dirname);
1472+
if (is_nonbare_repository_dir(&sb))
14721473
return exclude ? path_excluded : path_untracked;
1474+
strbuf_release(&sb);
14731475
}
14741476
return path_recurse;
14751477
}
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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ test_expect_success 'no file status change if no pathspec is given in subdir' '
396396
'
397397

398398
test_expect_success 'all statuses changed in folder if . is given' '
399+
rm -fr empty &&
399400
git add --chmod=+x . &&
400401
test $(git ls-files --stage | grep ^100644 | wc -l) -eq 0 &&
401402
git add --chmod=-x . &&

0 commit comments

Comments
 (0)