am: let --signoff override --no-signoff

After resolving a conflicting patch, a user may wish to sign off the patch to declare that the patch has been modified. As such, the user will expect that running "git am --signoff --continue" will append the signoff to the commit message. However, the --signoff option is only taken into account during the mail-parsing stage. If the --signoff option is set, then the signoff will be appended to the commit message. Since the mail-parsing stage comes before the patch application stage, the --signoff option, if provided on the command-line when resuming, will have no effect at all. We cannot move the append_signoff() call to the patch application stage as the applypatch-msg hook and interactive mode, which run before patch application, may expect the signoff to be there. Fix this by taking note if the user explictly set the --signoff option on the command-line, and append the signoff to the commit message when resuming if so. Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Paul Tan committed Aug 4, 2015 at 22:08 UTC b5e823594cff190bc18361207a89b08d57b038d7
2 files changed +45 -3
builtin/am.c
+25 -3
@@ -98,6 +98,12 @@ enum scissors_type {
98 SCISSORS_TRUE /* pass --scissors to git-mailinfo */
99 };
100
101 +enum signoff_type {
102 + SIGNOFF_FALSE = 0,
103 + SIGNOFF_TRUE = 1,
104 + SIGNOFF_EXPLICIT /* --signoff was set on the command-line */
105 +};
106 +
107 struct am_state {
108 /* state directory path */
109 char *dir;
@@ -123,7 +129,7 @@ struct am_state {
129 int interactive;
130 int threeway;
131 int quiet;
126 - int signoff;
132 + int signoff; /* enum signoff_type */
133 int utf8;
134 int keep; /* enum keep_type */
135 int message_id;
@@ -1185,6 +1191,18 @@ static void NORETURN die_user_resolve(const struct am_state *state)
1191 exit(128);
1192 }
1193
1194 +/**
1195 + * Appends signoff to the "msg" field of the am_state.
1196 + */
1197 +static void am_append_signoff(struct am_state *state)
1198 +{
1199 + struct strbuf sb = STRBUF_INIT;
1200 +
1201 + strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);
1202 + append_signoff(&sb, 0, 0);
1203 + state->msg = strbuf_detach(&sb, &state->msg_len);
1204 +}
1205 +
1206 /**
1207 * Parses `mail` using git-mailinfo, extracting its patch and authorship info.
1208 * state->msg will be set to the patch message. state->author_name,
@@ -2153,8 +2171,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
2171 OPT_BOOL('3', "3way", &state.threeway,
2172 N_("allow fall back on 3way merging if needed")),
2173 OPT__QUIET(&state.quiet, N_("be quiet")),
2156 - OPT_BOOL('s', "signoff", &state.signoff,
2157 - N_("add a Signed-off-by line to the commit message")),
2174 + OPT_SET_INT('s', "signoff", &state.signoff,
2175 + N_("add a Signed-off-by line to the commit message"),
2176 + SIGNOFF_EXPLICIT),
2177 OPT_BOOL('u', "utf8", &state.utf8,
2178 N_("recode into utf8 (default)")),
2179 OPT_SET_INT('k', "keep", &state.keep,
@@ -2267,6 +2286,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
2286
2287 if (resume == RESUME_FALSE)
2288 resume = RESUME_APPLY;
2289 +
2290 + if (state.signoff == SIGNOFF_EXPLICIT)
2291 + am_append_signoff(&state);
2292 } else {
2293 struct argv_array paths = ARGV_ARRAY_INIT;
2294 int i;
t/t4153-am-resume-override-opts.sh
+20
@@ -64,6 +64,26 @@ test_expect_success '--no-quiet overrides --quiet' '
64 test_i18ncmp expected out
65 '
66
67 +test_expect_success '--signoff overrides --no-signoff' '
68 + rm -fr .git/rebase-apply &&
69 + git reset --hard &&
70 + git checkout first &&
71 +
72 + test_must_fail git am --no-signoff side[12].eml &&
73 + test_path_is_dir .git/rebase-apply &&
74 + echo side1 >file &&
75 + git add file &&
76 + git am --signoff --continue &&
77 +
78 + # Applied side1 will be signed off
79 + echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
80 + git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
81 + test_cmp expected actual &&
82 +
83 + # Applied side2 will not be signed off
84 + test $(git cat-file commit HEAD | grep -c "Signed-off-by:") -eq 0
85 +'
86 +
87 test_expect_success TTY '--reject overrides --no-reject' '
88 rm -fr .git/rebase-apply &&
89 git reset --hard &&