Re: Q: supplying large sets of path to git commands

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]