Issue with empty patch detection

Signed-off-by: Nicolas Morey-Chaisemartin <[email protected]>
---
 builtin/am.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 126 insertions(+), 17 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index 92c485350..702cbf8e0 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -111,6 +111,11 @@ struct am_state {
        char *msg;
        size_t msg_len;
 
+       /* Series metadata */
+       int series_id;
+       int series_len;
+       int cover_id;
+
        /* when --rebasing, records the original commit the patch came from */
        struct object_id orig_commit;
 
@@ -131,6 +136,8 @@ struct am_state {
        int committer_date_is_author_date;
        int ignore_date;
        int allow_rerere_autoupdate;
+       int cover_at_tip;
+       int applying_cover;
        const char *sign_commit;
        int rebasing;
 };
@@ -160,6 +167,7 @@ static void am_state_init(struct am_state *state)
 
        if (!git_config_get_bool("commit.gpgsign", &gpgsign))
                state->sign_commit = gpgsign ? "" : NULL;
+
 }
 
 /**
@@ -432,6 +440,20 @@ static void am_load(struct am_state *state)
        read_state_file(&sb, state, "utf8", 1);
        state->utf8 = !strcmp(sb.buf, "t");
 
+       read_state_file(&sb, state, "cover-at-tip", 1);
+       state->cover_at_tip = !strcmp(sb.buf, "t");
+
+       if (state->cover_at_tip) {
+               read_state_file(&sb, state, "series_id", 1);
+               state->series_id = strtol(sb.buf, NULL, 10);
+
+               read_state_file(&sb, state, "series_len", 1);
+               state->series_len = strtol(sb.buf, NULL, 10);
+
+               read_state_file(&sb, state, "cover_id", 1);
+               state->cover_id = strtol(sb.buf, NULL, 10);
+       }
+
        if (file_exists(am_path(state, "rerere-autoupdate"))) {
                read_state_file(&sb, state, "rerere-autoupdate", 1);
                state->allow_rerere_autoupdate = strcmp(sb.buf, "t") ?
@@ -1020,6 +1042,7 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
        write_state_bool(state, "quiet", state->quiet);
        write_state_bool(state, "sign", state->signoff);
        write_state_bool(state, "utf8", state->utf8);
+       write_state_bool(state, "cover-at-tip", state->cover_at_tip);
 
        if (state->allow_rerere_autoupdate)
                write_state_bool(state, "rerere-autoupdate",
@@ -1076,6 +1099,12 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
                        delete_ref(NULL, "ORIG_HEAD", NULL, 0);
        }
 
+       if (state->cover_at_tip) {
+               write_state_count(state, "series_id", state->series_id);
+               write_state_count(state, "series_len", state->series_len);
+               write_state_count(state, "cover_id", state->cover_id);
+       }
+
        /*
         * NOTE: Since the "next" and "last" files determine if an am_state
         * session is in progress, they should be written last.
@@ -1088,13 +1117,9 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
 }
 
 /**
- * Increments the patch pointer, and cleans am_state for the application of the
- * next patch.
- */
-static void am_next(struct am_state *state)
+ * Cleans am_state.
+ */static void am_clean(struct am_state *state)
 {
-       struct object_id head;
-
        FREE_AND_NULL(state->author_name);
        FREE_AND_NULL(state->author_email);
        FREE_AND_NULL(state->author_date);
@@ -1106,14 +1131,6 @@ static void am_next(struct am_state *state)
 
        oidclr(&state->orig_commit);
        unlink(am_path(state, "original-commit"));
-
-       if (!get_oid("HEAD", &head))
-               write_state_text(state, "abort-safety", oid_to_hex(&head));
-       else
-               write_state_text(state, "abort-safety", "");
-
-       state->cur++;
-       write_state_count(state, "next", state->cur);
 }
 
 /**
@@ -1274,6 +1291,7 @@ static int parse_mail(struct am_state *state, const char 
*mail)
        fclose(mi.input);
        fclose(mi.output);
 
+
        /* Extract message and author information */
        fp = xfopen(am_path(state, "info"), "r");
        while (!strbuf_getline_lf(&sb, fp)) {
@@ -1298,9 +1316,30 @@ static int parse_mail(struct am_state *state, const char 
*mail)
                goto finish;
        }
 
