summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2019-05-09 00:37:23 +0900
committerLibravatar Junio C Hamano <gitster@pobox.com>2019-05-09 00:37:23 +0900
commit4ab701b2eec46ab5cbfe8c9732897e5d100184d8 (patch)
tree9e2001084537775407d1e4376ec9a0f5791d32d6
parentMerge branch 'dl/warn-tagging-a-tag' (diff)
parentadd: error appropriately on repository with no commits (diff)
downloadtgif-4ab701b2eec46ab5cbfe8c9732897e5d100184d8.tar.xz
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
-rw-r--r--builtin/add.c3
-rw-r--r--dir.c6
-rwxr-xr-xgit-submodule.sh7
-rw-r--r--read-cache.c3
-rwxr-xr-xt/t3009-ls-files-others-nonsubmodule.sh50
-rwxr-xr-xt/t3700-add.sh12
-rwxr-xr-xt/t7400-submodule-basic.sh11
7 files changed, 88 insertions, 4 deletions
diff --git a/builtin/add.c b/builtin/add.c
index db2dfa4350..dd18e5c9b6 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -374,11 +374,12 @@ static int add_files(struct dir_struct *dir, int flags)
}
for (i = 0; i < dir->nr; i++) {
- check_embedded_repo(dir->entries[i]->name);
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
if (!ignore_add_errors)
die(_("adding files failed"));
exit_status = 1;
+ } else {
+ check_embedded_repo(dir->entries[i]->name);
}
}
return exit_status;
diff --git a/dir.c b/dir.c
index ad30a5a46d..0a3ddcf2bc 100644
--- a/dir.c
+++ b/dir.c
@@ -1466,9 +1466,11 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
return path_none;
}
if (!(dir->flags & DIR_NO_GITLINKS)) {
- struct object_id oid;
- if (resolve_gitlink_ref(dirname, "HEAD", &oid) == 0)
+ struct strbuf sb = STRBUF_INIT;
+ strbuf_addstr(&sb, dirname);
+ if (is_nonbare_repository_dir(&sb))
return exclude ? path_excluded : path_untracked;
+ strbuf_release(&sb);
}
return path_recurse;
}
diff --git a/git-submodule.sh b/git-submodule.sh
index e3c054bde5..c7f58c5756 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -232,6 +232,13 @@ cmd_add()
die "$(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
fi
+ if test -d "$sm_path" &&
+ test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
+ then
+ git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
+ die "$(eval_gettext "'\$sm_path' does not have a commit checked out")"
+ fi
+
if test -z "$force" &&
! git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" > /dev/null 2>&1
then
diff --git a/read-cache.c b/read-cache.c
index d5a74b1861..61b043bac3 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -709,6 +709,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
(intent_only ? ADD_CACHE_NEW_ONLY : 0));
int hash_flags = HASH_WRITE_OBJECT;
+ struct object_id oid;
if (flags & ADD_CACHE_RENORMALIZE)
hash_flags |= HASH_RENORMALIZE;
@@ -718,6 +719,8 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
namelen = strlen(path);
if (S_ISDIR(st_mode)) {
+ if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
+ return error(_("'%s' does not have a commit checked out"), path);
while (namelen && path[namelen-1] == '/')
namelen--;
}
diff --git a/t/t3009-ls-files-others-nonsubmodule.sh b/t/t3009-ls-files-others-nonsubmodule.sh
new file mode 100755
index 0000000000..963f3462b7
--- /dev/null
+++ b/t/t3009-ls-files-others-nonsubmodule.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='test git ls-files --others with non-submodule repositories
+
+This test runs git ls-files --others with the following working tree:
+
+ nonrepo-no-files/
+ plain directory with no files
+ nonrepo-untracked-file/
+ plain directory with an untracked file
+ repo-no-commit-no-files/
+ git repository without a commit or a file
+ repo-no-commit-untracked-file/
+ git repository without a commit but with an untracked file
+ repo-with-commit-no-files/
+ git repository with a commit and no untracked files
+ repo-with-commit-untracked-file/
+ git repository with a commit and an untracked file
+'
+
+. ./test-lib.sh
+
+test_expect_success 'setup: directories' '
+ mkdir nonrepo-no-files/ &&
+ mkdir nonrepo-untracked-file &&
+ : >nonrepo-untracked-file/untracked &&
+ git init repo-no-commit-no-files &&
+ git init repo-no-commit-untracked-file &&
+ : >repo-no-commit-untracked-file/untracked &&
+ git init repo-with-commit-no-files &&
+ git -C repo-with-commit-no-files commit --allow-empty -mmsg &&
+ git init repo-with-commit-untracked-file &&
+ test_commit -C repo-with-commit-untracked-file msg &&
+ : >repo-with-commit-untracked-file/untracked
+'
+
+test_expect_success 'ls-files --others handles untracked git repositories' '
+ git ls-files -o >output &&
+ cat >expect <<-EOF &&
+ nonrepo-untracked-file/untracked
+ output
+ repo-no-commit-no-files/
+ repo-no-commit-untracked-file/
+ repo-with-commit-no-files/
+ repo-with-commit-untracked-file/
+ EOF
+ test_cmp expect output
+'
+
+test_done
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index be582a513b..c325167b90 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -296,6 +296,17 @@ test_expect_success '"git add ." in empty repo' '
)
'
+test_expect_success 'error on a repository with no commits' '
+ rm -fr empty &&
+ git init empty &&
+ test_must_fail git add empty >actual 2>&1 &&
+ cat >expect <<-EOF &&
+ error: '"'empty/'"' does not have a commit checked out
+ fatal: adding files failed
+ EOF
+ test_i18ncmp expect actual
+'
+
test_expect_success 'git add --dry-run of existing changed file' "
echo new >>track-this &&
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' '
'
test_expect_success 'all statuses changed in folder if . is given' '
+ rm -fr empty &&
git add --chmod=+x . &&
test $(git ls-files --stage | grep ^100644 | wc -l) -eq 0 &&
git add --chmod=-x . &&
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index aba2d4d6ee..a208cb26e1 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -46,6 +46,15 @@ test_expect_success 'submodule update aborts on missing gitmodules url' '
test_must_fail git submodule init
'
+test_expect_success 'add aborts on repository with no commits' '
+ cat >expect <<-\EOF &&
+ '"'repo-no-commits'"' does not have a commit checked out
+ EOF
+ git init repo-no-commits &&
+ test_must_fail git submodule add ../a ./repo-no-commits 2>actual &&
+ test_i18ncmp expect actual
+'
+
test_expect_success 'setup - repository in init subdirectory' '
mkdir init &&
(
@@ -809,7 +818,7 @@ test_expect_success '../bar/a/b/c works with relative local path - ../foo/bar.gi
cp pristine-.git-config .git/config &&
cp pristine-.gitmodules .gitmodules &&
mkdir -p a/b/c &&
- (cd a/b/c && git init) &&
+ (cd a/b/c && git init && test_commit msg) &&
git config remote.origin.url ../foo/bar.git &&
git submodule add ../bar/a/b/c ./a/b/c &&
git submodule init &&