Merge branch 'ob/format-patch-description-file'

"git format-patch" learns a way to feed cover letter description,
that (1) can be used on detached HEAD where there is no branch
description available, and (2) also can override the branch
description if there is one.

* ob/format-patch-description-file:
  format-patch: add --description-file option
maint
Junio C Hamano 2023-09-01 11:26:28 -07:00
commit 3b4e395cb3
3 changed files with 36 additions and 3 deletions

View File

@ -215,6 +215,10 @@ is greater than 100 bytes, then the mode will be `message`, otherwise
If `<mode>` is `none`, both the cover letter subject and body will be If `<mode>` is `none`, both the cover letter subject and body will be
populated with placeholder text. populated with placeholder text.


--description-file=<file>::
Use the contents of <file> instead of the branch's description
for generating the cover letter.

--subject-prefix=<subject prefix>:: --subject-prefix=<subject prefix>::
Instead of the standard '[PATCH]' prefix in the subject Instead of the standard '[PATCH]' prefix in the subject
line, instead use '[<subject prefix>]'. This line, instead use '[<subject prefix>]'. This

View File

@ -1253,7 +1253,15 @@ static void show_diffstat(struct rev_info *rev,
fprintf(rev->diffopt.file, "\n"); fprintf(rev->diffopt.file, "\n");
} }


static void read_desc_file(struct strbuf *buf, const char *desc_file)
{
if (strbuf_read_file(buf, desc_file, 0) < 0)
die_errno(_("unable to read branch description file '%s'"),
desc_file);
}

static void prepare_cover_text(struct pretty_print_context *pp, static void prepare_cover_text(struct pretty_print_context *pp,
const char *description_file,
const char *branch_name, const char *branch_name,
struct strbuf *sb, struct strbuf *sb,
const char *encoding, const char *encoding,
@ -1267,7 +1275,9 @@ static void prepare_cover_text(struct pretty_print_context *pp,
if (cover_from_description_mode == COVER_FROM_NONE) if (cover_from_description_mode == COVER_FROM_NONE)
goto do_pp; goto do_pp;


if (branch_name && *branch_name) if (description_file && *description_file)
read_desc_file(&description_sb, description_file);
else if (branch_name && *branch_name)
read_branch_desc(&description_sb, branch_name); read_branch_desc(&description_sb, branch_name);
if (!description_sb.len) if (!description_sb.len)
goto do_pp; goto do_pp;
@ -1313,6 +1323,7 @@ static void get_notes_args(struct strvec *arg, struct rev_info *rev)
static void make_cover_letter(struct rev_info *rev, int use_separate_file, static void make_cover_letter(struct rev_info *rev, int use_separate_file,
struct commit *origin, struct commit *origin,
int nr, struct commit **list, int nr, struct commit **list,
const char *description_file,
const char *branch_name, const char *branch_name,
int quiet) int quiet)
{ {
@ -1352,7 +1363,8 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
pp.rev = rev; pp.rev = rev;
pp.print_email_subject = 1; pp.print_email_subject = 1;
pp_user_info(&pp, NULL, &sb, committer, encoding); pp_user_info(&pp, NULL, &sb, committer, encoding);
prepare_cover_text(&pp, branch_name, &sb, encoding, need_8bit_cte); prepare_cover_text(&pp, description_file, branch_name, &sb,
encoding, need_8bit_cte);
fprintf(rev->diffopt.file, "%s\n", sb.buf); fprintf(rev->diffopt.file, "%s\n", sb.buf);


strbuf_release(&sb); strbuf_release(&sb);
@ -1893,6 +1905,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
int quiet = 0; int quiet = 0;
const char *reroll_count = NULL; const char *reroll_count = NULL;
char *cover_from_description_arg = NULL; char *cover_from_description_arg = NULL;
char *description_file = NULL;
char *branch_name = NULL; char *branch_name = NULL;
char *base_commit = NULL; char *base_commit = NULL;
struct base_tree_info bases; struct base_tree_info bases;
@ -1936,6 +1949,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
OPT_STRING(0, "cover-from-description", &cover_from_description_arg, OPT_STRING(0, "cover-from-description", &cover_from_description_arg,
N_("cover-from-description-mode"), N_("cover-from-description-mode"),
N_("generate parts of a cover letter based on a branch's description")), N_("generate parts of a cover letter based on a branch's description")),
OPT_FILENAME(0, "description-file", &description_file,
N_("use branch description from file")),
OPT_CALLBACK_F(0, "subject-prefix", &rev, N_("prefix"), OPT_CALLBACK_F(0, "subject-prefix", &rev, N_("prefix"),
N_("use [<prefix>] instead of [PATCH]"), N_("use [<prefix>] instead of [PATCH]"),
PARSE_OPT_NONEG, subject_prefix_callback), PARSE_OPT_NONEG, subject_prefix_callback),
@ -2321,7 +2336,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (thread) if (thread)
gen_message_id(&rev, "cover"); gen_message_id(&rev, "cover");
make_cover_letter(&rev, !!output_directory, make_cover_letter(&rev, !!output_directory,
origin, nr, list, branch_name, quiet); origin, nr, list, description_file, branch_name, quiet);
print_bases(&bases, rev.diffopt.file); print_bases(&bases, rev.diffopt.file);
print_signature(rev.diffopt.file); print_signature(rev.diffopt.file);
total++; total++;

View File

@ -1991,6 +1991,20 @@ test_expect_success 'cover letter using branch description (6)' '
grep hello actual grep hello actual
' '


test_expect_success 'cover letter with --description-file' '
test_when_finished "rm -f description.txt" &&
cat >description.txt <<-\EOF &&
subject from file

body from file
EOF
git checkout rebuild-1 &&
git format-patch --stdout --cover-letter --cover-from-description auto \
--description-file description.txt main >actual &&
grep "^Subject: \[PATCH 0/2\] subject from file$" actual &&
grep "^body from file$" actual
'

test_expect_success 'cover letter with nothing' ' test_expect_success 'cover letter with nothing' '
git format-patch --stdout --cover-letter >actual && git format-patch --stdout --cover-letter >actual &&
test_line_count = 0 actual test_line_count = 0 actual