git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>, "Jeff King" <peff@peff.net>,
	"Jiang Xin" <zhiyou.jx@alibaba-inc.com>,
	"Emily Shaffer" <emilyshaffer@google.com>,
	"Jonathan Tan" <jonathantanmy@google.com>,
	"Taylor Blau" <me@ttaylorr.com>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: [PATCH v3 3/4] pack-objects.c: do stdin parsing via revision.c's API
Date: Mon, 21 Jun 2021 17:10:15 +0200	[thread overview]
Message-ID: <patch-3.4-943b1b4c12a-20210621T150651Z-avarab@gmail.com> (raw)
In-Reply-To: <cover-0.4-00000000000-20210621T150651Z-avarab@gmail.com>

Extend the rev_info stdin parsing API to support hooking into its
read_revisions_from_stdin() function, and change the custom stdin
parsing in pack-objects.c to use it.

The pack-objects.c code being refactored away here was first added in
Linus's c323ac7d9c5 (git-pack-objects: create a packed object
representation., 2005-06-25).

Later on rev-list started doing similar parsing in 42cabc341c4 (Teach
rev-list an option to read revs from the standard input., 2006-09-05).
That code was promoted to a more general API in 1fc561d169a (Move
read_revisions_from_stdin from builtin-rev-list.c to revision.c,
2008-07-05).

Since then the API in revision.c has received improvements that have
been missed here. E.g. the arbitrary limit of 1000 bytes was removed
in 63d564b3002 (read_revision_from_stdin(): use strbuf, 2009-11-20),
and it moved to a more simpler strbuf API in 6e8d46f9d4b (revision:
read --stdin with strbuf_getline(), 2015-10-28).

Let's do the same here, as in 6e8d46f9d4b we can remove the "if (len
&& line[len - 1] == '\n')" check, it's now redundant to using
strbuf_getline(), and we get to skip the whole
"warn_on_object_refname_ambiguity" dance. The
read_revisions_from_stdin() function in revision.c we're now using
does it for us.

For now there isn't all that much point in this whole exercises. We
just end up calling setup_revisions() to loop over stdin for us, but
the callback we define makes no use of REV_INFO_STDIN_LINE_PROCESS, we
still need to call handle_revision_arg() ourselves because we'd like
to call it with different flags.

This very light use of the API will be further refined in a subsequent
commit, for now we're just doing the bare minimum to move this
existing code over to the new callback pattern without any functional
changes, and making it as friendly to "git show -w" and "the
--color-moved-ws=allow-indentation-change" mode as possible.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/pack-objects.c | 63 ++++++++++++++++++++----------------------
 revision.c             | 22 +++++++++++++++
 revision.h             | 30 ++++++++++++++++++++
 3 files changed, 82 insertions(+), 33 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index a4e2ae059c0..f8cae6c305a 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3755,15 +3755,40 @@ static void mark_bitmap_preferred_tips(void)
 	}
 }
 