-       if (is_empty_file(am_path(state, "patch"))) {
-               printf_ln(_("Patch is empty."));
-               die_user_resolve(state);
+       if (!state->applying_cover) {
+
+               state->series_id = mi.series_id;
+               state->series_len = mi.series_len;
+
+               if (state->cover_at_tip) {
+                       write_state_count(state, "series_id", state->series_id);
+                       write_state_count(state, "series_len", 
state->series_len);
+                       write_state_count(state, "cover_id", state->cover_id);
+               }
+
+               if (mi.series_id == 0){
+                       state->cover_id = state->cur;
+                       ret = 1;
+                       goto finish;
+               }
+
+               if (is_empty_file(am_path(state, "patch"))) {
+                               printf_ln(_("Patch is empty."));
+                               die_user_resolve(state);
+               } else if (state->cur == 1) {
+                       /* First mail is not empty. cover-at-tip cannot apply */
+                       state->cover_at_tip = 0;
+               }
        }
 
        strbuf_addstr(&msg, "\n\n");
@@ -1776,6 +1815,74 @@ static int do_interactive(struct am_state *state)
        }
 }
 
+
+/**
+ * Apply the cover letter of a patch series
+ */
+static void do_apply_cover(struct am_state *state)
+{
+       int previous_cur = state->cur;
+       const char *mail;
+
+       am_clean(state);
+
+       state->cur = state->cover_id;
+       state->applying_cover = 1;
+       mail = am_path(state, msgnum(state));
+       if (!file_exists(mail))
+               die("BUG: cover has disapeared");
+
+       if(parse_mail(state, mail))
+               die("BUG: first patch is not a cover-letter");
+
+       if (state->signoff)
+               am_append_signoff(state);
+
+       write_author_script(state);
+       write_commit_msg(state);
+
+       if (state->interactive && do_interactive(state))
+               goto cancel_cover;
+
+       say(state, stdout, _("Applying: %.*s"), linelen(state->msg), 
state->msg);
+
+       do_commit(state);
+ cancel_cover:
+       state->cur = previous_cur;
+       state->applying_cover = 0;
+
+       /* Reset series metadata */
+       state->series_len = 0;
+       state->series_id = 0;
+       state->cover_id = 0;
+}
+
+/**
+ * Increments the patch pointer, and cleans am_state for the application of the
+ * next patch.
+ */
+static void am_next(struct am_state *state)
+{
+       struct object_id head;
+
+       /* Flush the cover letter if needed */
+       if (state->cover_at_tip == 1 &&
+           state->series_len > 0 &&
+           state->series_id == state->series_len &&
+           state->cover_id > 0)
+               do_apply_cover(state);
+
+       am_clean(state);
+
+       if (!get_oid("HEAD", &head))
+               write_state_text(state, "abort-safety", oid_to_hex(&head));
+       else
+               write_state_text(state, "abort-safety", "");
+
+       state->cur++;
+       write_state_count(state, "next", state->cur);
+}
+
 /**
  * Applies all queued mail.
  *
@@ -2287,6 +2394,8 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
                        N_("lie about committer date")),
                OPT_BOOL(0, "ignore-date", &state.ignore_date,
                        N_("use current timestamp for author date")),
+               OPT_BOOL(0, "cover-at-tip", &state.cover_at_tip,
+                       N_("apply cover letter to the tip of the branch")),
                OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),
                { OPTION_STRING, 'S', "gpg-sign", &state.sign_commit, 
N_("key-id"),
                  N_("GPG-sign commits"),
-- 
2.15.0.169.g3d3eebb67.dirty


Reply via email to