grep: fix worktree case in submodules

Running git-grep with --recurse-submodules results in a cached grep for the submodules even when --cached is not used. This makes all modifications in submodules' tracked files be always ignored when grepping. Solve that making git-grep respect the cached option when invoking grep_cache() inside grep_submodule(). Also, add tests to ensure that the desired behavior is performed. Reported-by: Daniel Zaoui <jackdanielz@eyomi.org> Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Matheus Tavares committed Jul 30, 2019 at 13:53 UTC 6a289d45c0e5d155f536d7c1f73c3b33690e92c6
2 files changed +27 -4
builtin/grep.c
+6 -4
@@ -403,7 +403,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
403 static int grep_submodule(struct grep_opt *opt,
404 const struct pathspec *pathspec,
405 const struct object_id *oid,
406 - const char *filename, const char *path)
406 + const char *filename, const char *path, int cached)
407 {
408 struct repository subrepo;
409 struct repository *superproject = opt->repo;
@@ -474,7 +474,7 @@ static int grep_submodule(struct grep_opt *opt,
474 strbuf_release(&base);
475 free(data);
476 } else {
477 - hit = grep_cache(&subopt, pathspec, 1);
477 + hit = grep_cache(&subopt, pathspec, cached);
478 }
479
480 repo_clear(&subrepo);
@@ -522,7 +522,8 @@ static int grep_cache(struct grep_opt *opt,
522 }
523 } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
524 submodule_path_match(repo->index, pathspec, name.buf, NULL)) {
525 - hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name);
525 + hit |= grep_submodule(opt, pathspec, NULL, ce->name,
526 + ce->name, cached);
527 } else {
528 continue;
529 }
@@ -597,7 +598,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
598 free(data);
599 } else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
600 hit |= grep_submodule(opt, pathspec, &entry.oid,
600 - base->buf, base->buf + tn_len);
601 + base->buf, base->buf + tn_len,
602 + 1); /* ignored */
603 }
604
605 strbuf_setlen(base, old_baselen);
t/t7814-grep-recurse-submodules.sh
+21
@@ -392,4 +392,25 @@ test_expect_success 'grep --recurse-submodules with submodules without .gitmodul
392 test_cmp expect actual
393 '
394
395 +reset_and_clean () {
396 + git reset --hard &&
397 + git clean -fd &&
398 + git submodule foreach --recursive 'git reset --hard' &&
399 + git submodule foreach --recursive 'git clean -fd'
400 +}
401 +
402 +test_expect_success 'grep --recurse-submodules without --cached considers worktree modifications' '
403 + reset_and_clean &&
404 + echo "A modified line in submodule" >>submodule/a &&
405 + echo "submodule/a:A modified line in submodule" >expect &&
406 + git grep --recurse-submodules "A modified line in submodule" >actual &&
407 + test_cmp expect actual
408 +'
409 +
410 +test_expect_success 'grep --recurse-submodules with --cached ignores worktree modifications' '
411 + reset_and_clean &&
412 + echo "A modified line in submodule" >>submodule/a &&
413 + test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
414 + test_must_be_empty actual
415 +'
416 test_done