Re: Q: supplying large sets of path to git commands
From: Junio C Hamano <hidden>
Date: 2016-06-15 22:47:34
Subsystem:
documentation, the rest · Maintainers:
Jonathan Corbet, Linus Torvalds
Possibly related (same subject, not in this thread)
- 2016-06-15 · Q: supplying large sets of path to git commands · Constantine Plotnikov <hidden>
Constantine Plotnikov [off-list ref] writes:
Some git commands like git check-attr supports receiving paths from stdin.
Here is how one might implement it for diff/log family of commands that
use "setup_revisions()".
I didn't test it (of course) beyond running
./git diff --name-only HEAD | ./git diff --stdin-paths --stat -p
in order to include the patch text in this message, and running
./git diff --name-only | ./git log --stdin-paths --no-merges --stat
---
Documentation/git-rev-list.txt | 1 +
Documentation/rev-list-options.txt | 7 ++++
revision.c | 59 +++++++++++++++++++++++++++++++++--
3 files changed, 63 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 3341d1b..8fa276c 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt@@ -46,6 +46,7 @@ SYNOPSIS [ \--reverse ] [ \--walk-reflogs ] [ \--no-walk ] [ \--do-walk ] + [ \--stdin-paths | \--stdin-paths-z ] <commit>... [ \-- <paths>... ] DESCRIPTION
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index bf66116..9960de8 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt@@ -317,6 +317,13 @@ The following options select the commits to be shown: Commits modifying the given <paths> are selected. +--stdin-paths:: +--stdin-paths-z:: + + Additionally read <paths> (see above) from the standard input, + one path per line terminated with linefeed (or NUL when + --stdin-paths-z is used). + --simplify-by-decoration:: Commits that are referred by some branch or tag are selected.
diff --git a/revision.c b/revision.c
index 9fc4e8d..4caccdb 100644
--- a/revision.c
+++ b/revision.c@@ -1218,6 +1218,38 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx, ctx->argc -= n; } +enum append_stdin_mode { + APPEND_STDIN = 1, + APPEND_STDIN_Z = 2, +}; + +static const char **grab_pathspec(const char *prefix, const char **argv, + enum append_stdin_mode append_stdin) +{ + const char **nargv; + int cnt, alloc, term; + struct strbuf line = STRBUF_INIT; + + if (!append_stdin) + return get_pathspec(prefix, argv); + + for (cnt = 0; argv[cnt]; cnt++) + ; /* first count */ + alloc = alloc_nr(cnt); + nargv = xmalloc(sizeof(*nargv) * alloc); + for (cnt = 0; argv[cnt]; cnt++) + nargv[cnt] = argv[cnt]; /* then copy */ + + term = (append_stdin == APPEND_STDIN_Z) ? '\0' : '\n'; + while (strbuf_getline(&line, stdin, term) != EOF) { + ALLOC_GROW(nargv, cnt, alloc); + nargv[cnt++] = strbuf_detach(&line, NULL); + } + ALLOC_GROW(nargv, cnt, alloc); + nargv[cnt] = NULL; + return get_pathspec(prefix, nargv); +} + /* * Parse revision information, filling in the "rev_info" structure, * and removing the used arguments from the argument list.
@@ -1228,17 +1260,26 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx, int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def) { int i, flags, left, seen_dashdash; + enum append_stdin_mode append_stdin = 0; - /* First, search for "--" */ + /* First, search for "--", "--stdin-paths", and "--stdin-paths-z" */ seen_dashdash = 0; for (i = 1; i < argc; i++) { const char *arg = argv[i]; + + if (!strcmp(arg, "--stdin-paths")) + append_stdin = APPEND_STDIN; + else if (!strcmp(arg, "--stdin-paths-z")) + append_stdin = APPEND_STDIN_Z; + if (strcmp(arg, "--")) continue; argv[i] = NULL; argc = i; if (argv[i + 1]) - revs->prune_data = get_pathspec(revs->prefix, argv + i + 1); + revs->prune_data = grab_pathspec(revs->prefix, + argv + i + 1, + append_stdin); seen_dashdash = 1; break; }
@@ -1283,6 +1324,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->no_walk = 0; continue; } + if (!strcmp(arg, "--stdin-paths") || + !strcmp(arg, "--stdin-paths-z")) + continue; /* already handled */ opts = handle_revision_opt(revs, argc - i, argv + i, &left, argv); if (opts > 0) {
@@ -1308,12 +1352,19 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch for (j = i; j < argc; j++) verify_filename(revs->prefix, argv[j]); - revs->prune_data = get_pathspec(revs->prefix, - argv + i); + revs->prune_data = grab_pathspec(revs->prefix, + argv + i, + append_stdin); break; } } + if (!revs->prune_data && append_stdin) { + const char *empty_argv[1] = { NULL }; + revs->prune_data = grab_pathspec(revs->prefix, empty_argv, + append_stdin); + } + if (revs->def == NULL) revs->def = def; if (revs->show_merge)