]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'mt/grep-sparse-checkout'
authorJunio C Hamano <gitster@pobox.com>
Fri, 26 Feb 2021 00:43:31 +0000 (16:43 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 26 Feb 2021 00:43:31 +0000 (16:43 -0800)
"git grep" has been tweaked to be limited to the sparse checkout
paths.

* mt/grep-sparse-checkout:
  grep: honor sparse-checkout on working tree searches

builtin/grep.c
t/t7011-skip-worktree-reading.sh
t/t7817-grep-sparse-checkout.sh [new file with mode: 0755]

index e348e6bb3264693a88db5da4cd8f9e43a48a4023..4e91a253ac3b5fd0cdbd0436018c82fb45bde04c 100644 (file)
@@ -506,6 +506,10 @@ static int grep_cache(struct grep_opt *opt,
 
        for (nr = 0; nr < repo->index->cache_nr; nr++) {
                const struct cache_entry *ce = repo->index->cache[nr];
+
+               if (!cached && ce_skip_worktree(ce))
+                       continue;
+
                strbuf_setlen(&name, name_base_len);
                strbuf_addstr(&name, ce->name);
 
@@ -518,8 +522,7 @@ static int grep_cache(struct grep_opt *opt,
                         * cache entry are identical, even if worktree file has
                         * been modified, so use cache version instead
                         */
-                       if (cached || (ce->ce_flags & CE_VALID) ||
-                           ce_skip_worktree(ce)) {
+                       if (cached || (ce->ce_flags & CE_VALID)) {
                                if (ce_stage(ce) || ce_intent_to_add(ce))
                                        continue;
                                hit |= grep_oid(opt, &ce->oid, name.buf,
index 37525cae3af303dd60531226d885c72725b0ae53..26852586accf711fc5bf21ed800986f52a95b866 100755 (executable)
@@ -109,15 +109,6 @@ test_expect_success 'ls-files --modified' '
        test -z "$(git ls-files -m)"
 '
 
-test_expect_success 'grep with skip-worktree file' '
-       git update-index --no-skip-worktree 1 &&
-       echo test > 1 &&
-       git update-index 1 &&
-       git update-index --skip-worktree 1 &&
-       rm 1 &&
-       test "$(git grep --no-ext-grep test)" = "1:test"
-'
-
 echo ":000000 100644 $ZERO_OID $EMPTY_BLOB A   1" > expected
 test_expect_success 'diff-index does not examine skip-worktree absent entries' '
        setup_absent &&
diff --git a/t/t7817-grep-sparse-checkout.sh b/t/t7817-grep-sparse-checkout.sh
new file mode 100755 (executable)
index 0000000..590b99b
--- /dev/null
@@ -0,0 +1,174 @@
+#!/bin/sh
+
+test_description='grep in sparse checkout
+
+This test creates a repo with the following structure:
+
+.
+|-- a
+|-- b
+|-- dir
+|   `-- c
+|-- sub
+|   |-- A
+|   |   `-- a
+|   `-- B
+|       `-- b
+`-- sub2
+    `-- a
+
+Where the outer repository has non-cone mode sparsity patterns, sub is a
+submodule with cone mode sparsity patterns and sub2 is a submodule that is
+excluded by the superproject sparsity patterns. The resulting sparse checkout
+should leave the following structure in the working tree:
+
+.
+|-- a
+|-- sub
+|   `-- B
+|       `-- b
+`-- sub2
+    `-- a
+
+But note that sub2 should have the SKIP_WORKTREE bit set.
+'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       echo "text" >a &&
+       echo "text" >b &&
+       mkdir dir &&
+       echo "text" >dir/c &&
+
+       git init sub &&
+       (
+               cd sub &&
+               mkdir A B &&
+               echo "text" >A/a &&
+               echo "text" >B/b &&
+               git add A B &&
+               git commit -m sub &&
+               git sparse-checkout init --cone &&
+               git sparse-checkout set B
+       ) &&
+
+       git init sub2 &&
+       (
+               cd sub2 &&
+               echo "text" >a &&
+               git add a &&
+               git commit -m sub2
+       ) &&
+
+       git submodule add ./sub &&
+       git submodule add ./sub2 &&
+       git add a b dir &&
+       git commit -m super &&
+       git sparse-checkout init --no-cone &&
+       git sparse-checkout set "/*" "!b" "!/*/" "sub" &&
+
+       git tag -am tag-to-commit tag-to-commit HEAD &&
+       tree=$(git rev-parse HEAD^{tree}) &&
+       git tag -am tag-to-tree tag-to-tree $tree &&
+
+       test_path_is_missing b &&
+       test_path_is_missing dir &&
+       test_path_is_missing sub/A &&
+       test_path_is_file a &&
+       test_path_is_file sub/B/b &&
+       test_path_is_file sub2/a &&
+       git branch -m main
+'
+
+# The test below covers a special case: the sparsity patterns exclude '/b' and
+# sparse checkout is enabled, but the path exists in the working tree (e.g.
+# manually created after `git sparse-checkout init`). git grep should skip it.
+test_expect_success 'working tree grep honors sparse checkout' '
+       cat >expect <<-EOF &&
+       a:text
+       EOF
+       test_when_finished "rm -f b" &&
+       echo "new-text" >b &&
+       git grep "text" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'grep searches unmerged file despite not matching sparsity patterns' '
+       cat >expect <<-EOF &&
+       b:modified-b-in-branchX
+       b:modified-b-in-branchY
+       EOF
+       test_when_finished "test_might_fail git merge --abort && \
+                           git checkout main && git sparse-checkout init" &&
+
+       git sparse-checkout disable &&
+       git checkout -b branchY main &&
+       test_commit modified-b-in-branchY b &&
+       git checkout -b branchX main &&
+       test_commit modified-b-in-branchX b &&
+
+       git sparse-checkout init &&
+       test_path_is_missing b &&
+       test_must_fail git merge branchY &&
+       git grep "modified-b" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'grep --cached searches entries with the SKIP_WORKTREE bit' '
+       cat >expect <<-EOF &&
+       a:text
+       b:text
+       dir/c:text
+       EOF
+       git grep --cached "text" >actual &&
+       test_cmp expect actual
+'
+
+# Note that sub2/ is present in the worktree but it is excluded by the sparsity
+# patterns, so grep should not recurse into it.
+test_expect_success 'grep --recurse-submodules honors sparse checkout in submodule' '
+       cat >expect <<-EOF &&
+       a:text
+       sub/B/b:text
+       EOF
+       git grep --recurse-submodules "text" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'grep --recurse-submodules --cached searches entries with the SKIP_WORKTREE bit' '
+       cat >expect <<-EOF &&
+       a:text
+       b:text
+       dir/c:text
+       sub/A/a:text
+       sub/B/b:text
+       sub2/a:text
+       EOF
+       git grep --recurse-submodules --cached "text" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'working tree grep does not search the index with CE_VALID and SKIP_WORKTREE' '
+       cat >expect <<-EOF &&
+       a:text
+       EOF
+       test_when_finished "git update-index --no-assume-unchanged b" &&
+       git update-index --assume-unchanged b &&
+       git grep text >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'grep --cached searches index entries with both CE_VALID and SKIP_WORKTREE' '
+       cat >expect <<-EOF &&
+       a:text
+       b:text
+       dir/c:text
+       EOF
+       test_when_finished "git update-index --no-assume-unchanged b" &&
+       git update-index --assume-unchanged b &&
+       git grep --cached text >actual &&
+       test_cmp expect actual
+'
+
+test_done