diff mbox series

[4/8] builtin/commit-graph.c: extract 'read_one_commit()'

Message ID 9ae8745dc090de37af0475ab12b79d541a52713d.1588641176.git.me@ttaylorr.com (mailing list archive)
State New, archived
Headers show
Series commit-graph: drop CHECK_OIDS, peel in callers | expand

Commit Message

Taylor Blau May 5, 2020, 1:13 a.m. UTC
With either '--stdin-commits' or '--stdin-packs', the commit-graph
builtin will read line-delimited input, and interpret it either as a
series of commit OIDs, or pack names.

In a subsequent commit, we will begin handling '--stdin-commits'
differently by processing each line as it comes in, instead of in one
shot at the end. To make adequate room for this additional logic, split
the '--stdin-commits' case from '--stdin-packs' by only storing the
input when '--stdin-packs' is given.

In the case of '--stdin-commits', feed each line to a new
'read_one_commit' helper, which (for now) will merely call
'parse_oid_hex'.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
 builtin/commit-graph.c | 54 +++++++++++++++++++++++-------------------
 1 file changed, 29 insertions(+), 25 deletions(-)

Comments

Jeff King May 7, 2020, 8:03 p.m. UTC | #1
On Mon, May 04, 2020 at 07:13:46PM -0600, Taylor Blau wrote:

> In the case of '--stdin-commits', feed each line to a new
> 'read_one_commit' helper, which (for now) will merely call
> 'parse_oid_hex'.

Makes sense.

> +static int read_one_commit(struct oidset *commits, char *hash)

This could be "const char *hash", couldn't it?

> +	struct object_id oid;
> +	const char *end;
> +
> +	if (parse_oid_hex(hash, &oid, &end)) {
> +		error(_("unexpected non-hex object ID: %s"), hash);
> +		return 1;
> +	}

Returning "-1" for error is more idiomatic in our code base (though I
know some of the commit-graph code doesn't follow that, I think we
should slowly try to move it back in the other direction.

> +		while (strbuf_getline(&buf, stdin) != EOF) {
> +			char *line = strbuf_detach(&buf, NULL);
> +			if (opts.stdin_commits) {
> +				int result = read_one_commit(&commits, line);
> +				if (result)
> +					return result;
> +			} else
> +				string_list_append(&pack_indexes, line);
> +		}

This leaks "line" for each commit in stdin_commits mode (it used to get
added to a string list). I think you want:

  while (strbuf_getline(&buf, stdin) != EOF) {
        if (opts.stdin_commits) {
	        if (read_one_commit(&commits, buf.buf)) {
			strbuf_release(&buf);
			return 1;
		}
	} else {
	        string_list_append(&pack_indexes, strbuf_detach(&buf));
	}
  }

Though I think it might be easier to follow if each mode simply has its
own while loop.

> +
>  		UNLEAK(buf);

Not new in your patch, but this UNLEAK() has always bugged me. ;) Why
not just strbuf_release() it?

-Peff
Taylor Blau May 13, 2020, 8:01 p.m. UTC | #2
On Thu, May 07, 2020 at 04:03:05PM -0400, Jeff King wrote:
> On Mon, May 04, 2020 at 07:13:46PM -0600, Taylor Blau wrote:
>
> > In the case of '--stdin-commits', feed each line to a new
> > 'read_one_commit' helper, which (for now) will merely call
> > 'parse_oid_hex'.
>
> Makes sense.
>
> > +static int read_one_commit(struct oidset *commits, char *hash)
>
> This could be "const char *hash", couldn't it?

Yep, thanks.

