From: ZheNing Hu <adlternative@xxxxxxxxx> Because we may want to restrict grep's file scope to sparse specification, Apply the --scope option we implemented in diff to grep as well. `--scope=sparse` mean that the search file scope restrict to sparse specification when we grep something in commit history, and `--scope=all` mean that the search file scope will be full-tree. Note that `--scope` option only oly takes effect when "git grep <tree>" is specified. Signed-off-by: ZheNing Hu <adlternative@xxxxxxxxx> --- Documentation/git-grep.txt | 24 ++++++++++++++++++++++++ builtin/grep.c | 10 ++++++++++ grep.h | 2 ++ t/t1090-sparse-checkout-scope.sh | 27 +++++++++++++++++++++++++++ 4 files changed, 63 insertions(+) diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index dabdbe8471d..b556f657306 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -28,6 +28,7 @@ SYNOPSIS [-f <file>] [-e] <pattern> [--and|--or|--not|(|)|-e <pattern>...] [--recurse-submodules] [--parent-basename <basename>] + [--scope=(sparse|all)] [ [--[no-]exclude-standard] [--cached | --no-index | --untracked] | <tree>...] [--] [<pathspec>...] @@ -296,6 +297,29 @@ question doesn't support them. Do not output matched lines; instead, exit with status 0 when there is a match and with non-zero status when there isn't. +--scope=(sparse|all):: + Restrict or not restrict grep path scope in sparse specification. + The variants are as follows: + ++ +-- +`sparse`;; + When grep in commit history, restrict the scope of file path + to the sparse specification. See sparse specification in + link:technical/sparse-checkout.html [the sparse-checkout design + document] for more information. +`all`;; + When grep in commit history, the file path scope is full-tree. + This is consistent with the current default behavior. +-- ++ + +Note that `--scope` option only take effect if git command specify `<tree>`. + +The behavior of this `--scope` option is experimental and may change +in the future. See link:technical/sparse-checkout.html [the sparse-checkout +design document] for more information. + <tree>...:: Instead of searching tracked files in the working tree, search blobs in the given trees. diff --git a/builtin/grep.c b/builtin/grep.c index f7821c5fbba..8f7944fb924 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -640,6 +640,15 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, } strbuf_add(base, entry.path, te_len); + if (opt->scope == SPARSE_SCOPE_SPARSE && + base->len != tn_len && + !path_in_sparse_patterns(base->buf + tn_len, + S_ISDIR(entry.mode) || + S_ISGITLINK(entry.mode))) { + strbuf_setlen(base, old_baselen); + continue; + } + if (S_ISREG(entry.mode)) { hit |= grep_oid(opt, &entry.oid, base->buf, tn_len, @@ -999,6 +1008,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) PARSE_OPT_NOCOMPLETE), OPT_INTEGER('m', "max-count", &opt.max_count, N_("maximum number of results per file")), + OPT_SPARSE_SCOPE(&opt.scope), OPT_END() }; grep_prefix = prefix; diff --git a/grep.h b/grep.h index 6075f997e68..05010d4b166 100644 --- a/grep.h +++ b/grep.h @@ -22,6 +22,7 @@ typedef int pcre2_general_context; #endif #include "thread-utils.h" #include "userdiff.h" +#include "cache.h" struct repository; @@ -175,6 +176,7 @@ struct grep_opt { void (*output)(struct grep_opt *opt, const void *data, size_t size); void *output_priv; + enum sparse_scope scope; }; #define GREP_OPT_INIT { \ diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh index e6ec8e8c1e4..c8f68fc7afa 100755 --- a/t/t1090-sparse-checkout-scope.sh +++ b/t/t1090-sparse-checkout-scope.sh @@ -382,4 +382,31 @@ M in test_cmp expected actual ' +# git grep TREE + +test_expect_success 'git grep --scope=all' ' + reset_sparse_checkout_state && + cat >expected <<-EOF && +HEAD~:in/1 +HEAD~:out1/1 +HEAD~:out1/2 +HEAD~:out1/3 +HEAD~:out1/4 +HEAD~:out1/5 +HEAD~:out1/6 +HEAD~:out2/1 + EOF + git -C repo grep --name-only --scope=all 1 HEAD~ >actual && + test_cmp expected actual +' + +test_expect_success 'git grep --scope=sparse' ' + reset_sparse_checkout_state && + cat >expected <<-EOF && +HEAD~:in/1 + EOF + git -C repo grep --name-only --scope=sparse 1 HEAD~ >actual && + test_cmp expected actual +' + test_done -- gitgitgadget