{"thread":{"id":"18462","subject":"[PATCHv2 1/3] format-patch: create patch filename in one function","startedAt":"2009-03-22T04:32:40Z","lastAt":"2009-03-31T23:24:38Z","messageCount":20,"participants":["Stephen Boyd","Junio C Hamano","René Scharfe"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"108870","messageId":"1237696363-6819-1-git-send-email-bebarino@gmail.com","threadId":"18462","inReplyTo":null,"subject":"[PATCHv2 0/3] format-patch --attach/--inline use filename instead of SHA1","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-22T04:32:40Z","receivedAt":"2009-03-22T04:32:40Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"I'm resending this series because it seems it wasn't picked up probably because\nthe patches were mangled by my mailer.\n\nThis patch series modifies the behavior of format-patch when used with the\n--attach or --inline command line settings. Current behavior names the attached\nor inlined patches with the SHA1 of the commit, which isn't very friendly or\neasy for a human to use when downloading the attachments. This series replaces\nthe SHA1 values with the filename used by format-patch when it outputs the\npatches to files.\n\nStephen Boyd (3):\n  format-patch: create patch filename in one function\n  format-patch: --attach/inline uses filename instead of SHA1\n  format-patch: --numbered-files and --stdout aren't mutually exclusive\n\n Documentation/git-format-patch.txt                 |    1 -\n builtin-log.c                                      |   51 ++++++++--------\n log-tree.c                                         |    8 +-\n revision.h                                         |    1 +\n t/t4013-diff-various.sh                            |    1 +\n ..._--attach_--stdout_--suffix=.diff_initial..side |   61 ++++++++++++++++++++\n ....format-patch_--attach_--stdout_initial..master |   12 ++--\n ...format-patch_--attach_--stdout_initial..master^ |    8 +-\n ...ff.format-patch_--attach_--stdout_initial..side |    4 +-\n ...tdout_--subject-prefix=TESTCASE_initial..master |   12 ++--\n ....format-patch_--inline_--stdout_initial..master |   12 ++--\n ...format-patch_--inline_--stdout_initial..master^ |    8 +-\n ...ormat-patch_--inline_--stdout_initial..master^^ |    4 +-\n ...ff.format-patch_--inline_--stdout_initial..side |    4 +-\n 14 files changed, 124 insertions(+), 63 deletions(-)\n create mode 100644 t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n"},{"id":"108869","messageId":"1237696363-6819-2-git-send-email-bebarino@gmail.com","threadId":"18462","inReplyTo":"1237696363-6819-1-git-send-email-bebarino@gmail.com","subject":"[PATCHv2 1/3] format-patch: create patch filename in one function","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-22T04:32:41Z","receivedAt":"2009-03-22T04:32:41Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"reopen_stdout() usually takes the oneline description of a commit,\nappends the patch suffix, prepends the output directory (if any) and\nthen reopens stdout as the resulting file. Now the patch filename (the\noneline description and the patch suffix) is created in\nget_patch_filename() and passed to reopen_stdout() which prepends the\noutput directory and reopens stdout as that file.\n\nThe original function to get the oneline description,\nget_oneline_for_filename(), has been renamed to get_patch_filename() to\nreflect its new functionality.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n builtin-log.c |   49 +++++++++++++++++++++++++------------------------\n 1 files changed, 25 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 8af55d2..cc6d663 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -519,21 +519,17 @@ static int git_format_config(const char *var, const char *value, void *cb)\n }\n \n \n-static const char *get_oneline_for_filename(struct commit *commit,\n-\t\t\t\t\t    int keep_subject)\n+static const char *get_patch_filename(char* sol, int keep_subject, int nr)\n {\n \tstatic char filename[PATH_MAX];\n-\tchar *sol;\n \tint len = 0;\n \tint suffix_len = strlen(fmt_patch_suffix) + 1;\n \n-\tsol = strstr(commit->buffer, \"\\n\\n\");\n-\tif (!sol)\n-\t\tfilename[0] = '\\0';\n-\telse {\n+\tif (sol)\n+\t{\n \t\tint j, space = 0;\n \n-\t\tsol += 2;\n+\t\tlen += sprintf(filename, \"%04d-\", nr);\n \t\t/* strip [PATCH] or [PATCH blabla] */\n \t\tif (!keep_subject && !prefixcmp(sol, \"[PATCH\")) {\n \t\t\tchar *eos = strchr(sol + 6, ']');\n@@ -564,8 +560,11 @@ static const char *get_oneline_for_filename(struct commit *commit,\n \t\twhile (filename[len - 1] == '.'\n \t\t       || filename[len - 1] == '-')\n \t\t\tlen--;\n-\t\tfilename[len] = '\\0';\n+\t\tstrcpy(filename + len, fmt_patch_suffix);\n \t}\n+\telse\n+\t\tsprintf(filename, \"%d\", nr);\n+\n \treturn filename;\n }\n \n@@ -573,7 +572,7 @@ static FILE *realstdout = NULL;\n static const char *output_directory = NULL;\n static int outdir_offset;\n \n-static int reopen_stdout(const char *oneline, int nr, struct rev_info *rev)\n+static int reopen_stdout(const char *oneline, struct rev_info *rev)\n {\n \tchar filename[PATH_MAX];\n \tint len = 0;\n@@ -588,15 +587,7 @@ static int reopen_stdout(const char *oneline, int nr, struct rev_info *rev)\n \t\tif (filename[len - 1] != '/')\n \t\t\tfilename[len++] = '/';\n \t}\n-\n-\tif (!oneline)\n-\t\tlen += sprintf(filename + len, \"%d\", nr);\n-\telse {\n-\t\tlen += sprintf(filename + len, \"%04d-\", nr);\n-\t\tlen += snprintf(filename + len, sizeof(filename) - len - 1\n-\t\t\t\t- suffix_len, \"%s\", oneline);\n-\t\tstrcpy(filename + len, fmt_patch_suffix);\n-\t}\n+\tstrncpy(filename+len, oneline, PATH_MAX-len-1);\n \n \tif (!DIFF_OPT_TST(&rev->diffopt, QUIET))\n \t\tfprintf(realstdout, \"%s\\n\", filename + outdir_offset);\n@@ -688,8 +679,9 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tif (rev->commit_format != CMIT_FMT_EMAIL)\n \t\tdie(\"Cover letter needs email format\");\n \n-\tif (!use_stdout && reopen_stdout(numbered_files ?\n-\t\t\t\tNULL : \"cover-letter\", 0, rev))\n+\tif (!use_stdout && reopen_stdout(get_patch_filename(numbered_files ?\n+\t\t\t\t\t\t\tNULL : \"cover-letter\",\n+\t\t\t\t\t\t\t0, 0), rev))\n \t\treturn;\n \n \thead_sha1 = sha1_to_hex(head->object.sha1);\n@@ -802,6 +794,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tstruct patch_ids ids;\n \tchar *add_signoff = NULL;\n \tstruct strbuf buf = STRBUF_INIT;\n+\tchar *sol = NULL;\n \n \tgit_config(git_format_config, NULL);\n \tinit_revisions(&rev, prefix);\n@@ -1106,9 +1099,17 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t\t}\n \t\t\tgen_message_id(&rev, sha1_to_hex(commit->object.sha1));\n \t\t}\n-\t\tif (!use_stdout && reopen_stdout(numbered_files ? NULL :\n-\t\t\t\tget_oneline_for_filename(commit, keep_subject),\n-\t\t\t\trev.nr, &rev))\n+\t\t/*\n+\t\t * If we're outputting numbered files we don't need a subject\n+\t\t * line. Otherwise we want the subject line of the commit\n+\t\t * message which starts after the first double newline\n+\t\t * occurence in the commit buffer.\n+\t\t */\n+\t\tif (!numbered_files && (sol = strstr(commit->buffer, \"\\n\\n\")))\n+\t\t\tsol += 2;\n+\t\tif (!use_stdout && reopen_stdout(get_patch_filename(sol,\n+\t\t\t\t\t\t\t\tkeep_subject,\n+\t\t\t\t\t\t\t\trev.nr), &rev))\n \t\t\tdie(\"Failed to create output files\");\n \t\tshown = log_tree_commit(&rev, commit);\n \t\tfree(commit->buffer);\n-- \n1.6.2\n"},{"id":"108872","messageId":"1237696363-6819-3-git-send-email-bebarino@gmail.com","threadId":"18462","inReplyTo":"1237696363-6819-2-git-send-email-bebarino@gmail.com","subject":"[PATCHv2 2/3] format-patch: --attach/inline uses filename instead of SHA1","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-22T04:32:42Z","receivedAt":"2009-03-22T04:32:42Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"Currently when format-patch is used with --attach or --inline the patch\nattachment has the SHA1 of the commit for its filename. This replaces\nthe SHA1 with the filename used by format-patch when outputting to files.\n\nFix tests relying on the SHA1 output and add a test showing how the\n--suffix option affects the attachment filename output.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\nIs modifying the rev_info struct correct?\n\n builtin-log.c                                      |    6 +-\n log-tree.c                                         |    8 +-\n revision.h                                         |    1 +\n t/t4013-diff-various.sh                            |    1 +\n ..._--attach_--stdout_--suffix=.diff_initial..side |   61 ++++++++++++++++++++\n ....format-patch_--attach_--stdout_initial..master |   12 ++--\n ...format-patch_--attach_--stdout_initial..master^ |    8 +-\n ...ff.format-patch_--attach_--stdout_initial..side |    4 +-\n ...tdout_--subject-prefix=TESTCASE_initial..master |   12 ++--\n ....format-patch_--inline_--stdout_initial..master |   12 ++--\n ...format-patch_--inline_--stdout_initial..master^ |    8 +-\n ...ormat-patch_--inline_--stdout_initial..master^^ |    4 +-\n ...ff.format-patch_--inline_--stdout_initial..side |    4 +-\n 13 files changed, 102 insertions(+), 39 deletions(-)\n create mode 100644 t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex cc6d663..8ea25e0 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -1107,9 +1107,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t */\n \t\tif (!numbered_files && (sol = strstr(commit->buffer, \"\\n\\n\")))\n \t\t\tsol += 2;\n-\t\tif (!use_stdout && reopen_stdout(get_patch_filename(sol,\n-\t\t\t\t\t\t\t\tkeep_subject,\n-\t\t\t\t\t\t\t\trev.nr), &rev))\n+\t\trev.fmt_patch_filename = get_patch_filename(sol, keep_subject,\n+\t\t\t\t\t\t\t\trev.nr);\n+\t\tif (!use_stdout && reopen_stdout(rev.fmt_patch_filename, &rev))\n \t\t\tdie(\"Failed to create output files\");\n \t\tshown = log_tree_commit(&rev, commit);\n \t\tfree(commit->buffer);\ndiff --git a/log-tree.c b/log-tree.c\nindex 9565c18..dc37d16 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -245,14 +245,14 @@ void log_write_email_headers(struct rev_info *opt, const char *name,\n \t\tsnprintf(buffer, sizeof(buffer) - 1,\n \t\t\t \"\\n--%s%s\\n\"\n \t\t\t \"Content-Type: text/x-patch;\"\n-\t\t\t \" name=\\\"%s.diff\\\"\\n\"\n+\t\t\t \" name=\\\"%s\\\"\\n\"\n \t\t\t \"Content-Transfer-Encoding: 8bit\\n\"\n \t\t\t \"Content-Disposition: %s;\"\n-\t\t\t \" filename=\\\"%s.diff\\\"\\n\\n\",\n+\t\t\t \" filename=\\\"%s\\\"\\n\\n\",\n \t\t\t mime_boundary_leader, opt->mime_boundary,\n-\t\t\t name,\n+\t\t\t opt->fmt_patch_filename,\n \t\t\t opt->no_inline ? \"attachment\" : \"inline\",\n-\t\t\t name);\n+\t\t\t opt->fmt_patch_filename);\n \t\topt->diffopt.stat_sep = buffer;\n \t}\n \t*subject_p = subject;\ndiff --git a/revision.h b/revision.h\nindex ad123d7..c34eac9 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -86,6 +86,7 @@ struct rev_info {\n \tstruct log_info *loginfo;\n \tint\t\tnr, total;\n \tconst char\t*mime_boundary;\n+\tconst char\t*fmt_patch_filename;\n \tchar\t\t*message_id;\n \tstruct string_list *ref_message_ids;\n \tconst char\t*add_signoff;\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex 426e64e..6592a4f 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -246,6 +246,7 @@ format-patch --stdout initial..master\n format-patch --stdout --no-numbered initial..master\n format-patch --stdout --numbered initial..master\n format-patch --attach --stdout initial..side\n+format-patch --attach --stdout --suffix=.diff initial..side\n format-patch --attach --stdout initial..master^\n format-patch --attach --stdout initial..master\n format-patch --inline --stdout initial..side\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\nnew file mode 100644\nindex 0000000..52116d3\n--- /dev/null\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n@@ -0,0 +1,61 @@\n+$ git format-patch --attach --stdout --suffix=.diff initial..side\n+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001\n+From: A U Thor <author@example.com>\n+Date: Mon, 26 Jun 2006 00:03:00 +0000\n+Subject: [PATCH] Side\n+MIME-Version: 1.0\n+Content-Type: multipart/mixed; boundary=\"------------g-i-t--v-e-r-s-i-o-n\"\n+\n+This is a multi-part message in MIME format.\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/plain; charset=UTF-8; format=fixed\n+Content-Transfer-Encoding: 8bit\n+\n+---\n+ dir/sub |    2 ++\n+ file0   |    3 +++\n+ file3   |    4 ++++\n+ 3 files changed, 9 insertions(+), 0 deletions(-)\n+ create mode 100644 file3\n+\n+\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/x-patch; name=\"0001-Side.diff\"\n+Content-Transfer-Encoding: 8bit\n+Content-Disposition: attachment; filename=\"0001-Side.diff\"\n+\n+diff --git a/dir/sub b/dir/sub\n+index 35d242b..7289e35 100644\n+--- a/dir/sub\n++++ b/dir/sub\n+@@ -1,2 +1,4 @@\n+ A\n+ B\n++1\n++2\n+diff --git a/file0 b/file0\n+index 01e79c3..f4615da 100644\n+--- a/file0\n++++ b/file0\n+@@ -1,3 +1,6 @@\n+ 1\n+ 2\n+ 3\n++A\n++B\n++C\n+diff --git a/file3 b/file3\n+new file mode 100644\n+index 0000000..7289e35\n+--- /dev/null\n++++ b/file3\n+@@ -0,0 +1,4 @@\n++A\n++B\n++1\n++2\n+\n+--------------g-i-t--v-e-r-s-i-o-n--\n+\n+\n+$\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master\nindex e5ab744..ce49bd6 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: attachment; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: attachment; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\n@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0003-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: attachment; filename=\"0003-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\nindex 2c71d20..5f1b238 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: attachment; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: attachment; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side\nindex 38f7902..4a2364a 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side\n@@ -20,9 +20,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0001-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: attachment; filename=\"0001-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\nindex 58f8a7b..ca3f60b 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: inline; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: inline; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\n@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0003-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: inline; filename=\"0003-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master\nindex 9e7bbdf..08f2301 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: inline; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: inline; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\n@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0003-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: inline; filename=\"0003-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\nindex f881f64..07f1230 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: inline; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: inline; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\nindex 4f258b8..29e00ab 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: inline; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side\nindex e86dce6..67633d4 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side\n@@ -20,9 +20,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0001-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: inline; filename=\"0001-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\n-- \n1.6.2\n"},{"id":"108871","messageId":"1237696363-6819-4-git-send-email-bebarino@gmail.com","threadId":"18462","inReplyTo":"1237696363-6819-3-git-send-email-bebarino@gmail.com","subject":"[PATCHv2 3/3] format-patch: --numbered-files and --stdout aren't mutually exclusive","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-22T04:32:43Z","receivedAt":"2009-03-22T04:32:43Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"For example:\n\n    git format-patch --numbered-files --stdout --attach HEAD~~\n\nwill create two messages with files 1 and 2 attached respectively.\nThere is no effect when using --numbered-files and --stdout together\nwithout an --attach or --inline, the files simply aren't created.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n Documentation/git-format-patch.txt |    1 -\n builtin-log.c                      |    2 --\n 2 files changed, 0 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex c14e3ee..c2eb5fa 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -97,7 +97,6 @@ include::diff-options.txt[]\n --numbered-files::\n \tOutput file names will be a simple number sequence\n \twithout the default first line of the commit appended.\n-\tMutually exclusive with the --stdout option.\n \n -k::\n --keep-subject::\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 8ea25e0..f81d3a3 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -951,8 +951,6 @@ 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-\tif (numbered_files && use_stdout)\n-\t\tdie (\"--numbered-files and --stdout are mutually exclusive.\");\n \n \targc = setup_revisions(argc, argv, &rev, \"HEAD\");\n \tif (argc > 1)\n-- \n1.6.2\n"},{"id":"108874","messageId":"7vwsai86nw.fsf@gitster.siamese.dyndns.org","threadId":"18462","inReplyTo":"1237696363-6819-2-git-send-email-bebarino@gmail.com","subject":"Re: [PATCHv2 1/3] format-patch: create patch filename in one function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-22T05:31:47Z","receivedAt":"2009-03-22T05:31:47Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephen Boyd <bebarino@gmail.com> writes:\n\n> reopen_stdout() usually takes the oneline description of a commit,\n> appends the patch suffix, prepends the output directory (if any) and\n> then reopens stdout as the resulting file. Now the patch filename (the\n> oneline description and the patch suffix) is created in\n> get_patch_filename() and passed to reopen_stdout() which prepends the\n> output directory and reopens stdout as that file.\n\nThe renaming is a good idea even without any change in the feature.\nNaming functions after what their result is used _for_ is never a good\nidea, and we should name them after what they do.\n\nDoes it still make sense to pass \"keep_subject\" to the function?  After\nall what it does is to retain \"[PATCH..\" prefix that is useless for the\npurpose of making each patch easily identifiable.  Because people almost\nalways use patch acceptance tools in non-keep mode to strip the\n\"[PATCH..]\"  prefix when creating the commits these days anyway, it may\nmake more sense to lose the parameter altogether and simplify the\nprocessing.\n\n> -static const char *get_oneline_for_filename(struct commit *commit,\n> -\t\t\t\t\t    int keep_subject)\n> +static const char *get_patch_filename(char* sol, int keep_subject, int nr)\n\nAsterisk sticks to the variable name, not type name.\n\nI also wonder if it makes sense to move what this function does into a\nuser format; especially the logic that sanitizes the oneline string into\nfilename friendly one may be something Porcelains may want an access to\nfrom outside.\n\nIOW, you can introduce a new format specifier (say, \"%f\") to\nformat_commit_message() and the implemention of get_patch_filename() would\njust prepare a strbuf and call format_commit_message() on it, no?\n"},{"id":"108875","messageId":"7vr60q86gp.fsf@gitster.siamese.dyndns.org","threadId":"18462","inReplyTo":"1237696363-6819-3-git-send-email-bebarino@gmail.com","subject":"Re: [PATCHv2 2/3] format-patch: --attach/inline uses filename instead of SHA1","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-22T05:36:06Z","receivedAt":"2009-03-22T05:36:06Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephen Boyd <bebarino@gmail.com> writes:\n\n> Currently when format-patch is used with --attach or --inline the patch\n> attachment has the SHA1 of the commit for its filename. This replaces\n> the SHA1 with the filename used by format-patch when outputting to files.\n>\n> Fix tests relying on the SHA1 output and add a test showing how the\n> --suffix option affects the attachment filename output.\n>\n> Signed-off-by: Stephen Boyd <bebarino@gmail.com>\n> ---\n> Is modifying the rev_info struct correct?\n\nMost of the rev_info is about the overall traversal not about individual\ncommits, and I think the new field you are adding is about a single commit\nyou will update every time you switch to a new commit to process, so in\nthat sense it may violate the general idea of what rev-info is, but I do\nnot think it matters too much.\n"},{"id":"108876","messageId":"7vljqy8622.fsf@gitster.siamese.dyndns.org","threadId":"18462","inReplyTo":"1237696363-6819-4-git-send-email-bebarino@gmail.com","subject":"Re: [PATCHv2 3/3] format-patch: --numbered-files and --stdout aren't mutually exclusive","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-22T05:44:53Z","receivedAt":"2009-03-22T05:44:53Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephen Boyd <bebarino@gmail.com> writes:\n\n> For example:\n>\n>     git format-patch --numbered-files --stdout --attach HEAD~~\n>\n> will create two messages with files 1 and 2 attached respectively.\n> There is no effect when using --numbered-files and --stdout together\n> without an --attach or --inline, the files simply aren't created.\n\nHmm, \"the files aren't created\" is true, but I had to scratch my head if\nyou are describing a bug or justifying the change by saying \"so filename\ndoes not matter\".\n\nI think the change makes sense.  It could be argued that combination of\nthese two options should give a warning(\"ignoring --numbered\"), but I do\nnot think it is even worth it.\n"},{"id":"108877","messageId":"49C5D3BC.3030100@gmail.com","threadId":"18462","inReplyTo":"7vwsai86nw.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCHv2 1/3] format-patch: create patch filename in one function","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-22T05:59:24Z","receivedAt":"2009-03-22T05:59:24Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"Junio C Hamano wrote:\n> The renaming is a good idea even without any change in the feature.\n> Naming functions after what their result is used _for_ is never a good\n> idea, and we should name them after what they do.\n>\n> Does it still make sense to pass \"keep_subject\" to the function?  After\n> all what it does is to retain \"[PATCH..\" prefix that is useless for the\n> purpose of making each patch easily identifiable.  Because people almost\n> always use patch acceptance tools in non-keep mode to strip the\n> \"[PATCH..]\"  prefix when creating the commits these days anyway, it may\n> make more sense to lose the parameter altogether and simplify the\n> processing.\n\nI originally removed \"keep_subject\" but I took it out because I couldn't\nfigure out what it was being used for and I thought it might be\nimportant. When it's removed all the tests pass. It's not even used by\nother code besides a few if cases regarding numbering logic so I think\nthe entire command line switch could be removed.\n\n>\n> I also wonder if it makes sense to move what this function does into a\n> user format; especially the logic that sanitizes the oneline string into\n> filename friendly one may be something Porcelains may want an access to\n> from outside.\n>\n> IOW, you can introduce a new format specifier (say, \"%f\") to\n> format_commit_message() and the implemention of get_patch_filename() would\n> just prepare a strbuf and call format_commit_message() on it, no?\n\nThis sounds great! I'm new so I don't know where to look for something\nlike this.\n"},{"id":"108881","messageId":"7veiwq82wc.fsf@gitster.siamese.dyndns.org","threadId":"18462","inReplyTo":"49C5D3BC.3030100@gmail.com","subject":"Re: [PATCHv2 1/3] format-patch: create patch filename in one function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-22T06:53:07Z","receivedAt":"2009-03-22T06:53:07Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephen Boyd <bebarino@gmail.com> writes:\n\n> Junio C Hamano wrote:\n> ...\n>> IOW, you can introduce a new format specifier (say, \"%f\") to\n>> format_commit_message() and the implemention of get_patch_filename() would\n>> just prepare a strbuf and call format_commit_message() on it, no?\n>\n> This sounds great! I'm new so I don't know where to look for something\n> like this.\n\nI suspect you may not even have to pass the generated string around if you\ndid so.  Instead, you could pass the commit to log_write_email_headers()\ninstead of sha1_to_hex(commit->object.sha1) from show_log(), and use the\nsha-1on the unix \"From \" line, and inside \"if (opt->mime_boundar)\", you\ncan ask format_commit_message(\"%f\") to come up with a filename.\n"},{"id":"108882","messageId":"49C5E113.3020601@gmail.com","threadId":"18462","inReplyTo":"7veiwq82wc.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCHv2 1/3] format-patch: create patch filename in one function","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-22T06:56:19Z","receivedAt":"2009-03-22T06:56:19Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"Junio C Hamano wrote:\n> Stephen Boyd <bebarino@gmail.com> writes:\n>\n>> Junio C Hamano wrote:\n>> ...\n>>> IOW, you can introduce a new format specifier (say, \"%f\") to\n>>> format_commit_message() and the implemention of get_patch_filename() would\n>>> just prepare a strbuf and call format_commit_message() on it, no?\n>> This sounds great! I'm new so I don't know where to look for something\n>> like this.\n>\n> I suspect you may not even have to pass the generated string around if you\n> did so.  Instead, you could pass the commit to log_write_email_headers()\n> instead of sha1_to_hex(commit->object.sha1) from show_log(), and use the\n> sha-1on the unix \"From \" line, and inside \"if (opt->mime_boundar)\", you\n> can ask format_commit_message(\"%f\") to come up with a filename.\n\nI believe I won't be able to get the patch suffix at that point in the\ncode. Unless I decide to add that to the rev_info instead?\n"},{"id":"108885","messageId":"7v1vsq7zgd.fsf@gitster.siamese.dyndns.org","threadId":"18462","inReplyTo":"49C5E113.3020601@gmail.com","subject":"Re: [PATCHv2 1/3] format-patch: create patch filename in one function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-22T08:07:30Z","receivedAt":"2009-03-22T08:07:30Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephen Boyd <bebarino@gmail.com> writes:\n\n> Junio C Hamano wrote:\n>> Stephen Boyd <bebarino@gmail.com> writes:\n>>\n>>> Junio C Hamano wrote:\n>>> ...\n>>>> IOW, you can introduce a new format specifier (say, \"%f\") to\n>>>> format_commit_message() and the implemention of get_patch_filename() would\n>>>> just prepare a strbuf and call format_commit_message() on it, no?\n>>> This sounds great! I'm new so I don't know where to look for something\n>>> like this.\n>>\n>> I suspect you may not even have to pass the generated string around if you\n>> did so.  Instead, you could pass the commit to log_write_email_headers()\n>> instead of sha1_to_hex(commit->object.sha1) from show_log(), and use the\n>> sha-1on the unix \"From \" line, and inside \"if (opt->mime_boundar)\", you\n>> can ask format_commit_message(\"%f\") to come up with a filename.\n>\n> I believe I won't be able to get the patch suffix at that point in the\n> code. Unless I decide to add that to the rev_info instead?\n\nYeah, and I think that won't be \"per commit\" but \"the same across the\ntraversal controlled by that rev_info\", which is more in line with what\nrev_info is about ;-)\n"},{"id":"108983","messageId":"cover.1237773604.git.bebarino@gmail.com","threadId":"18462","inReplyTo":"1237696363-6819-1-git-send-email-bebarino@gmail.com","subject":"[PATCHv3 0/6] format-patch --attach/--inline uses filename not SHA1","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-23T02:14:00Z","receivedAt":"2009-03-23T02:14:00Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"This patch series modifies the behavior of format-patch when used with the\n--attach or --inline command line settings. Current behavior names the attached\nor inlined patches with the SHA1 of the commit, which isn't very friendly or\neasy for a human to use when downloading the attachments. This series replaces\nthe SHA1 values with the filename used by format-patch when it outputs the\npatches to files.\n\nNew features in this version: \n    - %f format specifier exposing sanitized filenames to porcelain\n    - get_patch_filename() moved to log-tree\n\nStephen Boyd (6):\n  pretty.c: add %f format specifier to format_commit_message()\n  format-patch: construct patch filename in one function\n  format-patch: pass a commit to reopen_stdout()\n  format-patch: move get_patch_filename() into log-tree\n  format-patch: --attach/inline uses filename instead of SHA1\n  format-patch: --numbered-files and --stdout aren't mutually exclusive\n\n Documentation/pretty-formats.txt                   |    1 +\n builtin-log.c                                      |  132 +++++----------\n log-tree.c                                         |   41 ++++-\n log-tree.h                                         |    6 +-\n pretty.c                                           |   38 +++++\n revision.h                                         |    2 +\n t/t4013-diff-various.sh                            |    3 +-\n ..._--attach_--stdout_--suffix=.diff_initial..side |   61 +++++++\n ....format-patch_--attach_--stdout_initial..master |   12 +-\n ...format-patch_--attach_--stdout_initial..master^ |    8 +-\n ...ff.format-patch_--attach_--stdout_initial..side |    4 +-\n ...nline_--stdout_--numbered-files_initial..master |  170 ++++++++++++++++++++\n ...tdout_--subject-prefix=TESTCASE_initial..master |   12 +-\n ....format-patch_--inline_--stdout_initial..master |   12 +-\n ...format-patch_--inline_--stdout_initial..master^ |    8 +-\n ...ormat-patch_--inline_--stdout_initial..master^^ |    4 +-\n ...ff.format-patch_--inline_--stdout_initial..side |    4 +-\n 17 files changed, 389 insertions(+), 129 deletions(-)\n create mode 100644 t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n create mode 100644 t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\n"},{"id":"108987","messageId":"baa327d88b54efae40b6d9df09a2fe482672101e.1237773604.git.bebarino@gmail.com","threadId":"18462","inReplyTo":"cover.1237773604.git.bebarino@gmail.com","subject":"[PATCHv3 1/6] pretty.c: add %f format specifier to format_commit_message()","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-23T02:14:01Z","receivedAt":"2009-03-23T02:14:01Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"This specifier represents the sanitized and filename friendly subject\nline of a commit. No checks are made against the length of the string,\nso users may need to trim the result to the desired length if using as a\nfilename. This is commonly used by format-patch to massage commit\nsubjects into filenames and output patches to files.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n Documentation/pretty-formats.txt |    1 +\n pretty.c                         |   38 ++++++++++++++++++++++++++++++++++++++\n 2 files changed, 39 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 5c6e678..2a845b1 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -121,6 +121,7 @@ The placeholders are:\n - '%d': ref names, like the --decorate option of linkgit:git-log[1]\n - '%e': encoding\n - '%s': subject\n+- '%f': sanitized subject line, suitable for a filename\n - '%b': body\n - '%Cred': switch color to red\n - '%Cgreen': switch color to green\ndiff --git a/pretty.c b/pretty.c\nindex efa7024..97de415 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -493,6 +493,41 @@ static void parse_commit_header(struct format_commit_context *context)\n \tcontext->commit_header_parsed = 1;\n }\n \n+static int istitlechar(char c)\n+{\n+\treturn (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||\n+\t\t(c >= '0' && c <= '9') || c == '.' || c == '_';\n+}\n+\n+static void format_sanitized_subject(struct strbuf *sb, const char *msg)\n+{\n+\tsize_t trimlen;\n+\tint space = 0;\n+\n+\tfor (; *msg && *msg != '\\n'; msg++) {\n+\t\tif (istitlechar(*msg))\n+\t\t{\n+\t\t    if (space) {\n+\t\t\tstrbuf_addch(sb, '-');\n+\t\t\tspace = 0;\n+\t\t    }\n+\t\t    strbuf_addch(sb, *msg);\n+\t\t    if (*msg == '.')\n+\t\t\twhile (*(msg+1) == '.')\n+\t\t\t\tmsg++;\n+\t\t}\n+\t\telse\n+\t\t\tspace = 1;\n+\t}\n+\n+\t// trim any trailing '.' or '-' characters\n+\ttrimlen = 0;\n+\twhile (sb->buf[sb->len - 1 - trimlen] == '.'\n+\t\t|| sb->buf[sb->len - 1 - trimlen] == '-')\n+\t\ttrimlen++;\n+\tstrbuf_remove(sb, sb->len - trimlen, trimlen);\n+}\n+\n const char *format_subject(struct strbuf *sb, const char *msg,\n \t\t\t   const char *line_separator)\n {\n@@ -683,6 +718,9 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \tcase 's':\t/* subject */\n \t\tformat_subject(sb, msg + c->subject_off, \" \");\n \t\treturn 1;\n+\tcase 'f':\t/* sanitized subject */\n+\t\tformat_sanitized_subject(sb, msg + c->subject_off);\n+\t\treturn 1;\n \tcase 'b':\t/* body */\n \t\tstrbuf_addstr(sb, msg + c->body_off);\n \t\treturn 1;\n-- \n1.6.2\n"},{"id":"108986","messageId":"616420f398701fafc45b5d5cebb1371534f88caa.1237773604.git.bebarino@gmail.com","threadId":"18462","inReplyTo":"baa327d88b54efae40b6d9df09a2fe482672101e.1237773604.git.bebarino@gmail.com","subject":"[PATCHv3 2/6] format-patch: construct patch filename in one function","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-23T02:14:02Z","receivedAt":"2009-03-23T02:14:02Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"reopen_stdout() usually takes the oneline subject of a commit,\nappends the patch suffix, prepends the output directory (if any) and\nthen reopens stdout as the resulting file. Now the patch filename (the\noneline subject and the patch suffix) is created in\nget_patch_filename() and passed to reopen_stdout() which prepends the\noutput directory and reopens stdout as that file.\n\nThe original function to get the oneline description,\nget_oneline_for_filename(), has been renamed to get_patch_filename() to\nreflect its new functionality.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n builtin-log.c |   99 +++++++++++++++++++-------------------------------------\n 1 files changed, 34 insertions(+), 65 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex c7a5772..54ef248 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -419,12 +419,6 @@ int cmd_log(int argc, const char **argv, const char *prefix)\n /* format-patch */\n #define FORMAT_PATCH_NAME_MAX 64\n \n-static int istitlechar(char c)\n-{\n-\treturn (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||\n-\t\t(c >= '0' && c <= '9') || c == '.' || c == '_';\n-}\n-\n static const char *fmt_patch_suffix = \".patch\";\n static int numbered = 0;\n static int auto_number = 1;\n@@ -519,61 +513,34 @@ static int git_format_config(const char *var, const char *value, void *cb)\n }\n \n \n-static const char *get_oneline_for_filename(struct commit *commit,\n-\t\t\t\t\t    int keep_subject)\n+static void get_patch_filename(struct commit *commit, int nr,\n+\t\t\t       const char *suffix, struct strbuf *buf)\n {\n-\tstatic char filename[PATH_MAX];\n-\tchar *sol;\n-\tint len = 0;\n-\tint suffix_len = strlen(fmt_patch_suffix) + 1;\n-\n-\tsol = strstr(commit->buffer, \"\\n\\n\");\n-\tif (!sol)\n-\t\tfilename[0] = '\\0';\n-\telse {\n-\t\tint j, space = 0;\n-\n-\t\tsol += 2;\n-\t\t/* strip [PATCH] or [PATCH blabla] */\n-\t\tif (!keep_subject && !prefixcmp(sol, \"[PATCH\")) {\n-\t\t\tchar *eos = strchr(sol + 6, ']');\n-\t\t\tif (eos) {\n-\t\t\t\twhile (isspace(*eos))\n-\t\t\t\t\teos++;\n-\t\t\t\tsol = eos;\n-\t\t\t}\n-\t\t}\n+\tint suffix_len = strlen(suffix) + 1;\n+\tint start_len = buf->len;\n \n-\t\tfor (j = 0;\n-\t\t     j < FORMAT_PATCH_NAME_MAX - suffix_len - 5 &&\n-\t\t\t     len < sizeof(filename) - suffix_len &&\n-\t\t\t     sol[j] && sol[j] != '\\n';\n-\t\t     j++) {\n-\t\t\tif (istitlechar(sol[j])) {\n-\t\t\t\tif (space) {\n-\t\t\t\t\tfilename[len++] = '-';\n-\t\t\t\t\tspace = 0;\n-\t\t\t\t}\n-\t\t\t\tfilename[len++] = sol[j];\n-\t\t\t\tif (sol[j] == '.')\n-\t\t\t\t\twhile (sol[j + 1] == '.')\n-\t\t\t\t\t\tj++;\n-\t\t\t} else\n-\t\t\t\tspace = 1;\n-\t\t}\n-\t\twhile (filename[len - 1] == '.'\n-\t\t       || filename[len - 1] == '-')\n-\t\t\tlen--;\n-\t\tfilename[len] = '\\0';\n+\tstrbuf_addf(buf, commit ? \"%04d-\" : \"%d\", nr);\n+\tif (commit)\n+\t{\n+\t\tformat_commit_message(commit, \"%f\", buf, DATE_NORMAL);\n+\t\t/*\n+\t\t * Replace characters at the end with the suffix if the the\n+\t\t * filename is too long\n+\t\t */\n+\t\tif (buf->len + suffix_len > FORMAT_PATCH_NAME_MAX + start_len)\n+\t\t\tstrbuf_splice(buf,\n+\t\t\t\tstart_len + FORMAT_PATCH_NAME_MAX - suffix_len,\n+\t\t\t\tsuffix_len, suffix, suffix_len);\n+\t\telse\n+\t\t\tstrbuf_addstr(buf, suffix);\n \t}\n-\treturn filename;\n }\n \n static FILE *realstdout = NULL;\n static const char *output_directory = NULL;\n static int outdir_offset;\n \n-static int reopen_stdout(const char *oneline, int nr, struct rev_info *rev)\n+static int reopen_stdout(const char *oneline, struct rev_info *rev)\n {\n \tchar filename[PATH_MAX];\n \tint len = 0;\n@@ -589,14 +556,7 @@ static int reopen_stdout(const char *oneline, int nr, struct rev_info *rev)\n \t\t\tfilename[len++] = '/';\n \t}\n \n-\tif (!oneline)\n-\t\tlen += sprintf(filename + len, \"%d\", nr);\n-\telse {\n-\t\tlen += sprintf(filename + len, \"%04d-\", nr);\n-\t\tlen += snprintf(filename + len, sizeof(filename) - len - 1\n-\t\t\t\t- suffix_len, \"%s\", oneline);\n-\t\tstrcpy(filename + len, fmt_patch_suffix);\n-\t}\n+\tstrncpy(filename + len, oneline, PATH_MAX - len);\n \n \tif (!DIFF_OPT_TST(&rev->diffopt, QUIET))\n \t\tfprintf(realstdout, \"%s\\n\", filename + outdir_offset);\n@@ -684,12 +644,17 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tconst char *encoding = \"utf-8\";\n \tstruct diff_options opts;\n \tint need_8bit_cte = 0;\n+\tchar filename[PATH_MAX];\n \n \tif (rev->commit_format != CMIT_FMT_EMAIL)\n \t\tdie(\"Cover letter needs email format\");\n \n-\tif (!use_stdout && reopen_stdout(numbered_files ?\n-\t\t\t\tNULL : \"cover-letter\", 0, rev))\n+\tif (numbered_files)\n+\t    sprintf(filename, \"0\");\n+\telse\n+\t    sprintf(filename, \"%04d-cover-letter%s\", 0, fmt_patch_suffix);\n+\n+\tif (!use_stdout && reopen_stdout(filename, rev))\n \t\treturn;\n \n \thead_sha1 = sha1_to_hex(head->object.sha1);\n@@ -802,6 +767,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tstruct patch_ids ids;\n \tchar *add_signoff = NULL;\n \tstruct strbuf buf = STRBUF_INIT;\n+\tstruct strbuf patch_filename = STRBUF_INIT;\n \n \tgit_config(git_format_config, NULL);\n \tinit_revisions(&rev, prefix);\n@@ -1104,10 +1070,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t\t}\n \t\t\tgen_message_id(&rev, sha1_to_hex(commit->object.sha1));\n \t\t}\n-\t\tif (!use_stdout && reopen_stdout(numbered_files ? NULL :\n-\t\t\t\tget_oneline_for_filename(commit, keep_subject),\n-\t\t\t\trev.nr, &rev))\n+\n+\t\tget_patch_filename(numbered_files ? NULL : commit, rev.nr,\n+\t\t\t\t    fmt_patch_suffix, &patch_filename);\n+\t\tif (!use_stdout && reopen_stdout(patch_filename.buf, &rev))\n \t\t\tdie(\"Failed to create output files\");\n+\t\tstrbuf_setlen(&patch_filename, 0);\n \t\tshown = log_tree_commit(&rev, commit);\n \t\tfree(commit->buffer);\n \t\tcommit->buffer = NULL;\n@@ -1131,6 +1099,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tif (!use_stdout)\n \t\t\tfclose(stdout);\n \t}\n+\tstrbuf_release(&patch_filename);\n \tfree(list);\n \tif (ignore_if_in_upstream)\n \t\tfree_patch_ids(&ids);\n-- \n1.6.2\n"},{"id":"108985","messageId":"00c4e51c2ff7786be6aedb4a451b8d1ff269d7b3.1237773604.git.bebarino@gmail.com","threadId":"18462","inReplyTo":"616420f398701fafc45b5d5cebb1371534f88caa.1237773604.git.bebarino@gmail.com","subject":"[PATCHv3 3/6] format-patch: pass a commit to reopen_stdout()","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-23T02:14:03Z","receivedAt":"2009-03-23T02:14:03Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"We use the commit to generate the patch filename in reopen_stdout()\nbefore we redirect stdout. The cover letter codepath creates a dummy\ncommit with the desired subject line 'cover letter'.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n builtin-log.c |   68 +++++++++++++++++++++++++++++++++-----------------------\n 1 files changed, 40 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 54ef248..392b16a 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -540,30 +540,29 @@ static FILE *realstdout = NULL;\n static const char *output_directory = NULL;\n static int outdir_offset;\n \n-static int reopen_stdout(const char *oneline, struct rev_info *rev)\n+static int reopen_stdout(struct commit *commit, struct rev_info *rev)\n {\n-\tchar filename[PATH_MAX];\n-\tint len = 0;\n+\tstruct strbuf filename = STRBUF_INIT;\n \tint suffix_len = strlen(fmt_patch_suffix) + 1;\n \n \tif (output_directory) {\n-\t\tlen = snprintf(filename, sizeof(filename), \"%s\",\n-\t\t\t\toutput_directory);\n-\t\tif (len >=\n-\t\t    sizeof(filename) - FORMAT_PATCH_NAME_MAX - suffix_len)\n+\t\tstrbuf_addstr(&filename, output_directory);\n+\t\tif (filename.len >=\n+\t\t    PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len)\n \t\t\treturn error(\"name of output directory is too long\");\n-\t\tif (filename[len - 1] != '/')\n-\t\t\tfilename[len++] = '/';\n+\t\tif (filename.buf[filename.len - 1] != '/')\n+\t\t\tstrbuf_addch(&filename, '/');\n \t}\n \n-\tstrncpy(filename + len, oneline, PATH_MAX - len);\n+\tget_patch_filename(commit, rev->nr, fmt_patch_suffix, &filename);\n \n \tif (!DIFF_OPT_TST(&rev->diffopt, QUIET))\n-\t\tfprintf(realstdout, \"%s\\n\", filename + outdir_offset);\n+\t\tfprintf(realstdout, \"%s\\n\", filename.buf + outdir_offset);\n \n-\tif (freopen(filename, \"w\", stdout) == NULL)\n-\t\treturn error(\"Cannot open patch file %s\",filename);\n+\tif (freopen(filename.buf, \"w\", stdout) == NULL)\n+\t\treturn error(\"Cannot open patch file %s\", filename.buf);\n \n+\tstrbuf_release(&filename);\n \treturn 0;\n }\n \n@@ -644,26 +643,43 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tconst char *encoding = \"utf-8\";\n \tstruct diff_options opts;\n \tint need_8bit_cte = 0;\n-\tchar filename[PATH_MAX];\n+\tstruct commit *commit = NULL;\n \n \tif (rev->commit_format != CMIT_FMT_EMAIL)\n \t\tdie(\"Cover letter needs email format\");\n \n-\tif (numbered_files)\n-\t    sprintf(filename, \"0\");\n-\telse\n-\t    sprintf(filename, \"%04d-cover-letter%s\", 0, fmt_patch_suffix);\n+\tcommitter = git_committer_info(0);\n+\thead_sha1 = sha1_to_hex(head->object.sha1);\n+\n+\tif (!numbered_files)\n+\t{\n+\t\t/*\n+\t\t * We fake a commit for the cover letter so we get the filename\n+\t\t * desired.\n+\t\t */\n+\t\tcommit = xcalloc(1, sizeof(*commit));\n+\t\tcommit->buffer = xmalloc(400);\n+\t\tsnprintf(commit->buffer, 400,\n+\t\t\t\"tree 0000000000000000000000000000000000000000\\n\"\n+\t\t\t\"parent %s\\n\"\n+\t\t\t\"author %s\\n\"\n+\t\t\t\"committer %s\\n\\n\"\n+\t\t\t\"cover letter\\n\",\n+\t\t\thead_sha1, committer, committer);\n+\t}\n \n-\tif (!use_stdout && reopen_stdout(filename, rev))\n+\tif (!use_stdout && reopen_stdout(commit, rev))\n \t\treturn;\n \n-\thead_sha1 = sha1_to_hex(head->object.sha1);\n+\tif (commit)\n+\t{\n+\t\tfree(commit->buffer);\n+\t\tfree(commit);\n+\t}\n \n \tlog_write_email_headers(rev, head_sha1, &subject_start, &extra_headers,\n \t\t\t\t&need_8bit_cte);\n \n-\tcommitter = git_committer_info(0);\n-\n \tmsg = body;\n \tpp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,\n \t\t     encoding);\n@@ -767,7 +783,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tstruct patch_ids ids;\n \tchar *add_signoff = NULL;\n \tstruct strbuf buf = STRBUF_INIT;\n-\tstruct strbuf patch_filename = STRBUF_INIT;\n \n \tgit_config(git_format_config, NULL);\n \tinit_revisions(&rev, prefix);\n@@ -1071,11 +1086,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\t\tgen_message_id(&rev, sha1_to_hex(commit->object.sha1));\n \t\t}\n \n-\t\tget_patch_filename(numbered_files ? NULL : commit, rev.nr,\n-\t\t\t\t    fmt_patch_suffix, &patch_filename);\n-\t\tif (!use_stdout && reopen_stdout(patch_filename.buf, &rev))\n+\t\tif (!use_stdout && reopen_stdout(numbered_files ? NULL : commit,\n+\t\t\t\t\t\t &rev))\n \t\t\tdie(\"Failed to create output files\");\n-\t\tstrbuf_setlen(&patch_filename, 0);\n \t\tshown = log_tree_commit(&rev, commit);\n \t\tfree(commit->buffer);\n \t\tcommit->buffer = NULL;\n@@ -1099,7 +1112,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tif (!use_stdout)\n \t\t\tfclose(stdout);\n \t}\n-\tstrbuf_release(&patch_filename);\n \tfree(list);\n \tif (ignore_if_in_upstream)\n \t\tfree_patch_ids(&ids);\n-- \n1.6.2\n"},{"id":"108984","messageId":"e8e0dcc738decb5f70dbc8e835263d7dc2834407.1237773604.git.bebarino@gmail.com","threadId":"18462","inReplyTo":"00c4e51c2ff7786be6aedb4a451b8d1ff269d7b3.1237773604.git.bebarino@gmail.com","subject":"[PATCHv3 4/6] format-patch: move get_patch_filename() into log-tree","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-23T02:14:04Z","receivedAt":"2009-03-23T02:14:04Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"Signed-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n builtin-log.c |   25 -------------------------\n log-tree.c    |   23 +++++++++++++++++++++++\n log-tree.h    |    4 ++++\n 3 files changed, 27 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 392b16a..a8d6037 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -417,7 +417,6 @@ int cmd_log(int argc, const char **argv, const char *prefix)\n }\n \n /* format-patch */\n-#define FORMAT_PATCH_NAME_MAX 64\n \n static const char *fmt_patch_suffix = \".patch\";\n static int numbered = 0;\n@@ -512,30 +511,6 @@ static int git_format_config(const char *var, const char *value, void *cb)\n \treturn git_log_config(var, value, cb);\n }\n \n-\n-static void get_patch_filename(struct commit *commit, int nr,\n-\t\t\t       const char *suffix, struct strbuf *buf)\n-{\n-\tint suffix_len = strlen(suffix) + 1;\n-\tint start_len = buf->len;\n-\n-\tstrbuf_addf(buf, commit ? \"%04d-\" : \"%d\", nr);\n-\tif (commit)\n-\t{\n-\t\tformat_commit_message(commit, \"%f\", buf, DATE_NORMAL);\n-\t\t/*\n-\t\t * Replace characters at the end with the suffix if the the\n-\t\t * filename is too long\n-\t\t */\n-\t\tif (buf->len + suffix_len > FORMAT_PATCH_NAME_MAX + start_len)\n-\t\t\tstrbuf_splice(buf,\n-\t\t\t\tstart_len + FORMAT_PATCH_NAME_MAX - suffix_len,\n-\t\t\t\tsuffix_len, suffix, suffix_len);\n-\t\telse\n-\t\t\tstrbuf_addstr(buf, suffix);\n-\t}\n-}\n-\n static FILE *realstdout = NULL;\n static const char *output_directory = NULL;\n static int outdir_offset;\ndiff --git a/log-tree.c b/log-tree.c\nindex 9565c18..9a790ab 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -179,6 +179,29 @@ static int has_non_ascii(const char *s)\n \treturn 0;\n }\n \n+void get_patch_filename(struct commit *commit, int nr, const char *suffix,\n+\t\t\tstruct strbuf *buf)\n+{\n+\tint suffix_len = strlen(suffix) + 1;\n+\tint start_len = buf->len;\n+\n+\tstrbuf_addf(buf, commit ? \"%04d-\" : \"%d\", nr);\n+\tif (commit)\n+\t{\n+\t\tformat_commit_message(commit, \"%f\", buf, DATE_NORMAL);\n+\t\t/*\n+\t\t * Replace characters at the end with the suffix if the the\n+\t\t * filename is too long\n+\t\t */\n+\t\tif (buf->len + suffix_len > FORMAT_PATCH_NAME_MAX + start_len)\n+\t\t\tstrbuf_splice(buf,\n+\t\t\t\tstart_len + FORMAT_PATCH_NAME_MAX - suffix_len,\n+\t\t\t\tsuffix_len, suffix, suffix_len);\n+\t\telse\n+\t\t\tstrbuf_addstr(buf, suffix);\n+\t}\n+}\n+\n void log_write_email_headers(struct rev_info *opt, const char *name,\n \t\t\t     const char **subject_p,\n \t\t\t     const char **extra_headers_p,\ndiff --git a/log-tree.h b/log-tree.h\nindex f2a9008..78dc5be 100644\n--- a/log-tree.h\n+++ b/log-tree.h\n@@ -19,4 +19,8 @@ void log_write_email_headers(struct rev_info *opt, const char *name,\n \t\t\t     int *need_8bit_cte_p);\n void load_ref_decorations(void);\n \n+#define FORMAT_PATCH_NAME_MAX 64\n+void get_patch_filename(struct commit *commit, int nr, const char *suffix,\n+\t\t\tstruct strbuf *buf);\n+\n #endif\n-- \n1.6.2\n"},{"id":"108988","messageId":"bb1484f1a621238d8689e471cc6affd8590cd382.1237773604.git.bebarino@gmail.com","threadId":"18462","inReplyTo":"e8e0dcc738decb5f70dbc8e835263d7dc2834407.1237773604.git.bebarino@gmail.com","subject":"[PATCHv3 5/6] format-patch: --attach/inline uses filename instead of SHA1","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-23T02:14:05Z","receivedAt":"2009-03-23T02:14:05Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"Currently when format-patch is used with --attach or --inline the patch\nattachment has the SHA1 of the commit for its filename.  This replaces\nthe SHA1 with the filename used by format-patch when outputting to\nfiles.\n\nFix tests relying on the SHA1 output and add a test showing how the\n--suffix option affects the attachment filename output.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n builtin-log.c                                      |    8 +-\n log-tree.c                                         |   18 ++++--\n log-tree.h                                         |    2 +-\n revision.h                                         |    2 +\n t/t4013-diff-various.sh                            |    1 +\n ..._--attach_--stdout_--suffix=.diff_initial..side |   61 ++++++++++++++++++++\n ....format-patch_--attach_--stdout_initial..master |   12 ++--\n ...format-patch_--attach_--stdout_initial..master^ |    8 +-\n ...ff.format-patch_--attach_--stdout_initial..side |    4 +-\n ...tdout_--subject-prefix=TESTCASE_initial..master |   12 ++--\n ....format-patch_--inline_--stdout_initial..master |   12 ++--\n ...format-patch_--inline_--stdout_initial..master^ |    8 +-\n ...ormat-patch_--inline_--stdout_initial..master^^ |    4 +-\n ...ff.format-patch_--inline_--stdout_initial..side |    4 +-\n 14 files changed, 112 insertions(+), 44 deletions(-)\n create mode 100644 t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex a8d6037..83d8c03 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -607,7 +607,6 @@ 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-\tchar *head_sha1;\n \tconst char *subject_start = NULL;\n \tconst char *body = \"*** SUBJECT HERE ***\\n\\n*** BLURB HERE ***\\n\";\n \tconst char *msg;\n@@ -624,7 +623,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\tdie(\"Cover letter needs email format\");\n \n \tcommitter = git_committer_info(0);\n-\thead_sha1 = sha1_to_hex(head->object.sha1);\n \n \tif (!numbered_files)\n \t{\n@@ -640,7 +638,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \t\t\t\"author %s\\n\"\n \t\t\t\"committer %s\\n\\n\"\n \t\t\t\"cover letter\\n\",\n-\t\t\thead_sha1, committer, committer);\n+\t\t\tsha1_to_hex(head->object.sha1), committer, committer);\n \t}\n \n \tif (!use_stdout && reopen_stdout(commit, rev))\n@@ -652,7 +650,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_sha1, &subject_start, &extra_headers,\n+\tlog_write_email_headers(rev, head, &subject_start, &extra_headers,\n \t\t\t\t&need_8bit_cte);\n \n \tmsg = body;\n@@ -1012,6 +1010,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tconst char *msgid = clean_message_id(in_reply_to);\n \t\tstring_list_append(msgid, rev.ref_message_ids);\n \t}\n+\trev.numbered_files = numbered_files;\n+\trev.patch_suffix = fmt_patch_suffix;\n \tif (cover_letter) {\n \t\tif (thread)\n \t\t\tgen_message_id(&rev, \"cover\");\ndiff --git a/log-tree.c b/log-tree.c\nindex 9a790ab..5c9e2cf 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -202,13 +202,14 @@ void get_patch_filename(struct commit *commit, int nr, const char *suffix,\n \t}\n }\n \n-void log_write_email_headers(struct rev_info *opt, const char *name,\n+void log_write_email_headers(struct rev_info *opt, struct commit *commit,\n \t\t\t     const char **subject_p,\n \t\t\t     const char **extra_headers_p,\n \t\t\t     int *need_8bit_cte_p)\n {\n \tconst char *subject = NULL;\n \tconst char *extra_headers = opt->extra_headers;\n+\tconst char *name = sha1_to_hex(commit->object.sha1);\n \n \t*need_8bit_cte_p = 0; /* unknown */\n \tif (opt->total > 0) {\n@@ -247,6 +248,7 @@ void log_write_email_headers(struct rev_info *opt, const char *name,\n \tif (opt->mime_boundary) {\n \t\tstatic char subject_buffer[1024];\n \t\tstatic char buffer[1024];\n+\t\tstruct strbuf filename =  STRBUF_INIT;\n \t\t*need_8bit_cte_p = -1; /* NEVER */\n \t\tsnprintf(subject_buffer, sizeof(subject_buffer) - 1,\n \t\t\t \"%s\"\n@@ -265,18 +267,21 @@ void log_write_email_headers(struct rev_info *opt, const char *name,\n \t\t\t mime_boundary_leader, opt->mime_boundary);\n \t\textra_headers = subject_buffer;\n \n+\t\tget_patch_filename(opt->numbered_files ? NULL : commit, opt->nr,\n+\t\t\t\t    opt->patch_suffix, &filename);\n \t\tsnprintf(buffer, sizeof(buffer) - 1,\n \t\t\t \"\\n--%s%s\\n\"\n \t\t\t \"Content-Type: text/x-patch;\"\n-\t\t\t \" name=\\\"%s.diff\\\"\\n\"\n+\t\t\t \" name=\\\"%s\\\"\\n\"\n \t\t\t \"Content-Transfer-Encoding: 8bit\\n\"\n \t\t\t \"Content-Disposition: %s;\"\n-\t\t\t \" filename=\\\"%s.diff\\\"\\n\\n\",\n+\t\t\t \" filename=\\\"%s\\\"\\n\\n\",\n \t\t\t mime_boundary_leader, opt->mime_boundary,\n-\t\t\t name,\n+\t\t\t filename.buf,\n \t\t\t opt->no_inline ? \"attachment\" : \"inline\",\n-\t\t\t name);\n+\t\t\t filename.buf);\n \t\topt->diffopt.stat_sep = buffer;\n+\t\tstrbuf_release(&filename);\n \t}\n \t*subject_p = subject;\n \t*extra_headers_p = extra_headers;\n@@ -356,8 +361,7 @@ void show_log(struct rev_info *opt)\n \t */\n \n \tif (opt->commit_format == CMIT_FMT_EMAIL) {\n-\t\tlog_write_email_headers(opt, sha1_to_hex(commit->object.sha1),\n-\t\t\t\t\t&subject, &extra_headers,\n+\t\tlog_write_email_headers(opt, commit, &subject, &extra_headers,\n \t\t\t\t\t&need_8bit_cte);\n \t} else if (opt->commit_format != CMIT_FMT_USERFORMAT) {\n \t\tfputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), stdout);\ndiff --git a/log-tree.h b/log-tree.h\nindex 78dc5be..20b5caf 100644\n--- a/log-tree.h\n+++ b/log-tree.h\n@@ -13,7 +13,7 @@ int log_tree_commit(struct rev_info *, struct commit *);\n int log_tree_opt_parse(struct rev_info *, const char **, int);\n void show_log(struct rev_info *opt);\n void show_decorations(struct rev_info *opt, struct commit *commit);\n-void log_write_email_headers(struct rev_info *opt, const char *name,\n+void log_write_email_headers(struct rev_info *opt, struct commit *commit,\n \t\t\t     const char **subject_p,\n \t\t\t     const char **extra_headers_p,\n \t\t\t     int *need_8bit_cte_p);\ndiff --git a/revision.h b/revision.h\nindex ad123d7..5259ed5 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -86,6 +86,8 @@ struct rev_info {\n \tstruct log_info *loginfo;\n \tint\t\tnr, total;\n \tconst char\t*mime_boundary;\n+\tconst char\t*patch_suffix;\n+\tint\t\tnumbered_files;\n \tchar\t\t*message_id;\n \tstruct string_list *ref_message_ids;\n \tconst char\t*add_signoff;\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex 426e64e..6592a4f 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -246,6 +246,7 @@ format-patch --stdout initial..master\n format-patch --stdout --no-numbered initial..master\n format-patch --stdout --numbered initial..master\n format-patch --attach --stdout initial..side\n+format-patch --attach --stdout --suffix=.diff initial..side\n format-patch --attach --stdout initial..master^\n format-patch --attach --stdout initial..master\n format-patch --inline --stdout initial..side\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\nnew file mode 100644\nindex 0000000..52116d3\n--- /dev/null\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side\n@@ -0,0 +1,61 @@\n+$ git format-patch --attach --stdout --suffix=.diff initial..side\n+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001\n+From: A U Thor <author@example.com>\n+Date: Mon, 26 Jun 2006 00:03:00 +0000\n+Subject: [PATCH] Side\n+MIME-Version: 1.0\n+Content-Type: multipart/mixed; boundary=\"------------g-i-t--v-e-r-s-i-o-n\"\n+\n+This is a multi-part message in MIME format.\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/plain; charset=UTF-8; format=fixed\n+Content-Transfer-Encoding: 8bit\n+\n+---\n+ dir/sub |    2 ++\n+ file0   |    3 +++\n+ file3   |    4 ++++\n+ 3 files changed, 9 insertions(+), 0 deletions(-)\n+ create mode 100644 file3\n+\n+\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/x-patch; name=\"0001-Side.diff\"\n+Content-Transfer-Encoding: 8bit\n+Content-Disposition: attachment; filename=\"0001-Side.diff\"\n+\n+diff --git a/dir/sub b/dir/sub\n+index 35d242b..7289e35 100644\n+--- a/dir/sub\n++++ b/dir/sub\n+@@ -1,2 +1,4 @@\n+ A\n+ B\n++1\n++2\n+diff --git a/file0 b/file0\n+index 01e79c3..f4615da 100644\n+--- a/file0\n++++ b/file0\n+@@ -1,3 +1,6 @@\n+ 1\n+ 2\n+ 3\n++A\n++B\n++C\n+diff --git a/file3 b/file3\n+new file mode 100644\n+index 0000000..7289e35\n+--- /dev/null\n++++ b/file3\n+@@ -0,0 +1,4 @@\n++A\n++B\n++1\n++2\n+\n+--------------g-i-t--v-e-r-s-i-o-n--\n+\n+\n+$\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master\nindex e5ab744..ce49bd6 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: attachment; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: attachment; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\n@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0003-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: attachment; filename=\"0003-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\nindex 2c71d20..5f1b238 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: attachment; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: attachment; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\ndiff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side\nindex 38f7902..4a2364a 100644\n--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side\n@@ -20,9 +20,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0001-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: attachment; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: attachment; filename=\"0001-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\nindex 58f8a7b..ca3f60b 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: inline; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: inline; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\n@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0003-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: inline; filename=\"0003-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master\nindex 9e7bbdf..08f2301 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: inline; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: inline; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\n@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0003-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: inline; filename=\"0003-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\nindex f881f64..07f1230 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: inline; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\n@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Type: text/x-patch; name=\"0002-Third.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff\"\n+Content-Disposition: inline; filename=\"0002-Third.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 8422d40..cead32e 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\nindex 4f258b8..29e00ab 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^\n@@ -22,9 +22,9 @@ This is the second commit.\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Type: text/x-patch; name=\"0001-Second.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff\"\n+Content-Disposition: inline; filename=\"0001-Second.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..8422d40 100644\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side\nindex e86dce6..67633d4 100644\n--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side\n@@ -20,9 +20,9 @@ Content-Transfer-Encoding: 8bit\n \n \n --------------g-i-t--v-e-r-s-i-o-n\n-Content-Type: text/x-patch; name=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Type: text/x-patch; name=\"0001-Side.patch\"\n Content-Transfer-Encoding: 8bit\n-Content-Disposition: inline; filename=\"c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff\"\n+Content-Disposition: inline; filename=\"0001-Side.patch\"\n \n diff --git a/dir/sub b/dir/sub\n index 35d242b..7289e35 100644\n-- \n1.6.2\n"},{"id":"108989","messageId":"7bf87c296a246e417b9fac0c215c717a27289fba.1237773605.git.bebarino@gmail.com","threadId":"18462","inReplyTo":"bb1484f1a621238d8689e471cc6affd8590cd382.1237773604.git.bebarino@gmail.com","subject":"[PATCHv3 6/6] format-patch: --numbered-files and --stdout aren't mutually exclusive","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-23T02:14:06Z","receivedAt":"2009-03-23T02:14:06Z","isPatch":false,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"For example:\n\n    git format-patch --numbered-files --stdout --attach HEAD~~\n\nwill create two messages with files 1 and 2 attached respectively.\nThere is no effect when using --numbered-files and --stdout together\nwithout an --attach or --inline, the --numbered-files option will be\nignored. Add a test to show this.\n\nSigned-off-by: Stephen Boyd <bebarino@gmail.com>\n---\n t/t4013-diff-various.sh                            |    2 +-\n ...nline_--stdout_--numbered-files_initial..master |  170 ++++++++++++++++++++\n 2 files changed, 171 insertions(+), 1 deletions(-)\n create mode 100644 t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\n\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex 6592a4f..8b33321 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -251,7 +251,7 @@ format-patch --attach --stdout initial..master^\n format-patch --attach --stdout initial..master\n format-patch --inline --stdout initial..side\n format-patch --inline --stdout initial..master^\n-format-patch --inline --stdout initial..master\n+format-patch --inline --stdout --numbered-files initial..master\n format-patch --inline --stdout initial..master\n format-patch --inline --stdout --subject-prefix=TESTCASE initial..master\n config format.subjectprefix DIFFERENT_PREFIX\ndiff --git a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\nnew file mode 100644\nindex 0000000..43b81eb\n--- /dev/null\n+++ b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master\n@@ -0,0 +1,170 @@\n+$ git format-patch --inline --stdout --numbered-files initial..master\n+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001\n+From: A U Thor <author@example.com>\n+Date: Mon, 26 Jun 2006 00:01:00 +0000\n+Subject: [PATCH 1/3] Second\n+MIME-Version: 1.0\n+Content-Type: multipart/mixed; boundary=\"------------g-i-t--v-e-r-s-i-o-n\"\n+\n+This is a multi-part message in MIME format.\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/plain; charset=UTF-8; format=fixed\n+Content-Transfer-Encoding: 8bit\n+\n+\n+This is the second commit.\n+---\n+ dir/sub |    2 ++\n+ file0   |    3 +++\n+ file2   |    3 ---\n+ 3 files changed, 5 insertions(+), 3 deletions(-)\n+ delete mode 100644 file2\n+\n+\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/x-patch; name=\"1\"\n+Content-Transfer-Encoding: 8bit\n+Content-Disposition: inline; filename=\"1\"\n+\n+diff --git a/dir/sub b/dir/sub\n+index 35d242b..8422d40 100644\n+--- a/dir/sub\n++++ b/dir/sub\n+@@ -1,2 +1,4 @@\n+ A\n+ B\n++C\n++D\n+diff --git a/file0 b/file0\n+index 01e79c3..b414108 100644\n+--- a/file0\n++++ b/file0\n+@@ -1,3 +1,6 @@\n+ 1\n+ 2\n+ 3\n++4\n++5\n++6\n+diff --git a/file2 b/file2\n+deleted file mode 100644\n+index 01e79c3..0000000\n+--- a/file2\n++++ /dev/null\n+@@ -1,3 +0,0 @@\n+-1\n+-2\n+-3\n+\n+--------------g-i-t--v-e-r-s-i-o-n--\n+\n+\n+\n+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001\n+From: A U Thor <author@example.com>\n+Date: Mon, 26 Jun 2006 00:02:00 +0000\n+Subject: [PATCH 2/3] Third\n+MIME-Version: 1.0\n+Content-Type: multipart/mixed; boundary=\"------------g-i-t--v-e-r-s-i-o-n\"\n+\n+This is a multi-part message in MIME format.\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/plain; charset=UTF-8; format=fixed\n+Content-Transfer-Encoding: 8bit\n+\n+---\n+ dir/sub |    2 ++\n+ file1   |    3 +++\n+ 2 files changed, 5 insertions(+), 0 deletions(-)\n+ create mode 100644 file1\n+\n+\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/x-patch; name=\"2\"\n+Content-Transfer-Encoding: 8bit\n+Content-Disposition: inline; filename=\"2\"\n+\n+diff --git a/dir/sub b/dir/sub\n+index 8422d40..cead32e 100644\n+--- a/dir/sub\n++++ b/dir/sub\n+@@ -2,3 +2,5 @@ A\n+ B\n+ C\n+ D\n++E\n++F\n+diff --git a/file1 b/file1\n+new file mode 100644\n+index 0000000..b1e6722\n+--- /dev/null\n++++ b/file1\n+@@ -0,0 +1,3 @@\n++A\n++B\n++C\n+\n+--------------g-i-t--v-e-r-s-i-o-n--\n+\n+\n+\n+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001\n+From: A U Thor <author@example.com>\n+Date: Mon, 26 Jun 2006 00:03:00 +0000\n+Subject: [PATCH 3/3] Side\n+MIME-Version: 1.0\n+Content-Type: multipart/mixed; boundary=\"------------g-i-t--v-e-r-s-i-o-n\"\n+\n+This is a multi-part message in MIME format.\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/plain; charset=UTF-8; format=fixed\n+Content-Transfer-Encoding: 8bit\n+\n+---\n+ dir/sub |    2 ++\n+ file0   |    3 +++\n+ file3   |    4 ++++\n+ 3 files changed, 9 insertions(+), 0 deletions(-)\n+ create mode 100644 file3\n+\n+\n+--------------g-i-t--v-e-r-s-i-o-n\n+Content-Type: text/x-patch; name=\"3\"\n+Content-Transfer-Encoding: 8bit\n+Content-Disposition: inline; filename=\"3\"\n+\n+diff --git a/dir/sub b/dir/sub\n+index 35d242b..7289e35 100644\n+--- a/dir/sub\n++++ b/dir/sub\n+@@ -1,2 +1,4 @@\n+ A\n+ B\n++1\n++2\n+diff --git a/file0 b/file0\n+index 01e79c3..f4615da 100644\n+--- a/file0\n++++ b/file0\n+@@ -1,3 +1,6 @@\n+ 1\n+ 2\n+ 3\n++A\n++B\n++C\n+diff --git a/file3 b/file3\n+new file mode 100644\n+index 0000000..7289e35\n+--- /dev/null\n++++ b/file3\n+@@ -0,0 +1,4 @@\n++A\n++B\n++1\n++2\n+\n+--------------g-i-t--v-e-r-s-i-o-n--\n+\n+\n+$\n-- \n1.6.2\n"},{"id":"110073","messageId":"49D2968D.6010108@lsrfire.ath.cx","threadId":"18462","inReplyTo":"baa327d88b54efae40b6d9df09a2fe482672101e.1237773604.git.bebarino@gmail.com","subject":"Re: [PATCHv3 1/6] pretty.c: add %f format specifier to format_commit_message()","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-03-31T22:17:49Z","receivedAt":"2009-03-31T22:17:49Z","isPatch":false,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Stephen Boyd schrieb:\n> This specifier represents the sanitized and filename friendly subject\n> line of a commit. No checks are made against the length of the string,\n> so users may need to trim the result to the desired length if using as a\n> filename. This is commonly used by format-patch to massage commit\n> subjects into filenames and output patches to files.\n> \n> Signed-off-by: Stephen Boyd <bebarino@gmail.com>\n> ---\n>  Documentation/pretty-formats.txt |    1 +\n>  pretty.c                         |   38 ++++++++++++++++++++++++++++++++++++++\n>  2 files changed, 39 insertions(+), 0 deletions(-)\n> \n> diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\n> index 5c6e678..2a845b1 100644\n> --- a/Documentation/pretty-formats.txt\n> +++ b/Documentation/pretty-formats.txt\n> @@ -121,6 +121,7 @@ The placeholders are:\n>  - '%d': ref names, like the --decorate option of linkgit:git-log[1]\n>  - '%e': encoding\n>  - '%s': subject\n> +- '%f': sanitized subject line, suitable for a filename\n>  - '%b': body\n>  - '%Cred': switch color to red\n>  - '%Cgreen': switch color to green\n> diff --git a/pretty.c b/pretty.c\n> index efa7024..97de415 100644\n> --- a/pretty.c\n> +++ b/pretty.c\n> @@ -493,6 +493,41 @@ static void parse_commit_header(struct format_commit_context *context)\n>  \tcontext->commit_header_parsed = 1;\n>  }\n>  \n> +static int istitlechar(char c)\n> +{\n> +\treturn (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||\n> +\t\t(c >= '0' && c <= '9') || c == '.' || c == '_';\n\nHow about this?\n\n\treturn isalnum(c) || c == '.' || c == '_';\n\n> +}\n> +\n> +static void format_sanitized_subject(struct strbuf *sb, const char *msg)\n> +{\n> +\tsize_t trimlen;\n> +\tint space = 0;\n> +\n> +\tfor (; *msg && *msg != '\\n'; msg++) {\n> +\t\tif (istitlechar(*msg))\n> +\t\t{\n> +\t\t    if (space) {\n> +\t\t\tstrbuf_addch(sb, '-');\n> +\t\t\tspace = 0;\n> +\t\t    }\n> +\t\t    strbuf_addch(sb, *msg);\n> +\t\t    if (*msg == '.')\n> +\t\t\twhile (*(msg+1) == '.')\n> +\t\t\t\tmsg++;\n> +\t\t}\n> +\t\telse\n> +\t\t\tspace = 1;\n> +\t}\n> +\n\n> +\t// trim any trailing '.' or '-' characters\n> +\ttrimlen = 0;\n> +\twhile (sb->buf[sb->len - 1 - trimlen] == '.'\n> +\t\t|| sb->buf[sb->len - 1 - trimlen] == '-')\n> +\t\ttrimlen++;\n> +\tstrbuf_remove(sb, sb->len - trimlen, trimlen);\n\nYou need to make sure that trimming stops as soon as the strbuf has been\nshortened to its original length.  E.g. for a subject line of \"...\"\nyou'd access the char before the first dot currently, or sb->buf[-1] if\nthe strbuf was empty initially.\n\n(One could also check for sb->len > 0 to just prevent the buffer\nunderrun, but %f sometimes eating preceding dots and dashes is\ncounter-intuitive to me.)\n\n> +}\n> +\n>  const char *format_subject(struct strbuf *sb, const char *msg,\n>  \t\t\t   const char *line_separator)\n>  {\n> @@ -683,6 +718,9 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n>  \tcase 's':\t/* subject */\n>  \t\tformat_subject(sb, msg + c->subject_off, \" \");\n>  \t\treturn 1;\n> +\tcase 'f':\t/* sanitized subject */\n> +\t\tformat_sanitized_subject(sb, msg + c->subject_off);\n> +\t\treturn 1;\n>  \tcase 'b':\t/* body */\n>  \t\tstrbuf_addstr(sb, msg + c->body_off);\n>  \t\treturn 1;\n"},{"id":"110078","messageId":"1238541878-11025-1-git-send-email-bebarino@gmail.com","threadId":"18462","inReplyTo":"49D2968D.6010108@lsrfire.ath.cx","subject":"[PATCH] format_sanitized_subject: Don't trim past initial length of strbuf","fromName":"Stephen Boyd","fromEmail":"bebarino@gmail.com","sentAt":"2009-03-31T23:24:38Z","receivedAt":"2009-03-31T23:24:38Z","isPatch":true,"sender":{"key":"bebarino@gmail.com","avatar":"https://avatars.githubusercontent.com/u/38832?v=4"},"body":"If the subject line is '...' the strbuf will be accessed before the\nfirst dot is added; potentially changing the strbuf passed into the\nfunction or accessing sb->buf[-1] if it was originally empty.\n\nReported-by: René Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\nI was thinking about this today actually. Thanks.\n\nWith regards to the isalnum(), I kept the original code because I wasn't sure\nif the functionality would be different.\n\n pretty.c |    6 ++++--\n 1 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/pretty.c b/pretty.c\nindex c57cef4..a0ef356 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -502,6 +502,7 @@ static int istitlechar(char c)\n static void format_sanitized_subject(struct strbuf *sb, const char *msg)\n {\n \tsize_t trimlen;\n+\tsize_t start_len = sb->len;\n \tint space = 2;\n \n \tfor (; *msg && *msg != '\\n'; msg++) {\n@@ -519,8 +520,9 @@ static void format_sanitized_subject(struct strbuf *sb, const char *msg)\n \n \t/* trim any trailing '.' or '-' characters */\n \ttrimlen = 0;\n-\twhile (sb->buf[sb->len - 1 - trimlen] == '.'\n-\t\t|| sb->buf[sb->len - 1 - trimlen] == '-')\n+\twhile (sb->len - trimlen > start_len &&\n+\t\t(sb->buf[sb->len - 1 - trimlen] == '.'\n+\t\t|| sb->buf[sb->len - 1 - trimlen] == '-'))\n \t\ttrimlen++;\n \tstrbuf_remove(sb, sb->len - trimlen, trimlen);\n }\n-- \n1.6.2\n"}]}