+static enum rev_info_stdin_line get_object_list_handle_stdin_line(
+	struct rev_info *revs, struct strbuf *line_sb, void *stdin_line_priv)
+{
+	int *flags = stdin_line_priv;
+	char *line = line_sb->buf;
+
+	if (*line == '-') {
+		if (!strcmp(line, "--not")) {
+			*flags ^= UNINTERESTING;
+			write_bitmap_index = 0;
+			return REV_INFO_STDIN_LINE_CONTINUE;
+		}
+		if (starts_with(line, "--shallow ")) {
+			struct object_id oid;
+			if (get_oid_hex(line + 10, &oid))
+				die("not an object name '%s'", line + 10);
+			register_shallow(the_repository, &oid);
+			use_bitmap_index = 0;
+			return REV_INFO_STDIN_LINE_CONTINUE;
+		}
+		die(_("not a rev '%s'"), line);
+	}
+	if (handle_revision_arg(line, revs, *flags, REVARG_CANNOT_BE_FILENAME))
+			die(_("bad revision '%s'"), line);
+	return REV_INFO_STDIN_LINE_CONTINUE;
+}
+
 static void get_object_list(int ac, const char **av)
 {
 	struct rev_info revs;
 	struct setup_revision_opt s_r_opt = {
 		.allow_exclude_promisor_objects = 1,
 	};
-	char line[1000];
 	int flags = 0;
-	int save_warning;
 
 	repo_init_revisions(the_repository, &revs, NULL);
 	save_commit_buffer = 0;
@@ -3771,39 +3796,11 @@ static void get_object_list(int ac, const char **av)
 	/* make sure shallows are read */
 	is_repository_shallow(the_repository);
 
+	revs.stdin_handling = REV_INFO_STDIN_ALWAYS_READ;
+	revs.handle_stdin_line = get_object_list_handle_stdin_line;
+	revs.stdin_line_priv = &flags;
 	setup_revisions(ac, av, &revs, &s_r_opt);
 
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
-
-	while (fgets(line, sizeof(line), stdin) != NULL) {
-		int len = strlen(line);
-		if (len && line[len - 1] == '\n')
-			line[--len] = 0;
-		if (!len)
-			break;
-		if (*line == '-') {
-			if (!strcmp(line, "--not")) {
-				flags ^= UNINTERESTING;
-				write_bitmap_index = 0;
-				continue;
-			}
-			if (starts_with(line, "--shallow ")) {
-				struct object_id oid;
-				if (get_oid_hex(line + 10, &oid))
-					die("not an object name '%s'", line + 10);
-				register_shallow(the_repository, &oid);
-				use_bitmap_index = 0;
-				continue;
-			}
-			die(_("not a rev '%s'"), line);
-		}
-		if (handle_revision_arg(line, &revs, flags, REVARG_CANNOT_BE_FILENAME))
-			die(_("bad revision '%s'"), line);
-	}
-
-	warn_on_object_refname_ambiguity = save_warning;
-
 	if (use_bitmap_index && !get_object_list_from_bitmap(&revs))
 		return;
 
diff --git a/revision.c b/revision.c
index a65f9b89e99..f55b3a1caf4 100644
--- a/revision.c
+++ b/revision.c
@@ -2119,6 +2119,19 @@ static void read_revisions_from_stdin(struct rev_info *revs,
 		int len = sb.len;
 		if (!len)
 			break;
+
+		if (revs->handle_stdin_line) {
+			enum rev_info_stdin_line ret = revs->handle_stdin_line(
+				revs, &sb, revs->stdin_line_priv);
+
+			switch (ret) {
+			case REV_INFO_STDIN_LINE_PROCESS:
+				break;
+			case REV_INFO_STDIN_LINE_CONTINUE:
+				continue;
+			}
+		}
+
 		if (sb.buf[0] == '-') {
 			if (len == 2 && sb.buf[1] == '-') {
 				seen_dashdash = 1;
@@ -2742,6 +2755,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 
 			if (!strcmp(arg, "--stdin")) {
 				switch (revs->stdin_handling) {
+				case REV_INFO_STDIN_ALWAYS_READ:
 				case REV_INFO_STDIN_IGNORE:
 					argv[left++] = arg;
 					continue;
@@ -2789,6 +2803,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 		}
 	}
 
+	/*
+	 * We're asked to ALWAYS_READ from stdin, but no --stdin
+	 * option (or "consumed_stdin" would be set).
+	 */
+	if (!revs->consumed_stdin &&
+	    revs->stdin_handling == REV_INFO_STDIN_ALWAYS_READ)
+		read_revisions_from_stdin(revs, &prune_data);
+
 	if (prune_data.nr) {
 		/*
 		 * If we need to introduce the magic "a lone ':' means no
diff --git a/revision.h b/revision.h
index 79a3421cd1f..ff7994bb13d 100644
--- a/revision.h
+++ b/revision.h
@@ -89,8 +89,17 @@ struct topo_walk_info;
 enum rev_info_stdin {
 	REV_INFO_STDIN_CONSUME_ON_OPTION = 0,
 	REV_INFO_STDIN_IGNORE,
+	REV_INFO_STDIN_ALWAYS_READ,
 };
 
+enum rev_info_stdin_line {
+	REV_INFO_STDIN_LINE_PROCESS,
+	REV_INFO_STDIN_LINE_CONTINUE,
+};
+
+typedef enum rev_info_stdin_line (*rev_info_stdin_line_func)(
+	struct rev_info *revs, struct strbuf *line, void *stdin_line_priv);
+
 struct rev_info {
 	/* Starting list */
 	struct commit_list *commits;
@@ -126,6 +135,9 @@ struct rev_info {
 	 *
 	 * Can be set to REV_INFO_STDIN_IGNORE to ignore the --stdin
 	 * option.
+	 *
+	 * Set it to REV_INFO_STDIN_ALWAYS_READ if there's always data
+	 * on stdin to be read, even if no --stdin option is provided.
 	 */
 	enum rev_info_stdin stdin_handling;
 
@@ -136,6 +148,24 @@ struct rev_info {
 	 */
 	int consumed_stdin;
 
+	/*
+	 * When reading from stdin (see "stdin_handling" above) define
+	 * a handle_stdin_line function to consume the lines.
+	 *
+	 * - Return REV_INFO_STDIN_LINE_PROCESS to continue
+	 *   revision.c's normal processing of the line (after
+	 *   possibly munging the provided strbuf).
+	 *
+	 * - Return REV_INFO_STDIN_LINE_CONTINUE to indicate that the
+	 *   line is fully processed, moving onto the next line (if
+	 *   any)
+	 *
+	 * Use the "stdin_line_priv" to optionally pass your own data
+	 * around.
+	 */
+	rev_info_stdin_line_func handle_stdin_line;
+	void *stdin_line_priv;
+
 	/* topo-sort */
 	enum rev_sort_order sort_order;
 
-- 
2.32.0.599.g3967b4fa4ac


  parent reply	other threads:[~2021-06-21 15:10 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-08 12:16 [PATCH 0/4] pack-objects: use revision.c's --stdin parsing Ævar Arnfjörð Bjarmason
2021-06-08 12:16 ` [PATCH 1/4] upload-pack: run is_repository_shallow() before setup_revisions() Ævar Arnfjörð Bjarmason
2021-06-08 12:16 ` [PATCH 2/4] revision.h: unify "disable_stdin" and "read_from_stdin" Ævar Arnfjörð Bjarmason
2021-06-08 12:16 ` [PATCH 3/4] pack-objects.c: do stdin parsing via revision.c's API Ævar Arnfjörð Bjarmason
2021-06-09  8:10   ` Junio C Hamano
2021-06-08 12:16 ` [PATCH 4/4] pack-objects.c: make use of REV_INFO_STDIN_LINE_PROCESS Ævar Arnfjörð Bjarmason
2021-06-17 10:57 ` [PATCH v2 0/4] pack-objects: use revision.c's --stdin parsing Ævar Arnfjörð Bjarmason
2021-06-17 10:57   ` [PATCH v2 1/4] upload-pack: run is_repository_shallow() before setup_revisions() Ævar Arnfjörð Bjarmason
2021-06-17 10:57   ` [PATCH v2 2/4] revision.h: unify "disable_stdin" and "read_from_stdin" Ævar Arnfjörð Bjarmason
2021-06-17 23:44     ` Emily Shaffer
2021-06-18 17:54     ` Jonathan Tan
2021-06-17 10:57   ` [PATCH v2 3/4] pack-objects.c: do stdin parsing via revision.c's API Ævar Arnfjörð Bjarmason
2021-06-18 18:57     ` Jonathan Tan
2021-06-17 10:57   ` [PATCH v2 4/4] pack-objects.c: make use of REV_INFO_STDIN_LINE_PROCESS Ævar Arnfjörð Bjarmason
2021-06-21 15:10   ` [PATCH v3 0/4] pack-objects: use revision.c's --stdin parsing Ævar Arnfjörð Bjarmason
2021-06-21 15:10     ` [PATCH v3 1/4] upload-pack: run is_repository_shallow() before setup_revisions() Ævar Arnfjörð Bjarmason
2021-06-21 15:10     ` [PATCH v3 2/4] revision.h: refactor "disable_stdin" and "read_from_stdin" Ævar Arnfjörð Bjarmason
2021-07-08 22:10       ` Junio C Hamano
2021-06-21 15:10     ` Ævar Arnfjörð Bjarmason [this message]
2021-07-08 22:21       ` [PATCH v3 3/4] pack-objects.c: do stdin parsing via revision.c's API Junio C Hamano
2021-06-21 15:10     ` [PATCH v3 4/4] pack-objects.c: make use of REV_INFO_STDIN_LINE_PROCESS Ævar Arnfjörð Bjarmason
2021-07-08 22:21       ` Junio C Hamano
2021-07-09 11:06     ` [PATCH v4 0/5] revision.[ch]: add --stdin parsing API, use in pack-objects Ævar Arnfjörð Bjarmason
2021-07-09 11:06       ` [PATCH v4 1/5] upload-pack: run is_repository_shallow() before setup_revisions() Ævar Arnfjörð Bjarmason
2021-07-09 11:06       ` [PATCH v4 2/5] revision.h: refactor "disable_stdin" and "read_from_stdin" Ævar Arnfjörð Bjarmason
2021-07-09 20:17         ` Junio C Hamano
2021-07-09 11:06       ` [PATCH v4 3/5] revision.[ch]: add a "handle_stdin_line" API Ævar Arnfjörð Bjarmason
2021-07-09 11:06       ` [PATCH v4 4/5] pack-objects.c: do stdin parsing via revision.c's API Ævar Arnfjörð Bjarmason
2021-07-09 11:06       ` [PATCH v4 5/5] pack-objects.c: make use of REV_INFO_STDIN_LINE_PROCESS Ævar Arnfjörð Bjarmason
2021-07-26 12:46       ` [PATCH v5 0/5] add --stdin parsing API, use in pack-objects Ævar Arnfjörð Bjarmason
2021-07-26 12:46         ` [PATCH v5 1/5] upload-pack: run is_repository_shallow() before setup_revisions() Ævar Arnfjörð Bjarmason
2021-07-26 12:46         ` [PATCH v5 2/5] revision.h: refactor "disable_stdin" and "read_from_stdin" Ævar Arnfjörð Bjarmason
2021-07-26 12:46         ` [PATCH v5 3/5] revision.[ch]: add a "handle_stdin_line" API Ævar Arnfjörð Bjarmason
2021-07-26 12:46         ` [PATCH v5 4/5] pack-objects.c: do stdin parsing via revision.c's API Ævar Arnfjörð Bjarmason
2021-07-26 12:46         ` [PATCH v5 5/5] pack-objects.c: make use of REV_INFO_STDIN_LINE_PROCESS Ævar Arnfjörð Bjarmason

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=patch-3.4-943b1b4c12a-20210621T150651Z-avarab@gmail.com \
    --to=avarab@gmail.com \
    --cc=emilyshaffer@google.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jonathantanmy@google.com \
    --cc=me@ttaylorr.com \
    --cc=peff@peff.net \
    --cc=zhiyou.jx@alibaba-inc.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).