@ -37,6 +37,7 @@
@@ -37,6 +37,7 @@
#include "range-diff.h"
#define MAIL_DEFAULT_WRAP 72
#define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100
/* Set a default date-time format for git log ("log.date" config variable) */
static const char *default_date_mode = NULL;
@ -765,23 +766,51 @@ static void add_header(const char *value)
@@ -765,23 +766,51 @@ static void add_header(const char *value)
item->string[len] = '\0';
}
#define THREAD_SHALLOW 1
#define THREAD_DEEP 2
static int thread;
enum cover_setting {
COVER_UNSET,
COVER_OFF,
COVER_ON,
COVER_AUTO
};
enum thread_level {
THREAD_UNSET,
THREAD_SHALLOW,
THREAD_DEEP
};
enum cover_from_description {
COVER_FROM_NONE,
COVER_FROM_MESSAGE,
COVER_FROM_SUBJECT,
COVER_FROM_AUTO
};
static enum thread_level thread;
static int do_signoff;
static int base_auto;
static char *from;
static const char *signature = git_version_string;
static const char *signature_file;
static int config_cover_letter;
static enum cover_setting config_cover_letter;
static const char *config_output_directory;
static enum cover_from_description cover_from_description_mode = COVER_FROM_MESSAGE;
enum {
COVER_UNSET,
COVER_OFF,
COVER_ON,
COVER_AUTO
};
static enum cover_from_description parse_cover_from_description(const char *arg)
{
if (!arg || !strcmp(arg, "default"))
return COVER_FROM_MESSAGE;
else if (!strcmp(arg, "none"))
return COVER_FROM_NONE;
else if (!strcmp(arg, "message"))
return COVER_FROM_MESSAGE;
else if (!strcmp(arg, "subject"))
return COVER_FROM_SUBJECT;
else if (!strcmp(arg, "auto"))
return COVER_FROM_AUTO;
else
die(_("%s: invalid cover from description mode"), arg);
}
static int git_format_config(const char *var, const char *value, void *cb)
{
@ -836,7 +865,7 @@ static int git_format_config(const char *var, const char *value, void *cb)
@@ -836,7 +865,7 @@ static int git_format_config(const char *var, const char *value, void *cb)
thread = THREAD_SHALLOW;
return 0;
}
thread = git_config_bool(var, value) && THREAD_SHALLOW;
thread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;
return 0;
}
if (!strcmp(var, "format.signoff")) {
@ -888,6 +917,10 @@ static int git_format_config(const char *var, const char *value, void *cb)
@@ -888,6 +917,10 @@ static int git_format_config(const char *var, const char *value, void *cb)
}
return 0;
}
if (!strcmp(var, "format.coverfromdescription")) {
cover_from_description_mode = parse_cover_from_description(value);
return 0;
}
return git_log_config(var, value, cb);
}
@ -994,20 +1027,6 @@ static void print_signature(FILE *file)
@@ -994,20 +1027,6 @@ static void print_signature(FILE *file)
putc('\n', file);
}
static void add_branch_description(struct strbuf *buf, const char *branch_name)
{
struct strbuf desc = STRBUF_INIT;
if (!branch_name || !*branch_name)
return;
read_branch_desc(&desc, branch_name);
if (desc.len) {
strbuf_addch(buf, '\n');
strbuf_addbuf(buf, &desc);
strbuf_addch(buf, '\n');
}
strbuf_release(&desc);
}
static char *find_branch_name(struct rev_info *rev)
{
int i, positive = -1;
@ -1054,6 +1073,44 @@ static void show_diffstat(struct rev_info *rev,
@@ -1054,6 +1073,44 @@ static void show_diffstat(struct rev_info *rev,
fprintf(rev->diffopt.file, "\n");
}
static void prepare_cover_text(struct pretty_print_context *pp,
const char *branch_name,
struct strbuf *sb,
const char *encoding,
int need_8bit_cte)
{
const char *subject = "*** SUBJECT HERE ***";
const char *body = "*** BLURB HERE ***";
struct strbuf description_sb = STRBUF_INIT;
struct strbuf subject_sb = STRBUF_INIT;
if (cover_from_description_mode == COVER_FROM_NONE)
goto do_pp;
if (branch_name && *branch_name)
read_branch_desc(&description_sb, branch_name);
if (!description_sb.len)
goto do_pp;
if (cover_from_description_mode == COVER_FROM_SUBJECT ||
cover_from_description_mode == COVER_FROM_AUTO)
body = format_subject(&subject_sb, description_sb.buf, " ");
if (cover_from_description_mode == COVER_FROM_MESSAGE ||
(cover_from_description_mode == COVER_FROM_AUTO &&
subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))
body = description_sb.buf;
else
subject = subject_sb.buf;
do_pp:
pp_title_line(pp, &subject, sb, encoding, need_8bit_cte);
pp_remainder(pp, &body, sb, 0);
strbuf_release(&description_sb);
strbuf_release(&subject_sb);
}
static void make_cover_letter(struct rev_info *rev, int use_stdout,
struct commit *origin,
int nr, struct commit **list,
@ -1061,8 +1118,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
@@ -1061,8 +1118,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
int quiet)
{
const char *committer;
const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
const char *msg;
struct shortlog log;
struct strbuf sb = STRBUF_INIT;
int i;
@ -1092,15 +1147,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
@@ -1092,15 +1147,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
if (!branch_name)
branch_name = find_branch_name(rev);
msg = body;
pp.fmt = CMIT_FMT_EMAIL;
pp.date_mode.type = DATE_RFC2822;
pp.rev = rev;
pp.print_email_subject = 1;
pp_user_info(&pp, NULL, &sb, committer, encoding);
pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
pp_remainder(&pp, &msg, &sb, 0);
add_branch_description(&sb, branch_name);
prepare_cover_text(&pp, branch_name, &sb, encoding, need_8bit_cte);
fprintf(rev->diffopt.file, "%s\n", sb.buf);
strbuf_release(&sb);
@ -1249,9 +1301,9 @@ static int output_directory_callback(const struct option *opt, const char *arg,
@@ -1249,9 +1301,9 @@ static int output_directory_callback(const struct option *opt, const char *arg,
static int thread_callback(const struct option *opt, const char *arg, int unset)
{
int *thread = (int *)opt->value;
enum thread_level *thread = (enum thread_level *)opt->value;
if (unset)
*thread = 0;
*thread = THREAD_UNSET;
else if (!arg || !strcmp(arg, "shallow"))
*thread = THREAD_SHALLOW;
else if (!strcmp(arg, "deep"))
@ -1542,6 +1594,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
@@ -1542,6 +1594,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
int use_patch_format = 0;
int quiet = 0;
int reroll_count = -1;
char *cover_from_description_arg = NULL;
char *branch_name = NULL;
char *base_commit = NULL;
struct base_tree_info bases;
@ -1578,6 +1631,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
@@ -1578,6 +1631,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
{ OPTION_CALLBACK, 0, "rfc", &rev, NULL,
N_("Use [RFC PATCH] instead of [PATCH]"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },
OPT_STRING(0, "cover-from-description", &cover_from_description_arg,
N_("cover-from-description-mode"),
N_("generate parts of a cover letter based on a branch's description")),
{ OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"),
N_("Use [<prefix>] instead of [PATCH]"),
PARSE_OPT_NONEG, subject_prefix_callback },
@ -1669,6 +1725,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
@@ -1669,6 +1725,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
PARSE_OPT_KEEP_DASHDASH);
if (cover_from_description_arg)
cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
if (0 < reroll_count) {
struct strbuf sprefix = STRBUF_INIT;
strbuf_addf(&sprefix, "%s v%d",