{"thread":{"id":"27443","subject":"commit a1f6baa5 (wrap long header lines) breaks my habit","startedAt":"2011-05-24T16:02:53Z","lastAt":"2011-05-26T22:47:29Z","messageCount":16,"participants":["Stefan-W. Hahn","Junio C Hamano","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"168578","messageId":"20110524160253.GA7723@scotty.home","threadId":"27443","inReplyTo":null,"subject":"commit a1f6baa5 (wrap long header lines) breaks my habit","fromName":"Stefan-W. Hahn","fromEmail":"stefan.hahn@s-hahn.de","sentAt":"2011-05-24T16:02:53Z","receivedAt":"2011-05-24T16:02:53Z","isPatch":false,"sender":{"key":"stefan.hahn@s-hahn.de","avatar":null},"body":"Hello,\n\nfor rebasing I'm using normally\n\n   git format-patch -k --stdout a..b | git am -k -3\n\nWith commit\n\n  commit a1f6baa5c97abc8b579fa7ac7c4dc21971bdc048\n  format-patch: wrap long header lines \n  (since >v1.7.4)\n\nthis isn't possible anymore for those patches which have more then 78\ncharacters on the first line.\n\nThe wrapping of the lines in the commit message will not be seen when\ncommiting but when rebasing via format-patch.\n\nWas this the intention of this change or was my sort of workflow just\nnot in focus?\n\nAny suggestion?\n\n\nStefan\n-- \nStefan-W. Hahn                          It is easy to make things.\n                                        It is hard to make things simple.\n"},{"id":"168582","messageId":"7vboys83nh.fsf@alter.siamese.dyndns.org","threadId":"27443","inReplyTo":"20110524160253.GA7723@scotty.home","subject":"Re: commit a1f6baa5 (wrap long header lines) breaks my habit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-24T16:27:46Z","receivedAt":"2011-05-24T16:27:46Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Stefan-W. Hahn\" <stefan.hahn@s-hahn.de> writes:\n\n>    git format-patch -k --stdout a..b | git am -k -3\n\nWhy -k to am?\n"},{"id":"168586","messageId":"20110524164616.GB7723@scotty.home","threadId":"27443","inReplyTo":"7vboys83nh.fsf@alter.siamese.dyndns.org","subject":"Re: commit a1f6baa5 (wrap long header lines) breaks my habit","fromName":"Stefan-W. Hahn","fromEmail":"stefan.hahn@s-hahn.de","sentAt":"2011-05-24T16:46:16Z","receivedAt":"2011-05-24T16:46:16Z","isPatch":false,"sender":{"key":"stefan.hahn@s-hahn.de","avatar":null},"body":"Mail von Junio C Hamano, Tue, 24 May 2011 at 09:27:46 -0700:\n\n> >    git format-patch -k --stdout a..b | git am -k -3\n> \n> Why -k to am?\n\nJust first \"-k\", and \"git am -3\". Wrong in mind here at home before my\ncomputer.\n\nStefan\n\n-- \nStefan-W. Hahn                          It is easy to make things.\n                                        It is hard to make things simple.\n"},{"id":"168594","messageId":"20110524200716.GF584@sigill.intra.peff.net","threadId":"27443","inReplyTo":"20110524164616.GB7723@scotty.home","subject":"Re: commit a1f6baa5 (wrap long header lines) breaks my habit","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-24T20:07:16Z","receivedAt":"2011-05-24T20:07:16Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, May 24, 2011 at 06:46:16PM +0200, Stefan-W. Hahn wrote:\n\n> Mail von Junio C Hamano, Tue, 24 May 2011 at 09:27:46 -0700:\n> \n> > >    git format-patch -k --stdout a..b | git am -k -3\n> > \n> > Why -k to am?\n> \n> Just first \"-k\", and \"git am -3\". Wrong in mind here at home before my\n> computer.\n\nThen it should preserve your long subject line just fine, as mailsplit\n(called by \"am\") will reassemble the folded line according to rfc822\nheader folding rules.\n\nWith \"am -k\", it does keep the fold. This is an artifact of the original\nbehavior, where the folds were literally included from a multi-line\nsubject. We should probably stop doing that now that we fold on length\n(and should probably embed newlines via rfc2047 encoding in\nformat-patch, at least with \"-k\", so that you can losslessly move\nmulti-line subjects between the two if you always use \"-k\").\n\n-Peff\n"},{"id":"168671","messageId":"20110525154046.GC7723@scotty.home","threadId":"27443","inReplyTo":"20110524200716.GF584@sigill.intra.peff.net","subject":"Re: commit a1f6baa5 (wrap long header lines) breaks my habit","fromName":"Stefan-W. Hahn","fromEmail":"stefan.hahn@s-hahn.de","sentAt":"2011-05-25T15:40:46Z","receivedAt":"2011-05-25T15:40:46Z","isPatch":false,"sender":{"key":"stefan.hahn@s-hahn.de","avatar":null},"body":"Mail von Jeff King, Tue, 24 May 2011 at 16:07:16 -0400:\n\nHello,\n\n> > > >    git format-patch -k --stdout a..b | git am -k -3\n> > > \n> > > Why -k to am?\n> > \n> > Just first \"-k\", and \"git am -3\". Wrong in mind here at home before my\n> > computer.\n\nWrong. I really typed the second \"-k\". (Local intelligence in\nfingers.)\n\n> Then it should preserve your long subject line just fine, as mailsplit\n> (called by \"am\") will reassemble the folded line according to rfc822\n> header folding rules.\n> \n> With \"am -k\", it does keep the fold. This is an artifact of the original\n> behavior, where the folds were literally included from a multi-line\n\nCorrect, I checked this, so with\n\n   git format-patch -k --stdout a..b | git am -3\n(no second -k)\n\nall is as before. \n\nThanks for your clarification, sorry for the noise.\n\nStefan\n\nPerhaps a little clarification like this:\n\ncommit e8069848dffe72579aa7f2c542e39fde9eab84b1\nAuthor: Stefan-W. Hahn <stefan.hahn@s-hahn.de>\nDate:   Wed May 25 17:33:03 2011 +0200\n\n    format-patch: Clarify the behaviour of '-k'.\n    \n    Added clarification in documentation of of 'git format-patch'.\n    \n    When using 'git format-patch' together with 'git am' for rebasing,\n    'git am' should be called without '-k' if long subject lines should be\n    reassembled. This is neccesary, because a wrapping of long header lines\n    was introduced with commit:\n    \n    commit a1f6baa5c97abc8b579fa7ac7c4dc21971bdc048\n    format-patch: wrap long header lines\n    \n    Signed-off-by: Stefan-W. Hahn <stefan.hahn@s-hahn.de>\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex d13c9b2..4e62248 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -468,6 +468,16 @@ the current branch using 'git am' to cherry-pick them:\n ------------\n $ git format-patch -k --stdout R1..R2 | git am -3 -k\n ------------\n++\n+In this example the subject lines of the commits will be folded after\n+78 characters and 'git am' will keep this folding.\n++\n+To preserve long subject lines, 'git am' will reassemble the folded\n+lines according to rfc822 if called without '-k' like this:\n++\n+------------\n+$ git format-patch -k --stdout R1..R2 | git am -3\n+------------\n \n * Extract all commits which are in the current branch but not in the\n origin branch:\n\n-- \nStefan-W. Hahn                          It is easy to make things.\n                                        It is hard to make things simple.\n"},{"id":"168815","messageId":"20110526203625.GA31018@sigill.intra.peff.net","threadId":"27443","inReplyTo":"20110525154046.GC7723@scotty.home","subject":"Re: commit a1f6baa5 (wrap long header lines) breaks my habit","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-26T20:36:25Z","receivedAt":"2011-05-26T20:36:25Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, May 25, 2011 at 05:40:46PM +0200, Stefan-W. Hahn wrote:\n\n> > With \"am -k\", it does keep the fold. This is an artifact of the original\n> > behavior, where the folds were literally included from a multi-line\n> \n> Correct, I checked this, so with\n> \n>    git format-patch -k --stdout a..b | git am -3\n> (no second -k)\n> \n> all is as before. \n> \n> Thanks for your clarification, sorry for the noise.\n\nActually, I don't think it's noise. Look at the documentation patch you\nsuggest:\n\n> index d13c9b2..4e62248 100644\n> --- a/Documentation/git-format-patch.txt\n> +++ b/Documentation/git-format-patch.txt\n> @@ -468,6 +468,16 @@ the current branch using 'git am' to cherry-pick them:\n>  ------------\n>  $ git format-patch -k --stdout R1..R2 | git am -3 -k\n>  ------------\n> ++\n> +In this example the subject lines of the commits will be folded after\n> +78 characters and 'git am' will keep this folding.\n\nYou are using \"format-patch -k | am -k\". Surely that should preserve\nyour subject, no matter the length, and the fact that we need to\ndocument it is a sign that the behavior is simply wrong.\n\nSo I think we should do the following series instead.\n\n  [1/3]: t: test subject handling in format-patch / am pipeline\n  [2/3]: mailinfo: always clean up rfc822 header folding\n  [3/3]: format-patch: preserve subject newlines with -k\n\n-Peff\n"},{"id":"168816","messageId":"20110526204118.GA31340@sigill.intra.peff.net","threadId":"27443","inReplyTo":"20110526203625.GA31018@sigill.intra.peff.net","subject":"[PATCH 1/3] t: test subject handling in format-patch / am pipeline","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-26T20:41:18Z","receivedAt":"2011-05-26T20:41:18Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Commit a1f6baa (format-patch: wrap long header lines,\n2011-02-23) changed format-patch's behavior with respect to\nlong header lines, but made no accompanying changes to the\nreceiving side. It was thought that \"git am\" would handle\nthese folded subjects fine, but there is a regression when\nusing \"am -k\".\n\nLet's add a test documenting this. While we're at it, let's\ngive more complete test coverage to document what should be\nhappening in each case. We test three types of subjects:\na short one, one long enough to require wrapping, and a\nmultiline subject. For each, we test these three\ncombinations:\n\n  format-patch | am\n  format-patch -k | am\n  format-patch -k | am -k\n\nWe don't bother testing \"format-patch | am -k\", which is\nnonsense (you will be adding in [PATCH] cruft to each\nsubject).\n\nThis reveals the regression above (long subjects have\nlinebreaks introduced via \"format-patch -k | am -k\"),\nas well as an existing non-optimal behavior (multiline\nsubjects are not preserved using \"-k\").\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis can go straight on top of the jk/format-patch-multiline-header\nwhich went into v1.7.5 (the tip was c22e7de).\n\n t/t4152-am-subjects.sh |   77 ++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 77 insertions(+), 0 deletions(-)\n create mode 100755 t/t4152-am-subjects.sh\n\ndiff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh\nnew file mode 100755\nindex 0000000..7222c06\n--- /dev/null\n+++ b/t/t4152-am-subjects.sh\n@@ -0,0 +1,77 @@\n+#!/bin/sh\n+\n+test_description='test subject preservation with format-patch | am'\n+. ./test-lib.sh\n+\n+make_patches() {\n+\ttype=$1\n+\tsubject=$2\n+\ttest_expect_success \"create patches with $type subject\" '\n+\t\tgit reset --hard baseline &&\n+\t\techo $type >file &&\n+\t\tgit commit -a -m \"$subject\" &&\n+\t\tgit format-patch -1 --stdout >$type.patch &&\n+\t\tgit format-patch -1 --stdout -k >$type-k.patch\n+\t'\n+}\n+\n+check_subject() {\n+\tgit reset --hard baseline &&\n+\tgit am $2 $1.patch &&\n+\tgit log -1 --pretty=format:%B >actual &&\n+\ttest_cmp expect actual\n+}\n+\n+test_expect_success 'setup baseline commit' '\n+\ttest_commit baseline file\n+'\n+\n+SHORT_SUBJECT='short subject'\n+make_patches short \"$SHORT_SUBJECT\"\n+\n+LONG_SUBJECT1='this is a long subject that is virtually guaranteed'\n+LONG_SUBJECT2='to require wrapping via format-patch if it is all'\n+LONG_SUBJECT3='going to appear on a single line'\n+LONG_SUBJECT=\"$LONG_SUBJECT1 $LONG_SUBJECT2 $LONG_SUBJECT3\"\n+make_patches long \"$LONG_SUBJECT\"\n+\n+MULTILINE_SUBJECT=\"$LONG_SUBJECT1\n+$LONG_SUBJECT2\n+$LONG_SUBJECT3\"\n+make_patches multiline \"$MULTILINE_SUBJECT\"\n+\n+echo \"$SHORT_SUBJECT\" >expect\n+test_expect_success 'short subject preserved (format-patch | am)' '\n+\tcheck_subject short\n+'\n+test_expect_success 'short subject preserved (format-patch -k | am)' '\n+\tcheck_subject short-k\n+'\n+test_expect_success 'short subject preserved (format-patch -k | am -k)' '\n+\tcheck_subject short-k -k\n+'\n+\n+echo \"$LONG_SUBJECT\" >expect\n+test_expect_success 'long subject preserved (format-patch | am)' '\n+\tcheck_subject long\n+'\n+test_expect_success 'long subject preserved (format-patch -k | am)' '\n+\tcheck_subject long-k\n+'\n+test_expect_failure 'long subject preserved (format-patch -k | am -k)' '\n+\tcheck_subject long-k -k\n+'\n+\n+echo \"$LONG_SUBJECT\" >expect\n+test_expect_success 'multiline subject unwrapped (format-patch | am)' '\n+\tcheck_subject multiline\n+'\n+test_expect_success 'multiline subject unwrapped (format-patch -k | am)' '\n+\tcheck_subject multiline-k\n+'\n+echo \"$MULTILINE_SUBJECT\" >expect\n+test_expect_failure 'multiline subject preserved (format-patch -k | am -k)' '\n+\tcheck_subject multiline-k -k\n+'\n+\n+test_done\n-- \n1.7.4.5.26.g0c6a2\n"},{"id":"168818","messageId":"20110526205338.GB31340@sigill.intra.peff.net","threadId":"27443","inReplyTo":"20110526203625.GA31018@sigill.intra.peff.net","subject":"[PATCH 2/3] mailinfo: always clean up rfc822 header folding","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-26T20:53:38Z","receivedAt":"2011-05-26T20:53:38Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Without the \"-k\" option, mailinfo will convert a folded\nsubject header like:\n\n  Subject: this is a\n    subject that doesn't\n    fit on one line\n\ninto a single line. With \"-k\", however, we assumed that\nthese newlines were significant and represented something\nthat the sending side would want us to preserve.\n\nFor messages created by format-patch, this assumption was\nbroken by a1f6baa (format-patch: wrap long header lines,\n2011-02-23).  For messages sent by arbitrary MUAs, this was\nprobably never a good assumption to make, as they may have\nbeen folding subjects in accordance with rfc822's line\nlength recommendations all along.\n\nThis patch now joins folded lines with a single whitespace\ncharacter. This treats header folding purely as a syntactic\nfeature of the transport mechanism, not as something that\nformat-patch is trying to tell us about the original\nsubject.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThe astute reader will notice that even with this patch, there is still\na regression when using new versions of format-patch (with a1f6baa) with\nan older version of \"git am\". But you only see it when using \"am -k\", so\ninteroperability is probably not a huge deal:\n\n  1. Before this patch, \"am -k\" was arguably broken anyway for applying\n     random patches via email, since MUAs may have been doing arbitrary\n     header folding. So we can probably discount people running \"am -k\"\n     on random input as insane.\n\n  2. People doing \"git format-patch -k | git am -k\" will presumably use\n     the same version for both, and are OK.\n\n  3. People doing \"git format-patch -k >file\", followed by upgrading\n     git, and t hen \"git am file\" are still OK, since the newer version\n     of \"am\" handles the output of both old and new format-patch.\n\n  4. The problematic case is \"git format-patch -k >file\" with v1.7.5 or\n     newer, then _downgrading_ git, then using \"git am -k\" to apply. Or\n     more likely, using a newer version to create an mbox, shipping the\n     mbox to another machine, and then using an older \"git am\" to apply.\n\nSo I don't see it as all that likely a problem in practice. If we do\ncare, we can't fix it with a simple patch. We would have to revert the\nheader-folding from format-patch, fix am, wait N time units until all of\nthe old \"am\" no longer exists, and then re-apply.\n\n builtin/mailinfo.c     |    2 +-\n t/t4152-am-subjects.sh |    2 +-\n 2 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/mailinfo.c b/builtin/mailinfo.c\nindex 71e6262..bfb32b7 100644\n--- a/builtin/mailinfo.c\n+++ b/builtin/mailinfo.c\n@@ -400,7 +400,7 @@ static int read_one_header_line(struct strbuf *line, FILE *in)\n \t\t\tbreak;\n \t\tif (strbuf_getline(&continuation, in, '\\n'))\n \t\t\tbreak;\n-\t\tcontinuation.buf[0] = '\\n';\n+\t\tcontinuation.buf[0] = ' ';\n \t\tstrbuf_rtrim(&continuation);\n \t\tstrbuf_addbuf(line, &continuation);\n \t}\ndiff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh\nindex 7222c06..37e5c03 100755\n--- a/t/t4152-am-subjects.sh\n+++ b/t/t4152-am-subjects.sh\n@@ -58,7 +58,7 @@ test_expect_success 'long subject preserved (format-patch | am)' '\n test_expect_success 'long subject preserved (format-patch -k | am)' '\n \tcheck_subject long-k\n '\n-test_expect_failure 'long subject preserved (format-patch -k | am -k)' '\n+test_expect_success 'long subject preserved (format-patch -k | am -k)' '\n \tcheck_subject long-k -k\n '\n \n-- \n1.7.4.5.26.g0c6a2\n"},{"id":"168819","messageId":"20110526205504.GC31340@sigill.intra.peff.net","threadId":"27443","inReplyTo":"20110526203625.GA31018@sigill.intra.peff.net","subject":"[PATCH 3/3] format-patch: preserve subject newlines with -k","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-26T20:55:04Z","receivedAt":"2011-05-26T20:55:04Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"In older versions of git, we used rfc822 header folding to\nindicate that the original subject line had multiple lines\nin it.  But since a1f6baa (format-patch: wrap long header\nlines, 2011-02-23), we now use header folding whenever there\nis a long line.\n\nThis means that \"git am\" cannot trust header folding as a\nsign from format-patch that newlines should be preserved.\nInstead, format-patch needs to signal more explicitly that\nthe newlines are significant.  This patch does so by\nrfc2047-encoding the newlines in the subject line. No\nchanges are needed on the \"git am\" end; it already decodes\nthe newlines properly.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nWe have always treated multi-line subjects as second-class citizens, so\nthis is not a must-have patch. But I think it makes sense to do,\nconsidering how simple it is, and the fact that it makes \"format-patch\n-k | am -k\" always a no-op, even with multi-line subjects.\n\n builtin/log.c          |    3 ++-\n commit.h               |    4 +++-\n log-tree.c             |    1 +\n pretty.c               |    8 +++++---\n revision.h             |    3 ++-\n t/t4152-am-subjects.sh |    2 +-\n 6 files changed, 14 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex d8c6c28..3fdf488 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -768,7 +768,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tpp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,\n \t\t     encoding);\n \tpp_title_line(CMIT_FMT_EMAIL, &msg, &sb, subject_start, extra_headers,\n-\t\t      encoding, need_8bit_cte);\n+\t\t      encoding, need_8bit_cte, 0);\n \tpp_remainder(CMIT_FMT_EMAIL, &msg, &sb, 0);\n \tprintf(\"%s\\n\", sb.buf);\n \n@@ -1130,6 +1130,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tdie (\"-n and -k are mutually exclusive.\");\n \tif (keep_subject && subject_prefix)\n \t\tdie (\"--subject-prefix and -k are mutually exclusive.\");\n+\trev.preserve_subject = keep_subject;\n \n \targc = setup_revisions(argc, argv, &rev, &s_r_opt);\n \tif (argc > 1)\ndiff --git a/commit.h b/commit.h\nindex eb6c5af..30cb7bc 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -73,6 +73,7 @@ struct pretty_print_context\n \tint abbrev;\n \tconst char *subject;\n \tconst char *after_subject;\n+\tint preserve_subject;\n \tenum date_mode date_mode;\n \tint need_8bit_cte;\n \tint show_notes;\n@@ -107,7 +108,8 @@ void pp_title_line(enum cmit_fmt fmt,\n \t\t   const char *subject,\n \t\t   const char *after_subject,\n \t\t   const char *encoding,\n-\t\t   int need_8bit_cte);\n+\t\t   int need_8bit_cte,\n+\t\t   int preserve_lines);\n void pp_remainder(enum cmit_fmt fmt,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\ndiff --git a/log-tree.c b/log-tree.c\nindex b46ed3b..9b9aaf2 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -504,6 +504,7 @@ void show_log(struct rev_info *opt)\n \tctx.date_mode = opt->date_mode;\n \tctx.abbrev = opt->diffopt.abbrev;\n \tctx.after_subject = extra_headers;\n+\tctx.preserve_subject = opt->preserve_subject;\n \tctx.reflog_info = opt->reflog_info;\n \tpretty_print_commit(opt->commit_format, commit, &msgbuf, &ctx);\n \ndiff --git a/pretty.c b/pretty.c\nindex 65d20a7..315f1d2 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1121,12 +1121,13 @@ void pp_title_line(enum cmit_fmt fmt,\n \t\t   const char *subject,\n \t\t   const char *after_subject,\n \t\t   const char *encoding,\n-\t\t   int need_8bit_cte)\n+\t\t   int need_8bit_cte,\n+\t\t   int preserve_lines)\n {\n \tstruct strbuf title;\n \n \tstrbuf_init(&title, 80);\n-\t*msg_p = format_subject(&title, *msg_p, \" \");\n+\t*msg_p = format_subject(&title, *msg_p, preserve_lines ? \"\\n\" : \" \");\n \n \tstrbuf_grow(sb, title.len + 1024);\n \tif (subject) {\n@@ -1254,7 +1255,8 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n \t/* These formats treat the title line specially. */\n \tif (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)\n \t\tpp_title_line(fmt, &msg, sb, context->subject,\n-\t\t\t      context->after_subject, encoding, need_8bit_cte);\n+\t\t\t      context->after_subject, encoding, need_8bit_cte,\n+\t\t\t      context->preserve_subject);\n \n \tbeginning_of_body = sb->len;\n \tif (fmt != CMIT_FMT_ONELINE)\ndiff --git a/revision.h b/revision.h\nindex 05659c6..f8ddd83 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -90,7 +90,8 @@ struct rev_info {\n \t\t\tabbrev_commit:1,\n \t\t\tuse_terminator:1,\n \t\t\tmissing_newline:1,\n-\t\t\tdate_mode_explicit:1;\n+\t\t\tdate_mode_explicit:1,\n+\t\t\tpreserve_subject:1;\n \tunsigned int\tdisable_stdin:1;\n \n \tenum date_mode date_mode;\ndiff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh\nindex 37e5c03..4c68245 100755\n--- a/t/t4152-am-subjects.sh\n+++ b/t/t4152-am-subjects.sh\n@@ -70,7 +70,7 @@ test_expect_success 'multiline subject unwrapped (format-patch -k | am)' '\n \tcheck_subject multiline-k\n '\n echo \"$MULTILINE_SUBJECT\" >expect\n-test_expect_failure 'multiline subject preserved (format-patch -k | am -k)' '\n+test_expect_success 'multiline subject preserved (format-patch -k | am -k)' '\n \tcheck_subject multiline-k -k\n '\n \n-- \n1.7.4.5.26.g0c6a2\n"},{"id":"168827","messageId":"7vboypw47q.fsf@alter.siamese.dyndns.org","threadId":"27443","inReplyTo":"20110526205504.GC31340@sigill.intra.peff.net","subject":"Re: [PATCH 3/3] format-patch: preserve subject newlines with -k","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-26T21:18:33Z","receivedAt":"2011-05-26T21:18:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> We have always treated multi-line subjects as second-class citizens, so\n> this is not a must-have patch. But I think it makes sense to do,\n> considering how simple it is, and the fact that it makes \"format-patch\n> -k | am -k\" always a no-op, even with multi-line subjects.\n\nI think this is a good thing to have, as the reason why we treated\nmulti-line subjects as second-class citizens is exactly because we didn't\ntry to stuff multiple lines on \"Subject:\" like you did with this patch.\n\n> diff --git a/builtin/log.c b/builtin/log.c\n> index d8c6c28..3fdf488 100644\n> --- a/builtin/log.c\n> +++ b/builtin/log.c\n> @@ -768,7 +768,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n>  \tpp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,\n>  \t\t     encoding);\n>  \tpp_title_line(CMIT_FMT_EMAIL, &msg, &sb, subject_start, extra_headers,\n> -\t\t      encoding, need_8bit_cte);\n> +\t\t      encoding, need_8bit_cte, 0);\n\nI do not appreciate a single-bit tweak as separate parameter to a\nfunction.  Back when pp_title_line() had only \"do we need 8-bit cte\", it\nwas Ok, but now that you are adding another bit, could we make it an\n\"unsigned flag\"?\n"},{"id":"168828","messageId":"20110526211952.GA32097@sigill.intra.peff.net","threadId":"27443","inReplyTo":"7vboypw47q.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 3/3] format-patch: preserve subject newlines with -k","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-26T21:19:52Z","receivedAt":"2011-05-26T21:19:52Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, May 26, 2011 at 02:18:33PM -0700, Junio C Hamano wrote:\n\n> > diff --git a/builtin/log.c b/builtin/log.c\n> > index d8c6c28..3fdf488 100644\n> > --- a/builtin/log.c\n> > +++ b/builtin/log.c\n> > @@ -768,7 +768,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n> >  \tpp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,\n> >  \t\t     encoding);\n> >  \tpp_title_line(CMIT_FMT_EMAIL, &msg, &sb, subject_start, extra_headers,\n> > -\t\t      encoding, need_8bit_cte);\n> > +\t\t      encoding, need_8bit_cte, 0);\n> \n> I do not appreciate a single-bit tweak as separate parameter to a\n> function.  Back when pp_title_line() had only \"do we need 8-bit cte\", it\n> was Ok, but now that you are adding another bit, could we make it an\n> \"unsigned flag\"?\n\nActually, I wonder if we can refactor to just pass the pretty_context to\npp_title_line. Let me see what I can do.\n\n-Peff\n"},{"id":"168839","messageId":"20110526222450.GA20077@sigill.intra.peff.net","threadId":"27443","inReplyTo":"20110526211952.GA32097@sigill.intra.peff.net","subject":"Re: [PATCH 3/3] format-patch: preserve subject newlines with -k","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-26T22:24:50Z","receivedAt":"2011-05-26T22:24:50Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, May 26, 2011 at 05:19:52PM -0400, Jeff King wrote:\n\n> > >  \tpp_title_line(CMIT_FMT_EMAIL, &msg, &sb, subject_start, extra_headers,\n> > > -\t\t      encoding, need_8bit_cte);\n> > > +\t\t      encoding, need_8bit_cte, 0);\n> > \n> > I do not appreciate a single-bit tweak as separate parameter to a\n> > function.  Back when pp_title_line() had only \"do we need 8-bit cte\", it\n> > was Ok, but now that you are adding another bit, could we make it an\n> > \"unsigned flag\"?\n> \n> Actually, I wonder if we can refactor to just pass the pretty_context to\n> pp_title_line. Let me see what I can do.\n\nIt ends up being a lot of lines changed, but I think the result is more\nreadable. Replace my 3/3 with (1/5 and 2/5 are the same as before):\n\n  [3/5]: pretty: add pp_commit_easy function for simple callers\n  [4/5]: clean up calling conventions for pretty.c functions\n  [5/5]: format-patch: preserve subject newlines with -k\n\n-Peff\n"},{"id":"168840","messageId":"20110526222724.GA21775@sigill.intra.peff.net","threadId":"27443","inReplyTo":"20110526222450.GA20077@sigill.intra.peff.net","subject":"[PATCH 3/5] pretty: add pp_commit_easy function for simple callers","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-26T22:27:24Z","receivedAt":"2011-05-26T22:27:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Many callers don't actually care about the pretty print\ncontext at all; let's just give them a simple way of\npretty-printing a commit without having to create a context\nstruct.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis trades off per-call lines for some infrastructure lines. It's a\nslight lose in line count now, but as more callers are added, it may be\na win. But I think even now it's overall easier to read.\n\n builtin/branch.c      |    4 +---\n builtin/checkout.c    |    3 +--\n builtin/log.c         |    4 +---\n builtin/shortlog.c    |    3 +--\n builtin/show-branch.c |    3 +--\n commit.h              |    2 ++\n pretty.c              |    7 +++++++\n 7 files changed, 14 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 9e546e4..d8f1522 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -436,9 +436,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \n \t\tcommit = item->commit;\n \t\tif (commit && !parse_commit(commit)) {\n-\t\t\tstruct pretty_print_context ctx = {0};\n-\t\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit,\n-\t\t\t\t\t    &subject, &ctx);\n+\t\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &subject);\n \t\t\tsub = subject.buf;\n \t\t}\n \ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 757f9a0..c1759dc 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -300,9 +300,8 @@ static void show_local_changes(struct object *head, struct diff_options *opts)\n static void describe_detached_head(char *msg, struct commit *commit)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n-\tstruct pretty_print_context ctx = {0};\n \tparse_commit(commit);\n-\tpretty_print_commit(CMIT_FMT_ONELINE, commit, &sb, &ctx);\n+\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n \tfprintf(stderr, \"%s %s... %s\\n\", msg,\n \t\tfind_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV), sb.buf);\n \tstrbuf_release(&sb);\ndiff --git a/builtin/log.c b/builtin/log.c\nindex d8c6c28..cedfdb6 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1439,9 +1439,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)\n \n \t\tif (verbose) {\n \t\t\tstruct strbuf buf = STRBUF_INIT;\n-\t\t\tstruct pretty_print_context ctx = {0};\n-\t\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit,\n-\t\t\t\t\t    &buf, &ctx);\n+\t\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);\n \t\t\tprintf(\"%c %s %s\\n\", sign,\n \t\t\t       find_unique_abbrev(commit->object.sha1, abbrev),\n \t\t\t       buf.buf);\ndiff --git a/builtin/shortlog.c b/builtin/shortlog.c\nindex 1a21e4b..90877b5 100644\n--- a/builtin/shortlog.c\n+++ b/builtin/shortlog.c\n@@ -141,9 +141,8 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)\n \tconst char *author = NULL, *buffer;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct strbuf ufbuf = STRBUF_INIT;\n-\tstruct pretty_print_context ctx = {0};\n \n-\tpretty_print_commit(CMIT_FMT_RAW, commit, &buf, &ctx);\n+\tpp_commit_easy(CMIT_FMT_RAW, commit, &buf);\n \tbuffer = buf.buf;\n \twhile (*buffer && *buffer != '\\n') {\n \t\tconst char *eol = strchr(buffer, '\\n');\ndiff --git a/builtin/show-branch.c b/builtin/show-branch.c\nindex da69581..a5fc2aa 100644\n--- a/builtin/show-branch.c\n+++ b/builtin/show-branch.c\n@@ -293,8 +293,7 @@ static void show_one_commit(struct commit *commit, int no_name)\n \tstruct commit_name *name = commit->util;\n \n \tif (commit->object.parsed) {\n-\t\tstruct pretty_print_context ctx = {0};\n-\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit, &pretty, &ctx);\n+\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);\n \t\tpretty_str = pretty.buf;\n \t}\n \tif (!prefixcmp(pretty_str, \"[PATCH] \"))\ndiff --git a/commit.h b/commit.h\nindex eb6c5af..3e733be 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -98,6 +98,8 @@ extern void format_commit_message(const struct commit *commit,\n extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n \t\t\t\tstruct strbuf *sb,\n \t\t\t\tconst struct pretty_print_context *context);\n+extern void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n+\t\t\t   struct strbuf *sb);\n void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,\n \t\t   const char *line, enum date_mode dmode,\n \t\t   const char *encoding);\ndiff --git a/pretty.c b/pretty.c\nindex 65d20a7..38cd398 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1279,3 +1279,10 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n \n \tfree(reencoded);\n }\n+\n+void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n+\t\t    struct strbuf *sb)\n+{\n+\tstruct pretty_print_context pp = {0};\n+\tpretty_print_commit(fmt, commit, sb, &pp);\n+}\n-- \n1.7.4.5.26.g0c6a2\n"},{"id":"168841","messageId":"20110526222749.GB21775@sigill.intra.peff.net","threadId":"27443","inReplyTo":"20110526222450.GA20077@sigill.intra.peff.net","subject":"[PATCH 4/5] clean up calling conventions for pretty.c functions","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-26T22:27:49Z","receivedAt":"2011-05-26T22:27:49Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"We have a pretty_print_context representing the parameters\nfor a pretty-print session, but we did not use it uniformly.\nAs a result, functions kept growing more and more arguments.\n\nLet's clean this up in a few ways:\n\n  1. All pretty-print pp_* functions now take a context.\n     This lets us reduce the number of arguments to these\n     functions, since we were just passing around the\n     context values separately.\n\n  2. The context argument now has a cmit_fmt field, which\n     was passed around separately. That's one less argument\n     per function.\n\n  3. The context argument always comes first, which makes\n     calling a little more uniform.\n\nThis drops lines from some callers, and adds lines in a few\nplaces (because we need an extra line to set the context's\nfmt field). Overall, we don't save many lines, but the lines\nthat are there are a lot simpler and more readable.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n builtin/log.c      |   21 ++++++-----\n builtin/merge.c    |    3 +-\n builtin/rev-list.c |    3 +-\n builtin/shortlog.c |    3 +-\n commit.h           |   19 +++++-----\n log-tree.c         |    3 +-\n pretty.c           |   99 ++++++++++++++++++++++++---------------------------\n 7 files changed, 75 insertions(+), 76 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex cedfdb6..8d842cb 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -327,9 +327,11 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)\n static void show_tagger(char *buf, int len, struct rev_info *rev)\n {\n \tstruct strbuf out = STRBUF_INIT;\n+\tstruct pretty_print_context pp = {0};\n \n-\tpp_user_info(\"Tagger\", rev->commit_format, &out, buf, rev->date_mode,\n-\t\tget_log_output_encoding());\n+\tpp.fmt = rev->commit_format;\n+\tpp.date_mode = rev->date_mode;\n+\tpp_user_info(&pp, \"Tagger\", &out, buf, get_log_output_encoding());\n \tprintf(\"%s\", out.buf);\n \tstrbuf_release(&out);\n }\n@@ -715,10 +717,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\t\t      int nr, struct commit **list, struct commit *head)\n {\n \tconst char *committer;\n-\tconst char *subject_start = NULL;\n \tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n \tconst char *msg;\n-\tconst char *extra_headers = rev->extra_headers;\n \tstruct shortlog log;\n \tstruct strbuf sb = STRBUF_INIT;\n \tint i;\n@@ -726,6 +726,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tstruct diff_options opts;\n \tint need_8bit_cte = 0;\n \tstruct commit *commit = NULL;\n+\tstruct pretty_print_context pp = {0};\n \n \tif (rev->commit_format != CMIT_FMT_EMAIL)\n \t\tdie(\"Cover letter needs email format\");\n@@ -757,7 +758,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\tfree(commit);\n \t}\n \n-\tlog_write_email_headers(rev, head, &subject_start, &extra_headers,\n+\tlog_write_email_headers(rev, head, &pp.subject, &pp.after_subject,\n \t\t\t\t&need_8bit_cte);\n \n \tfor (i = 0; !need_8bit_cte && i < nr; i++)\n@@ -765,11 +766,11 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\t\tneed_8bit_cte = 1;\n \n \tmsg = body;\n-\tpp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,\n-\t\t     encoding);\n-\tpp_title_line(CMIT_FMT_EMAIL, &msg, &sb, subject_start, extra_headers,\n-\t\t      encoding, need_8bit_cte);\n-\tpp_remainder(CMIT_FMT_EMAIL, &msg, &sb, 0);\n+\tpp.fmt = CMIT_FMT_EMAIL;\n+\tpp.date_mode = DATE_RFC2822;\n+\tpp_user_info(&pp, NULL, &sb, committer, encoding);\n+\tpp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);\n+\tpp_remainder(&pp, &msg, &sb, 0);\n \tprintf(\"%s\\n\", sb.buf);\n \n \tstrbuf_release(&sb);\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 42fff38..c902e81 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -333,13 +333,14 @@ static void squash_message(void)\n \n \tctx.abbrev = rev.abbrev;\n \tctx.date_mode = rev.date_mode;\n+\tctx.fmt = rev.commit_format;\n \n \tstrbuf_addstr(&out, \"Squashed commit of the following:\\n\");\n \twhile ((commit = get_revision(&rev)) != NULL) {\n \t\tstrbuf_addch(&out, '\\n');\n \t\tstrbuf_addf(&out, \"commit %s\\n\",\n \t\t\tsha1_to_hex(commit->object.sha1));\n-\t\tpretty_print_commit(rev.commit_format, commit, &out, &ctx);\n+\t\tpretty_print_commit(&ctx, commit, &out);\n \t}\n \tif (write(fd, out.buf, out.len) < 0)\n \t\tdie_errno(\"Writing SQUASH_MSG\");\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex ba27d39..0ec42fc 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -108,7 +108,8 @@ static void show_commit(struct commit *commit, void *data)\n \t\tstruct pretty_print_context ctx = {0};\n \t\tctx.abbrev = revs->abbrev;\n \t\tctx.date_mode = revs->date_mode;\n-\t\tpretty_print_commit(revs->commit_format, commit, &buf, &ctx);\n+\t\tctx.fmt = revs->commit_format;\n+\t\tpretty_print_commit(&ctx, commit, &buf);\n \t\tif (revs->graph) {\n \t\t\tif (buf.len) {\n \t\t\t\tif (revs->commit_format != CMIT_FMT_ONELINE)\ndiff --git a/builtin/shortlog.c b/builtin/shortlog.c\nindex 90877b5..074fd26 100644\n--- a/builtin/shortlog.c\n+++ b/builtin/shortlog.c\n@@ -161,11 +161,12 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)\n \t\t    sha1_to_hex(commit->object.sha1));\n \tif (log->user_format) {\n \t\tstruct pretty_print_context ctx = {0};\n+\t\tctx.fmt = CMIT_FMT_USERFORMAT;\n \t\tctx.abbrev = log->abbrev;\n \t\tctx.subject = \"\";\n \t\tctx.after_subject = \"\";\n \t\tctx.date_mode = DATE_NORMAL;\n-\t\tpretty_print_commit(CMIT_FMT_USERFORMAT, commit, &ufbuf, &ctx);\n+\t\tpretty_print_commit(&ctx, commit, &ufbuf);\n \t\tbuffer = ufbuf.buf;\n \t} else if (*buffer) {\n \t\tbuffer++;\ndiff --git a/commit.h b/commit.h\nindex 3e733be..2935740 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -70,6 +70,7 @@ enum cmit_fmt {\n \n struct pretty_print_context\n {\n+\tenum cmit_fmt fmt;\n \tint abbrev;\n \tconst char *subject;\n \tconst char *after_subject;\n@@ -95,22 +96,20 @@ extern void userformat_find_requirements(const char *fmt, struct userformat_want\n extern void format_commit_message(const struct commit *commit,\n \t\t\t\t  const char *format, struct strbuf *sb,\n \t\t\t\t  const struct pretty_print_context *context);\n-extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n-\t\t\t\tstruct strbuf *sb,\n-\t\t\t\tconst struct pretty_print_context *context);\n+extern void pretty_print_commit(const struct pretty_print_context *pp,\n+\t\t\t\tconst struct commit *commit,\n+\t\t\t\tstruct strbuf *sb);\n extern void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n \t\t\t   struct strbuf *sb);\n-void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,\n-\t\t   const char *line, enum date_mode dmode,\n-\t\t   const char *encoding);\n-void pp_title_line(enum cmit_fmt fmt,\n+void pp_user_info(const struct pretty_print_context *pp,\n+\t\t  const char *what, struct strbuf *sb,\n+\t\t  const char *line, const char *encoding);\n+void pp_title_line(const struct pretty_print_context *pp,\n \t\t   const char **msg_p,\n \t\t   struct strbuf *sb,\n-\t\t   const char *subject,\n-\t\t   const char *after_subject,\n \t\t   const char *encoding,\n \t\t   int need_8bit_cte);\n-void pp_remainder(enum cmit_fmt fmt,\n+void pp_remainder(const struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n \t\t  int indent);\ndiff --git a/log-tree.c b/log-tree.c\nindex b46ed3b..0d8cc7a 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -505,7 +505,8 @@ void show_log(struct rev_info *opt)\n \tctx.abbrev = opt->diffopt.abbrev;\n \tctx.after_subject = extra_headers;\n \tctx.reflog_info = opt->reflog_info;\n-\tpretty_print_commit(opt->commit_format, commit, &msgbuf, &ctx);\n+\tctx.fmt = opt->commit_format;\n+\tpretty_print_commit(&ctx, commit, &msgbuf);\n \n \tif (opt->add_signoff)\n \t\tappend_signoff(&msgbuf, opt->add_signoff);\ndiff --git a/pretty.c b/pretty.c\nindex 38cd398..f920205 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -266,16 +266,16 @@ needquote:\n \tstrbuf_addstr(sb, \"?=\");\n }\n \n-void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,\n-\t\t  const char *line, enum date_mode dmode,\n-\t\t  const char *encoding)\n+void pp_user_info(const struct pretty_print_context *pp,\n+\t\t  const char *what, struct strbuf *sb,\n+\t\t  const char *line, const char *encoding)\n {\n \tchar *date;\n \tint namelen;\n \tunsigned long time;\n \tint tz;\n \n-\tif (fmt == CMIT_FMT_ONELINE)\n+\tif (pp->fmt == CMIT_FMT_ONELINE)\n \t\treturn;\n \tdate = strchr(line, '>');\n \tif (!date)\n@@ -284,7 +284,7 @@ void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,\n \ttime = strtoul(date, &date, 10);\n \ttz = strtol(date, NULL, 10);\n \n-\tif (fmt == CMIT_FMT_EMAIL) {\n+\tif (pp->fmt == CMIT_FMT_EMAIL) {\n \t\tchar *name_tail = strchr(line, '<');\n \t\tint display_name_length;\n \t\tif (!name_tail)\n@@ -298,18 +298,18 @@ void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,\n \t\tstrbuf_addch(sb, '\\n');\n \t} else {\n \t\tstrbuf_addf(sb, \"%s: %.*s%.*s\\n\", what,\n-\t\t\t      (fmt == CMIT_FMT_FULLER) ? 4 : 0,\n+\t\t\t      (pp->fmt == CMIT_FMT_FULLER) ? 4 : 0,\n \t\t\t      \"    \", namelen, line);\n \t}\n-\tswitch (fmt) {\n+\tswitch (pp->fmt) {\n \tcase CMIT_FMT_MEDIUM:\n-\t\tstrbuf_addf(sb, \"Date:   %s\\n\", show_date(time, tz, dmode));\n+\t\tstrbuf_addf(sb, \"Date:   %s\\n\", show_date(time, tz, pp->date_mode));\n \t\tbreak;\n \tcase CMIT_FMT_EMAIL:\n \t\tstrbuf_addf(sb, \"Date: %s\\n\", show_date(time, tz, DATE_RFC2822));\n \t\tbreak;\n \tcase CMIT_FMT_FULLER:\n-\t\tstrbuf_addf(sb, \"%sDate: %s\\n\", what, show_date(time, tz, dmode));\n+\t\tstrbuf_addf(sb, \"%sDate: %s\\n\", what, show_date(time, tz, pp->date_mode));\n \t\tbreak;\n \tdefault:\n \t\t/* notin' */\n@@ -340,12 +340,12 @@ static const char *skip_empty_lines(const char *msg)\n \treturn msg;\n }\n \n-static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb,\n-\t\t\tconst struct commit *commit, int abbrev)\n+static void add_merge_info(const struct pretty_print_context *pp,\n+\t\t\t   struct strbuf *sb, const struct commit *commit)\n {\n \tstruct commit_list *parent = commit->parents;\n \n-\tif ((fmt == CMIT_FMT_ONELINE) || (fmt == CMIT_FMT_EMAIL) ||\n+\tif ((pp->fmt == CMIT_FMT_ONELINE) || (pp->fmt == CMIT_FMT_EMAIL) ||\n \t    !parent || !parent->next)\n \t\treturn;\n \n@@ -354,8 +354,8 @@ static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb,\n \twhile (parent) {\n \t\tstruct commit *p = parent->item;\n \t\tconst char *hex = NULL;\n-\t\tif (abbrev)\n-\t\t\thex = find_unique_abbrev(p->object.sha1, abbrev);\n+\t\tif (pp->abbrev)\n+\t\t\thex = find_unique_abbrev(p->object.sha1, pp->abbrev);\n \t\tif (!hex)\n \t\t\thex = sha1_to_hex(p->object.sha1);\n \t\tparent = parent->next;\n@@ -1052,9 +1052,7 @@ void format_commit_message(const struct commit *commit,\n \t\tfree(context.message);\n }\n \n-static void pp_header(enum cmit_fmt fmt,\n-\t\t      int abbrev,\n-\t\t      enum date_mode dmode,\n+static void pp_header(const struct pretty_print_context *pp,\n \t\t      const char *encoding,\n \t\t      const struct commit *commit,\n \t\t      const char **msg_p,\n@@ -1074,7 +1072,7 @@ static void pp_header(enum cmit_fmt fmt,\n \t\t\t/* End of header */\n \t\t\treturn;\n \n-\t\tif (fmt == CMIT_FMT_RAW) {\n+\t\tif (pp->fmt == CMIT_FMT_RAW) {\n \t\t\tstrbuf_add(sb, line, linelen);\n \t\t\tcontinue;\n \t\t}\n@@ -1094,7 +1092,7 @@ static void pp_header(enum cmit_fmt fmt,\n \t\t\t\t;\n \t\t\t/* with enough slop */\n \t\t\tstrbuf_grow(sb, num * 50 + 20);\n-\t\t\tadd_merge_info(fmt, sb, commit, abbrev);\n+\t\t\tadd_merge_info(pp, sb, commit);\n \t\t\tparents_shown = 1;\n \t\t}\n \n@@ -1105,21 +1103,19 @@ static void pp_header(enum cmit_fmt fmt,\n \t\t */\n \t\tif (!memcmp(line, \"author \", 7)) {\n \t\t\tstrbuf_grow(sb, linelen + 80);\n-\t\t\tpp_user_info(\"Author\", fmt, sb, line + 7, dmode, encoding);\n+\t\t\tpp_user_info(pp, \"Author\", sb, line + 7, encoding);\n \t\t}\n \t\tif (!memcmp(line, \"committer \", 10) &&\n-\t\t    (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) {\n+\t\t    (pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {\n \t\t\tstrbuf_grow(sb, linelen + 80);\n-\t\t\tpp_user_info(\"Commit\", fmt, sb, line + 10, dmode, encoding);\n+\t\t\tpp_user_info(pp, \"Commit\", sb, line + 10, encoding);\n \t\t}\n \t}\n }\n \n-void pp_title_line(enum cmit_fmt fmt,\n+void pp_title_line(const struct pretty_print_context *pp,\n \t\t   const char **msg_p,\n \t\t   struct strbuf *sb,\n-\t\t   const char *subject,\n-\t\t   const char *after_subject,\n \t\t   const char *encoding,\n \t\t   int need_8bit_cte)\n {\n@@ -1129,8 +1125,8 @@ void pp_title_line(enum cmit_fmt fmt,\n \t*msg_p = format_subject(&title, *msg_p, \" \");\n \n \tstrbuf_grow(sb, title.len + 1024);\n-\tif (subject) {\n-\t\tstrbuf_addstr(sb, subject);\n+\tif (pp->subject) {\n+\t\tstrbuf_addstr(sb, pp->subject);\n \t\tadd_rfc2047(sb, title.buf, title.len, encoding);\n \t} else {\n \t\tstrbuf_addbuf(sb, &title);\n@@ -1144,16 +1140,16 @@ void pp_title_line(enum cmit_fmt fmt,\n \t\t\t\"Content-Transfer-Encoding: 8bit\\n\";\n \t\tstrbuf_addf(sb, header_fmt, encoding);\n \t}\n-\tif (after_subject) {\n-\t\tstrbuf_addstr(sb, after_subject);\n+\tif (pp->after_subject) {\n+\t\tstrbuf_addstr(sb, pp->after_subject);\n \t}\n-\tif (fmt == CMIT_FMT_EMAIL) {\n+\tif (pp->fmt == CMIT_FMT_EMAIL) {\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n \tstrbuf_release(&title);\n }\n \n-void pp_remainder(enum cmit_fmt fmt,\n+void pp_remainder(const struct pretty_print_context *pp,\n \t\t  const char **msg_p,\n \t\t  struct strbuf *sb,\n \t\t  int indent)\n@@ -1170,7 +1166,7 @@ void pp_remainder(enum cmit_fmt fmt,\n \t\tif (is_empty_line(line, &linelen)) {\n \t\t\tif (first)\n \t\t\t\tcontinue;\n-\t\t\tif (fmt == CMIT_FMT_SHORT)\n+\t\t\tif (pp->fmt == CMIT_FMT_SHORT)\n \t\t\t\tbreak;\n \t\t}\n \t\tfirst = 0;\n@@ -1195,19 +1191,19 @@ char *reencode_commit_message(const struct commit *commit, const char **encoding\n \treturn logmsg_reencode(commit, encoding);\n }\n \n-void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n-\t\t\t struct strbuf *sb,\n-\t\t\t const struct pretty_print_context *context)\n+void pretty_print_commit(const struct pretty_print_context *pp,\n+\t\t\t const struct commit *commit,\n+\t\t\t struct strbuf *sb)\n {\n \tunsigned long beginning_of_body;\n \tint indent = 4;\n \tconst char *msg = commit->buffer;\n \tchar *reencoded;\n \tconst char *encoding;\n-\tint need_8bit_cte = context->need_8bit_cte;\n+\tint need_8bit_cte = pp->need_8bit_cte;\n \n-\tif (fmt == CMIT_FMT_USERFORMAT) {\n-\t\tformat_commit_message(commit, user_format, sb, context);\n+\tif (pp->fmt == CMIT_FMT_USERFORMAT) {\n+\t\tformat_commit_message(commit, user_format, sb, pp);\n \t\treturn;\n \t}\n \n@@ -1216,14 +1212,14 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n \t\tmsg = reencoded;\n \t}\n \n-\tif (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)\n+\tif (pp->fmt == CMIT_FMT_ONELINE || pp->fmt == CMIT_FMT_EMAIL)\n \t\tindent = 0;\n \n \t/*\n \t * We need to check and emit Content-type: to mark it\n \t * as 8-bit if we haven't done so.\n \t */\n-\tif (fmt == CMIT_FMT_EMAIL && need_8bit_cte == 0) {\n+\tif (pp->fmt == CMIT_FMT_EMAIL && need_8bit_cte == 0) {\n \t\tint i, ch, in_body;\n \n \t\tfor (in_body = i = 0; (ch = msg[i]); i++) {\n@@ -1242,9 +1238,8 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n \t\t}\n \t}\n \n-\tpp_header(fmt, context->abbrev, context->date_mode, encoding,\n-\t\t  commit, &msg, sb);\n-\tif (fmt != CMIT_FMT_ONELINE && !context->subject) {\n+\tpp_header(pp, encoding, commit, &msg, sb);\n+\tif (pp->fmt != CMIT_FMT_ONELINE && !pp->subject) {\n \t\tstrbuf_addch(sb, '\\n');\n \t}\n \n@@ -1252,17 +1247,16 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n \tmsg = skip_empty_lines(msg);\n \n \t/* These formats treat the title line specially. */\n-\tif (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)\n-\t\tpp_title_line(fmt, &msg, sb, context->subject,\n-\t\t\t      context->after_subject, encoding, need_8bit_cte);\n+\tif (pp->fmt == CMIT_FMT_ONELINE || pp->fmt == CMIT_FMT_EMAIL)\n+\t\tpp_title_line(pp, &msg, sb, encoding, need_8bit_cte);\n \n \tbeginning_of_body = sb->len;\n-\tif (fmt != CMIT_FMT_ONELINE)\n-\t\tpp_remainder(fmt, &msg, sb, indent);\n+\tif (pp->fmt != CMIT_FMT_ONELINE)\n+\t\tpp_remainder(pp, &msg, sb, indent);\n \tstrbuf_rtrim(sb);\n \n \t/* Make sure there is an EOLN for the non-oneline case */\n-\tif (fmt != CMIT_FMT_ONELINE)\n+\tif (pp->fmt != CMIT_FMT_ONELINE)\n \t\tstrbuf_addch(sb, '\\n');\n \n \t/*\n@@ -1270,10 +1264,10 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n \t * format.  Make sure we did not strip the blank line\n \t * between the header and the body.\n \t */\n-\tif (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)\n+\tif (pp->fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)\n \t\tstrbuf_addch(sb, '\\n');\n \n-\tif (context->show_notes)\n+\tif (pp->show_notes)\n \t\tformat_display_notes(commit->object.sha1, sb, encoding,\n \t\t\t\t     NOTES_SHOW_HEADER | NOTES_INDENT);\n \n@@ -1284,5 +1278,6 @@ void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n \t\t    struct strbuf *sb)\n {\n \tstruct pretty_print_context pp = {0};\n-\tpretty_print_commit(fmt, commit, sb, &pp);\n+\tpp.fmt = fmt;\n+\tpretty_print_commit(&pp, commit, sb);\n }\n-- \n1.7.4.5.26.g0c6a2\n"},{"id":"168842","messageId":"20110526222817.GC21775@sigill.intra.peff.net","threadId":"27443","inReplyTo":"20110526222450.GA20077@sigill.intra.peff.net","subject":"[PATCH 5/5] format-patch: preserve subject newlines with -k","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-26T22:28:17Z","receivedAt":"2011-05-26T22:28:17Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"In older versions of git, we used rfc822 header folding to\nindicate that the original subject line had multiple lines\nin it.  But since a1f6baa (format-patch: wrap long header\nlines, 2011-02-23), we now use header folding whenever there\nis a long line.\n\nThis means that \"git am\" cannot trust header folding as a\nsign from format-patch that newlines should be preserved.\nInstead, format-patch needs to signal more explicitly that\nthe newlines are significant.  This patch does so by\nrfc2047-encoding the newlines in the subject line. No\nchanges are needed on the \"git am\" end; it already decodes\nthe newlines properly.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n builtin/log.c          |    1 +\n commit.h               |    1 +\n log-tree.c             |    1 +\n pretty.c               |    3 ++-\n revision.h             |    3 ++-\n t/t4152-am-subjects.sh |    2 +-\n 6 files changed, 8 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 8d842cb..0e46e5a 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1131,6 +1131,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tdie (\"-n and -k are mutually exclusive.\");\n \tif (keep_subject && subject_prefix)\n \t\tdie (\"--subject-prefix and -k are mutually exclusive.\");\n+\trev.preserve_subject = keep_subject;\n \n \targc = setup_revisions(argc, argv, &rev, &s_r_opt);\n \tif (argc > 1)\ndiff --git a/commit.h b/commit.h\nindex 2935740..e985dcc 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -74,6 +74,7 @@ struct pretty_print_context\n \tint abbrev;\n \tconst char *subject;\n \tconst char *after_subject;\n+\tint preserve_subject;\n \tenum date_mode date_mode;\n \tint need_8bit_cte;\n \tint show_notes;\ndiff --git a/log-tree.c b/log-tree.c\nindex 0d8cc7a..0c41789 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -504,6 +504,7 @@ void show_log(struct rev_info *opt)\n \tctx.date_mode = opt->date_mode;\n \tctx.abbrev = opt->diffopt.abbrev;\n \tctx.after_subject = extra_headers;\n+\tctx.preserve_subject = opt->preserve_subject;\n \tctx.reflog_info = opt->reflog_info;\n \tctx.fmt = opt->commit_format;\n \tpretty_print_commit(&ctx, commit, &msgbuf);\ndiff --git a/pretty.c b/pretty.c\nindex f920205..905a082 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1122,7 +1122,8 @@ void pp_title_line(const struct pretty_print_context *pp,\n \tstruct strbuf title;\n \n \tstrbuf_init(&title, 80);\n-\t*msg_p = format_subject(&title, *msg_p, \" \");\n+\t*msg_p = format_subject(&title, *msg_p,\n+\t\t\t\tpp->preserve_subject ? \"\\n\" : \" \");\n \n \tstrbuf_grow(sb, title.len + 1024);\n \tif (pp->subject) {\ndiff --git a/revision.h b/revision.h\nindex 05659c6..f8ddd83 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -90,7 +90,8 @@ struct rev_info {\n \t\t\tabbrev_commit:1,\n \t\t\tuse_terminator:1,\n \t\t\tmissing_newline:1,\n-\t\t\tdate_mode_explicit:1;\n+\t\t\tdate_mode_explicit:1,\n+\t\t\tpreserve_subject:1;\n \tunsigned int\tdisable_stdin:1;\n \n \tenum date_mode date_mode;\ndiff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh\nindex 37e5c03..4c68245 100755\n--- a/t/t4152-am-subjects.sh\n+++ b/t/t4152-am-subjects.sh\n@@ -70,7 +70,7 @@ test_expect_success 'multiline subject unwrapped (format-patch -k | am)' '\n \tcheck_subject multiline-k\n '\n echo \"$MULTILINE_SUBJECT\" >expect\n-test_expect_failure 'multiline subject preserved (format-patch -k | am -k)' '\n+test_expect_success 'multiline subject preserved (format-patch -k | am -k)' '\n \tcheck_subject multiline-k -k\n '\n \n-- \n1.7.4.5.26.g0c6a2\n"},{"id":"168844","messageId":"7v4o4hulj2.fsf@alter.siamese.dyndns.org","threadId":"27443","inReplyTo":"20110526222724.GA21775@sigill.intra.peff.net","subject":"Re: [PATCH 3/5] pretty: add pp_commit_easy function for simple callers","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-26T22:47:29Z","receivedAt":"2011-05-26T22:47:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Many callers don't actually care about the pretty print context at all;\n> let's just give them a simple way of pretty-printing a commit without\n> having to create a context struct.\n\nVery nice ;-).\n"}]}