Skip to content

Commit b75ba9b

Browse files
committed
Merge branch 'dl/format-patch-cover-from-desc'
The branch description ("git branch --edit-description") has been used to fill the body of the cover letters by the format-patch command; this has been enhanced so that the subject can also be filled. * dl/format-patch-cover-from-desc: format-patch: teach --cover-from-description option format-patch: use enum variables format-patch: replace erroneous and condition
2 parents 15d9f3d + bf8e65b commit b75ba9b

File tree

5 files changed

+296
-34
lines changed

5 files changed

+296
-34
lines changed

Documentation/config/format.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ format.subjectPrefix::
3636
The default for format-patch is to output files with the '[PATCH]'
3737
subject prefix. Use this variable to change that prefix.
3838

39+
format.coverFromDescription::
40+
The default mode for format-patch to determine which parts of
41+
the cover letter will be populated using the branch's
42+
description. See the `--cover-from-description` option in
43+
linkgit:git-format-patch[1].
44+
3945
format.signature::
4046
The default for format-patch is to output a signature containing
4147
the Git version number. Use this variable to change that default.

Documentation/git-format-patch.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ SYNOPSIS
1919
[--start-number <n>] [--numbered-files]
2020
[--in-reply-to=<message id>] [--suffix=.<sfx>]
2121
[--ignore-if-in-upstream]
22+
[--cover-from-description=<mode>]
2223
[--rfc] [--subject-prefix=<subject prefix>]
2324
[(--reroll-count|-v) <n>]
2425
[--to=<email>] [--cc=<email>]
@@ -172,6 +173,26 @@ will want to ensure that threading is disabled for `git send-email`.
172173
patches being generated, and any patch that matches is
173174
ignored.
174175

176+
--cover-from-description=<mode>::
177+
Controls which parts of the cover letter will be automatically
178+
populated using the branch's description.
179+
+
180+
If `<mode>` is `message` or `default`, the cover letter subject will be
181+
populated with placeholder text. The body of the cover letter will be
182+
populated with the branch's description. This is the default mode when
183+
no configuration nor command line option is specified.
184+
+
185+
If `<mode>` is `subject`, the first paragraph of the branch description will
186+
populate the cover letter subject. The remainder of the description will
187+
populate the body of the cover letter.
188+
+
189+
If `<mode>` is `auto`, if the first paragraph of the branch description
190+
is greater than 100 bytes, then the mode will be `message`, otherwise
191+
`subject` will be used.
192+
+
193+
If `<mode>` is `none`, both the cover letter subject and body will be
194+
populated with placeholder text.
195+
175196
--subject-prefix=<subject prefix>::
176197
Instead of the standard '[PATCH]' prefix in the subject
177198
line, instead use '[<subject prefix>]'. This
@@ -348,6 +369,7 @@ with configuration variables.
348369
signOff = true
349370
outputDirectory = <directory>
350371
coverLetter = auto
372+
coverFromDescription = auto
351373
------------
352374

353375

builtin/log.c

Lines changed: 92 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "range-diff.h"
3838

3939
#define MAIL_DEFAULT_WRAP 72
40+
#define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100
4041

4142
/* Set a default date-time format for git log ("log.date" config variable) */
4243
static const char *default_date_mode = NULL;
@@ -765,23 +766,51 @@ static void add_header(const char *value)
765766
item->string[len] = '\0';
766767
}
767768

768-
#define THREAD_SHALLOW 1
769-
#define THREAD_DEEP 2
770-
static int thread;
769+
enum cover_setting {
770+
COVER_UNSET,
771+
COVER_OFF,
772+
COVER_ON,
773+
COVER_AUTO
774+
};
775+
776+
enum thread_level {
777+
THREAD_UNSET,
778+
THREAD_SHALLOW,
779+
THREAD_DEEP
780+
};
781+
782+
enum cover_from_description {
783+
COVER_FROM_NONE,
784+
COVER_FROM_MESSAGE,
785+
COVER_FROM_SUBJECT,
786+
COVER_FROM_AUTO
787+
};
788+
789+
static enum thread_level thread;
771790
static int do_signoff;
772791
static int base_auto;
773792
static char *from;
774793
static const char *signature = git_version_string;
775794
static const char *signature_file;
776-
static int config_cover_letter;
795+
static enum cover_setting config_cover_letter;
777796
static const char *config_output_directory;
797+
static enum cover_from_description cover_from_description_mode = COVER_FROM_MESSAGE;
778798

