Subject: Re: [PATCH v5 00/44] Make git-am a builtin

From: Paul Tan <[email-masked]>
Date: Wed, 8 Jul 2015 16:19:02 +0800

On Wed, Jul 08, 2015 at 12:48:06AM -0700, Junio C Hamano wrote:
> Junio C Hamano <[email-masked]> writes:
> $ git am -s ./+dt
> ...
> error: patch failed: builtin/update-ref.c:421
> error: builtin/update-ref.c: patch does not apply
> Patch failed at 0007 update-ref and tag: add --create-reflog arg
> The copy of the patch that failed is found in:.git/rebase-apply/patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
> $ git am -3
> git: builtin/am.c:1332: parse_mail: Assertion `!state->author_name'
> failed.
> Aborted (core dumped)

Ah, it's because parse_mail() does not expect to be called while the
authorship and commit msg fields have been filled up. This is a wrong
assumption, of course.

So the fix would be to remove the assert()s, as follows:

diff --git a/builtin/am.c b/builtin/am.c
index c548129..ab560ab 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1327,16 +1327,20 @@ static int parse_mail(struct am_state *state, const char *mail)
 	if (state->append_signoff)
 		append_signoff(&msg, 0, 0);
 
-	assert(!state->author_name);
+	if (state->author_name)
+		free(state->author_name);
 	state->author_name = strbuf_detach(&author_name, NULL);
 
-	assert(!state->author_email);
+	if (state->author_email)
+		free(state->author_email);
 	state->author_email = strbuf_detach(&author_email, NULL);
 
-	assert(!state->author_date);
+	if (state->author_date)
+		free(state->author_date);
 	state->author_date = strbuf_detach(&author_date, NULL);
 
-	assert(!state->msg);
+	if (state->msg)
+		free(state->msg);
 	state->msg = strbuf_detach(&msg, &state->msg_len);
 
 finish:
@@ -1392,7 +1396,9 @@ static void get_commit_info(struct am_state *state, struct commit *commit)
 		die(_("invalid ident line: %s"), sb.buf);
 	}
 
-	assert(!state->author_name);
+	if (state->author_name)
+		free(state->author_name);
+
 	if (ident_split.name_begin) {
 		strbuf_add(&sb, ident_split.name_begin,
 			ident_split.name_end - ident_split.name_begin);
@@ -1400,7 +1406,9 @@ static void get_commit_info(struct am_state *state, struct commit *commit)
 	} else
 		state->author_name = xstrdup("");
 
-	assert(!state->author_email);
+	if (state->author_email)
+		free(state->author_email);
+
 	if (ident_split.mail_begin) {
 		strbuf_add(&sb, ident_split.mail_begin,
 			ident_split.mail_end - ident_split.mail_begin);
@@ -1410,13 +1418,17 @@ static void get_commit_info(struct am_state *state, struct commit *commit)
 
 	author_date = show_ident_date(&ident_split, DATE_NORMAL);
 	strbuf_addstr(&sb, author_date);
-	assert(!state->author_date);
+
+	if (state->author_date)
+		free(state->author_date);
 	state->author_date = strbuf_detach(&sb, NULL);
 
-	assert(!state->msg);
 	msg = strstr(buffer, "\n\n");
 	if (!msg)
 		die(_("unable to parse commit %s"), sha1_to_hex(commit->object.sha1));
+
+	if (state->msg)
+		free(state->msg);
 	state->msg = xstrdup(msg + 2);
 	state->msg_len = strlen(state->msg);
 }