Constantine Plotnikov <constantine.plotnikov@xxxxxxxxx> 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) -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html