779-
enum {
780-
COVER_UNSET,
781-
COVER_OFF,
782-
COVER_ON,
783-
COVER_AUTO
784-
};
799+
static enum cover_from_description parse_cover_from_description(const char *arg)
800+
{
801+
if (!arg || !strcmp(arg, "default"))
802+
return COVER_FROM_MESSAGE;
803+
else if (!strcmp(arg, "none"))
804+
return COVER_FROM_NONE;
805+
else if (!strcmp(arg, "message"))
806+
return COVER_FROM_MESSAGE;
807+
else if (!strcmp(arg, "subject"))
808+
return COVER_FROM_SUBJECT;
809+
else if (!strcmp(arg, "auto"))
810+
return COVER_FROM_AUTO;
811+
else
812+
die(_("%s: invalid cover from description mode"), arg);
813+
}
785814

786815
static int git_format_config(const char *var, const char *value, void *cb)
787816
{
@@ -836,7 +865,7 @@ static int git_format_config(const char *var, const char *value, void *cb)
836865
thread = THREAD_SHALLOW;
837866
return 0;
838867
}
839-
thread = git_config_bool(var, value) && THREAD_SHALLOW;
868+
thread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;
840869
return 0;
841870
}
842871
if (!strcmp(var, "format.signoff")) {
@@ -888,6 +917,10 @@ static int git_format_config(const char *var, const char *value, void *cb)
888917
}
889918
return 0;
890919
}
920+
if (!strcmp(var, "format.coverfromdescription")) {
921+
cover_from_description_mode = parse_cover_from_description(value);
922+
return 0;
923+
}
891924

892925
return git_log_config(var, value, cb);
893926
}
@@ -994,20 +1027,6 @@ static void print_signature(FILE *file)
9941027
putc('\n', file);
9951028
}
9961029

