Re: [PATCH v2] grep: support the --pathspec-from-file option
- From
Junio C Hamano <gitster@pobox.com>
- Date
- Dec 4, 2019, 22:24 UTC
- Message-ID
- <xmqq5ziv3f20.fsf@gitster-ct.c.googlers.com>
- In-Reply-To
- <20191204203911.237056-1-emilyshaffer@google.com>
Emily Shaffer <emilyshaffer@google.com> writes:
Show 14 quoted lines
> Teach 'git grep' to use OPT_PATHSPEC_FROM_FILE and update the > documentation accordingly. > > This changes enables 'git grep' to receive the pathspec from a file by > specifying the path, or from stdin by specifying '-' as the path. This > matches the previous functionality of '-f', so the documentation of '-f' > has been expanded to describe this functionality. To let '-f' match the > new '--pathspec-from-file' option, also teach a '--patterns-from-file' > long name to '-f'. > > Since there are now two arguments which can attempt to read from stdin, > add a safeguard to check whether the user specified '-' for both of > them. It is still possible for a user to pass '/dev/stdin' to one or > both arguments at present; we do not explicitly check.
OK. I guess this is good enough at least for now and possibly forever as that falls into the "doctor, it hurts when I do this" category.
> Refactored to use am/pathspec-from-file. This changes the implementation > significantly since v1, but the testcases mostly remain the same.
I am hoping that this topic, and Alexandr's "add" and "checkout" stuff, would help establishing a good pattern for other commands to follow.
Show 10 quoted lines
> diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt > index c89fb569e3..56b1c5a302 100644 > --- a/Documentation/git-grep.txt > +++ b/Documentation/git-grep.txt > @@ -24,7 +24,8 @@ SYNOPSIS > [-A <post-context>] [-B <pre-context>] [-C <context>] > [-W | --function-context] > [--threads <num>] > - [-f <file>] [-e] <pattern> > + [-f | --patterns-from-file <file>] [-e] <pattern>
OK.
> + [--pathspec-from-file=<file> [--pathspec-file-nul]]
OK.
Show 9 quoted lines
> @@ -270,7 +271,10 @@ providing this option will cause it to die. > See `grep.threads` in 'CONFIGURATION' for more information. > > -f <file>:: > - Read patterns from <file>, one per line. > +--patterns-from-file <file>:: > + Read patterns from <file>, one per line. If `<file>` is exactly `-` then > + standard input is used; standard input cannot be used for both > + --patterns-from-file and --pathspec-from-file.
Makes sense---otherwise they would compete and we cannot know which kind each line in the standard input is ;-)
Show 18 quoted lines
> @@ -289,6 +293,20 @@ In future versions we may learn to support patterns containing \0 for > more search backends, until then we'll die when the pattern type in > question doesn't support them. > > +--pathspec-from-file <file>:: > + Read pathspec from <file> instead of the command line. If `<file>` is > + exactly `-` then standard input is used; standard input cannot be used > + for both --patterns-from-file and --pathspec-from-file. Pathspec elements > + are separated by LF or CR/LF. Pathspec elements can be quoted as > + explained for the configuration variable `core.quotePath` (see > + linkgit:git-config[1]). See also `--pathspec-file-nul` and global > + `--literal-pathspecs`. > + > +--pathspec-file-nul:: > + Only meaningful with `--pathspec-from-file`. Pathspec elements are > + separated with NUL character and all other characters are taken > + literally (including newlines and quotes). > +
I think these matches the ones in git-reset.txt from the earlier work by Alexandr's, which is good.
Show 15 quoted lines
> diff --git a/builtin/grep.c b/builtin/grep.c
> index 50ce8d9461..54ba991c42 100644
> --- a/builtin/grep.c
> +++ b/builtin/grep.c
> @@ -31,6 +31,7 @@ static char const * const grep_usage[] = {
> };
>
> static int recurse_submodules;
> +static int patterns_from_stdin, pathspec_from_stdin;
>
> #define GREP_NUM_THREADS_DEFAULT 8
> static int num_threads;
> @@ -723,15 +724,18 @@ static int context_callback(const struct option *opt, const char *arg,
> static int file_callback(const struct option *opt, const char *arg, int unset)
> {Shouldn't this be renamed? Earlier, the only thing that can be taken from a file was the patterns, but now a file can be given to specify a set of pathspec elements. "patterns_file_callback()" or something like taht?
Show 11 quoted lines
> struct grep_opt *grep_opt = opt->value; > - int from_stdin; > FILE *patterns; > int lno = 0; > struct strbuf sb = STRBUF_INIT; > > BUG_ON_OPT_NEG(unset); > > - from_stdin = !strcmp(arg, "-"); > - patterns = from_stdin ? stdin : fopen(arg, "r"); > + patterns_from_stdin = !strcmp(arg, "-");
Totally outside the scope of this patch, but we may want to introduce
int is_stdin_cmdline_marker(const char *arg)
{
return !strcmp(arg, "-");
}which later can be taught also about "/dev/stdin". Even outside the pathspec-from-file option, I think "diff --no-index" also has some special-case provision for treating "-" as "input coming from the standard input string", which would benefit from such a helper.
> + if (patterns_from_stdin && pathspec_from_stdin)
> + die(_("cannot specify both patterns and pathspec via stdin"));It's kind of sad that we need to check this in this callback and also inside cmd_grep() top-level we will see further down...
Show 8 quoted lines
> + if (pathspec_from_file) {
> + if (pathspec.nr)
> + die(_("--pathspec-from-file is incompatible with pathspec arguments"));
> +
> + pathspec_from_stdin = !strcmp(pathspec_from_file, "-");
> +
> + if (patterns_from_stdin && pathspec_from_stdin)
> + die(_("cannot specify both patterns and pathspec via stdin"));... here.
Thanks.