> > +	struct object_id oid;
> > +	const char *end;
> > +
> > +	if (parse_oid_hex(hash, &oid, &end)) {
> > +		error(_("unexpected non-hex object ID: %s"), hash);
> > +		return 1;
> > +	}
>
> Returning "-1" for error is more idiomatic in our code base (though I
> know some of the commit-graph code doesn't follow that, I think we
> should slowly try to move it back in the other direction.

Yeah, I know the -1 is more idiomatic than what I had written here. This
was done so that I could use the return value from 'read_one_commit' as
an exit code from 'graph_write()', but I don't mind switching this to
'return error(...)' and then checking at the caller for a non-zero
return value and returning 1 there instead.

> > +		while (strbuf_getline(&buf, stdin) != EOF) {
> > +			char *line = strbuf_detach(&buf, NULL);
> > +			if (opts.stdin_commits) {
> > +				int result = read_one_commit(&commits, line);
> > +				if (result)
> > +					return result;
> > +			} else
> > +				string_list_append(&pack_indexes, line);
> > +		}
>
> This leaks "line" for each commit in stdin_commits mode (it used to get
> added to a string list). I think you want:
>
>   while (strbuf_getline(&buf, stdin) != EOF) {
>         if (opts.stdin_commits) {
> 	        if (read_one_commit(&commits, buf.buf)) {
> 			strbuf_release(&buf);
> 			return 1;
> 		}
> 	} else {
> 	        string_list_append(&pack_indexes, strbuf_detach(&buf));
> 	}
>   }
>
> Though I think it might be easier to follow if each mode simply has its
> own while loop.

Yeah, it's much clearer as two separate cases. I'll send something like
that shortly once I get to the rest of your review.

> > +
> >  		UNLEAK(buf);
>
> Not new in your patch, but this UNLEAK() has always bugged me. ;) Why
> not just strbuf_release() it?

I snuck it in! ;)

> -Peff

Thanks,
Taylor
diff mbox series

Patch

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 15fe60317c..f550d8489a 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -138,12 +138,25 @@  static int write_option_parse_split(const struct option *opt, const char *arg,
 	return 0;
 }
 
+static int read_one_commit(struct oidset *commits, char *hash)
+{
+	struct object_id oid;
+	const char *end;
+
+	if (parse_oid_hex(hash, &oid, &end)) {
+		error(_("unexpected non-hex object ID: %s"), hash);
+		return 1;
+	}
+
+	oidset_insert(commits, &oid);
+	return 0;
+}
+
 static int graph_write(int argc, const char **argv)
 {
-	struct string_list *pack_indexes = NULL;
+	struct string_list pack_indexes;
 	struct oidset commits = OIDSET_INIT;
 	struct object_directory *odb = NULL;
-	struct string_list lines;
 	int result = 0;
 	enum commit_graph_write_flags flags = 0;
 
@@ -209,44 +222,35 @@  static int graph_write(int argc, const char **argv)
 		return 0;
 	}
 
-	string_list_init(&lines, 0);
+	string_list_init(&pack_indexes, 0);
 	if (opts.stdin_packs || opts.stdin_commits) {
 		struct strbuf buf = STRBUF_INIT;
-
-		while (strbuf_getline(&buf, stdin) != EOF)
-			string_list_append(&lines, strbuf_detach(&buf, NULL));
-
-		if (opts.stdin_packs)
-			pack_indexes = &lines;
 		if (opts.stdin_commits) {
-			struct string_list_item *item;
-			oidset_init(&commits, lines.nr);
-			for_each_string_list_item(item, &lines) {
-				struct object_id oid;
-				const char *end;
-
-				if (parse_oid_hex(item->string, &oid, &end)) {
-					error(_("unexpected non-hex object ID: "
-						"%s"), item->string);
-					return 1;
-				}
-
-				oidset_insert(&commits, &oid);
-			}
+			oidset_init(&commits, 0);
 			flags |= COMMIT_GRAPH_WRITE_CHECK_OIDS;
 		}
 
+		while (strbuf_getline(&buf, stdin) != EOF) {
+			char *line = strbuf_detach(&buf, NULL);
+			if (opts.stdin_commits) {
+				int result = read_one_commit(&commits, line);
+				if (result)
+					return result;
+			} else
+				string_list_append(&pack_indexes, line);
+		}
+
 		UNLEAK(buf);
 	}
 
 	if (write_commit_graph(odb,
-			       pack_indexes,
+			       opts.stdin_packs ? &pack_indexes : NULL,
 			       opts.stdin_commits ? &commits : NULL,
 			       flags,
 			       &split_opts))
 		result = 1;
 
-	UNLEAK(lines);
+	UNLEAK(pack_indexes);
 	return result;
 }