997-
static void add_branch_description(struct strbuf *buf, const char *branch_name)
998-
{
999-
struct strbuf desc = STRBUF_INIT;
1000-
if (!branch_name || !*branch_name)
1001-
return;
1002-
read_branch_desc(&desc, branch_name);
1003-
if (desc.len) {
1004-
strbuf_addch(buf, '\n');
1005-
strbuf_addbuf(buf, &desc);
1006-
strbuf_addch(buf, '\n');
1007-
}
1008-
strbuf_release(&desc);
1009-
}
1010-
10111030
static char *find_branch_name(struct rev_info *rev)
10121031
{
10131032
int i, positive = -1;
@@ -1054,15 +1073,51 @@ static void show_diffstat(struct rev_info *rev,
10541073
fprintf(rev->diffopt.file, "\n");
10551074
}
10561075

1076+
static void prepare_cover_text(struct pretty_print_context *pp,
1077+
const char *branch_name,
1078+
struct strbuf *sb,
1079+
const char *encoding,
1080+
int need_8bit_cte)
1081+
{
1082+
const char *subject = "*** SUBJECT HERE ***";
1083+
const char *body = "*** BLURB HERE ***";
1084+
struct strbuf description_sb = STRBUF_INIT;
1085+
struct strbuf subject_sb = STRBUF_INIT;
1086+
1087+
if (cover_from_description_mode == COVER_FROM_NONE)
1088+
goto do_pp;
1089+
1090+
if (branch_name && *branch_name)
1091+
read_branch_desc(&description_sb, branch_name);
1092+
if (!description_sb.len)
1093+
goto do_pp;
1094+
1095+
if (cover_from_description_mode == COVER_FROM_SUBJECT ||
1096+
cover_from_description_mode == COVER_FROM_AUTO)
1097+
body = format_subject(&subject_sb, description_sb.buf, " ");
1098+
1099+
if (cover_from_description_mode == COVER_FROM_MESSAGE ||
1100+
(cover_from_description_mode == COVER_FROM_AUTO &&
1101+
subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))
1102+
body = description_sb.buf;
1103+
else
1104+
subject = subject_sb.buf;
1105+
1106+
do_pp:
1107+
pp_title_line(pp, &subject, sb, encoding, need_8bit_cte);
1108+
pp_remainder(pp, &body, sb, 0);
1109+
1110+
strbuf_release(&description_sb);
1111+
strbuf_release(&subject_sb);
1112+
}
1113+
10571114
static void make_cover_letter(struct rev_info *rev, int use_stdout,
10581115
struct commit *origin,
10591116
int nr, struct commit **list,
10601117
const char *branch_name,
10611118
int quiet)
10621119
{
10631120
const char *committer;
1064-
const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
1065-
const char *msg;
10661121
struct shortlog log;
10671122
struct strbuf sb = STRBUF_INIT;
10681123
int i;
@@ -1092,15 +1147,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
10921147
if (!branch_name)
10931148
branch_name = find_branch_name(rev);
10941149

1095-
msg = body;
10961150
pp.fmt = CMIT_FMT_EMAIL;
10971151
pp.date_mode.type = DATE_RFC2822;
10981152
pp.rev = rev;
10991153
pp.print_email_subject = 1;
11001154
pp_user_info(&pp, NULL, &sb, committer, encoding);
1101-
pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
1102-
pp_remainder(&pp, &msg, &sb, 0);
1103-
add_branch_description(&sb, branch_name);
1155+
prepare_cover_text(&pp, branch_name, &sb, encoding, need_8bit_cte);
11041156
fprintf(rev->diffopt.file, "%s\n", sb.buf);
11051157

11061158
strbuf_release(&sb);
@@ -1249,9 +1301,9 @@ static int output_directory_callback(const struct option *opt, const char *arg,
12491301

12501302
static int thread_callback(const struct option *opt, const char *arg, int unset)
12511303
{
1252-
int *thread = (int *)opt->value;
1304+
enum thread_level *thread = (enum thread_level *)opt->value;
12531305
if (unset)
1254-
*thread = 0;
1306+
*thread = THREAD_UNSET;
12551307
else if (!arg || !strcmp(arg, "shallow"))
12561308
*thread = THREAD_SHALLOW;
12571309
else if (!strcmp(arg, "deep"))
@@ -1542,6 +1594,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
15421594
int use_patch_format = 0;
15431595
int quiet = 0;
15441596
int reroll_count = -1;
1597+
char *cover_from_description_arg = NULL;
15451598
char *branch_name = NULL;
15461599
char *base_commit = NULL;
15471600
struct base_tree_info bases;
@@ -1578,6 +1631,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
15781631
{ OPTION_CALLBACK, 0, "rfc", &rev, NULL,
15791632
N_("Use [RFC PATCH] instead of [PATCH]"),
15801633
PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },
1634+
OPT_STRING(0, "cover-from-description", &cover_from_description_arg,
1635+
N_("cover-from-description-mode"),
1636+
N_("generate parts of a cover letter based on a branch's description")),
15811637
{ OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"),
15821638
N_("Use [<prefix>] instead of [PATCH]"),
15831639
PARSE_OPT_NONEG, subject_prefix_callback },
@@ -1669,6 +1725,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
16691725
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
16701726
PARSE_OPT_KEEP_DASHDASH);
16711727

1728+
if (cover_from_description_arg)
1729+
cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
1730+
16721731
if (0 < reroll_count) {
16731732
struct strbuf sprefix = STRBUF_INIT;
16741733
strbuf_addf(&sprefix, "%s v%d",

0 commit comments

Comments
 (0)