Merge branch 'jc/format-patch-reroll'

Teach "format-patch" to prefix v4- to its output files for the
fourth iteration of a patch series, to make it easier for the
submitter to keep separate copies for iterations.

* jc/format-patch-reroll:
  format-patch: give --reroll-count a short synonym -v
  format-patch: document and test --reroll-count
  format-patch: add --reroll-count=$N option
  get_patch_filename(): split into two functions
  get_patch_filename(): drop "just-numbers" hack
  get_patch_filename(): simplify function signature
  builtin/log.c: stop using global patch_suffix
  builtin/log.c: drop redundant "numbered_files" parameter from make_cover_letter()
  builtin/log.c: drop unused "numbered" parameter from make_cover_letter()
This commit is contained in:
Junio C Hamano
2013-01-11 18:34:10 -08:00
6 changed files with 81 additions and 30 deletions

View File

@ -18,7 +18,7 @@ SYNOPSIS
[--start-number <n>] [--numbered-files] [--start-number <n>] [--numbered-files]
[--in-reply-to=Message-Id] [--suffix=.<sfx>] [--in-reply-to=Message-Id] [--suffix=.<sfx>]
[--ignore-if-in-upstream] [--ignore-if-in-upstream]
[--subject-prefix=Subject-Prefix] [--subject-prefix=Subject-Prefix] [(--reroll-count|-v) <n>]
[--to=<email>] [--cc=<email>] [--to=<email>] [--cc=<email>]
[--cover-letter] [--quiet] [--notes[=<ref>]] [--cover-letter] [--quiet] [--notes[=<ref>]]
[<common diff options>] [<common diff options>]
@ -166,6 +166,15 @@ will want to ensure that threading is disabled for `git send-email`.
allows for useful naming of a patch series, and can be allows for useful naming of a patch series, and can be
combined with the `--numbered` option. combined with the `--numbered` option.
-v <n>::
--reroll-count=<n>::
Mark the series as the <n>-th iteration of the topic. The
output filenames have `v<n>` pretended to them, and the
subject prefix ("PATCH" by default, but configurable via the
`--subject-prefix` option) has ` v<n>` appended to it. E.g.
`--reroll-count=4` may produce `v4-0001-add-makefile.patch`
file that has "Subject: [PATCH v4 1/20] Add makefile" in it.
--to=<email>:: --to=<email>::
Add a `To:` header to the email headers. This is in addition Add a `To:` header to the email headers. This is in addition
to any configured headers, and may be used multiple times. to any configured headers, and may be used multiple times.

View File

@ -678,7 +678,7 @@ static int reopen_stdout(struct commit *commit, const char *subject,
struct rev_info *rev, int quiet) struct rev_info *rev, int quiet)
{ {
struct strbuf filename = STRBUF_INIT; struct strbuf filename = STRBUF_INIT;
int suffix_len = strlen(fmt_patch_suffix) + 1; int suffix_len = strlen(rev->patch_suffix) + 1;
if (output_directory) { if (output_directory) {
strbuf_addstr(&filename, output_directory); strbuf_addstr(&filename, output_directory);
@ -689,7 +689,12 @@ static int reopen_stdout(struct commit *commit, const char *subject,
strbuf_addch(&filename, '/'); strbuf_addch(&filename, '/');
} }
get_patch_filename(commit, subject, rev->nr, fmt_patch_suffix, &filename); if (rev->numbered_files)
strbuf_addf(&filename, "%d", rev->nr);
else if (commit)
fmt_output_commit(&filename, commit, rev);
else
fmt_output_subject(&filename, subject, rev);
if (!quiet) if (!quiet)
fprintf(realstdout, "%s\n", filename.buf + outdir_offset); fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
@ -773,7 +778,6 @@ static void add_branch_description(struct strbuf *buf, const char *branch_name)
} }
static void make_cover_letter(struct rev_info *rev, int use_stdout, static void make_cover_letter(struct rev_info *rev, int use_stdout,
int numbered, int numbered_files,
struct commit *origin, struct commit *origin,
int nr, struct commit **list, struct commit *head, int nr, struct commit **list, struct commit *head,
const char *branch_name, const char *branch_name,
@ -796,7 +800,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
committer = git_committer_info(0); committer = git_committer_info(0);
if (!use_stdout && if (!use_stdout &&
reopen_stdout(NULL, numbered_files ? NULL : "cover-letter", rev, quiet)) reopen_stdout(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
return; return;
log_write_email_headers(rev, head, &pp.subject, &pp.after_subject, log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
@ -1060,7 +1064,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
int nr = 0, total, i; int nr = 0, total, i;
int use_stdout = 0; int use_stdout = 0;
int start_number = -1; int start_number = -1;
int numbered_files = 0; /* _just_ numbers */ int just_numbers = 0;
int ignore_if_in_upstream = 0; int ignore_if_in_upstream = 0;
int cover_letter = 0; int cover_letter = 0;
int boundary_count = 0; int boundary_count = 0;
@ -1072,6 +1076,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
int use_patch_format = 0; int use_patch_format = 0;
int quiet = 0; int quiet = 0;
int reroll_count = -1;
char *branch_name = NULL; char *branch_name = NULL;
const struct option builtin_format_patch_options[] = { const struct option builtin_format_patch_options[] = {
{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL, { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
@ -1085,12 +1090,14 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
N_("print patches to standard out")), N_("print patches to standard out")),
OPT_BOOLEAN(0, "cover-letter", &cover_letter, OPT_BOOLEAN(0, "cover-letter", &cover_letter,
N_("generate a cover letter")), N_("generate a cover letter")),
OPT_BOOLEAN(0, "numbered-files", &numbered_files, OPT_BOOLEAN(0, "numbered-files", &just_numbers,
N_("use simple number sequence for output file names")), N_("use simple number sequence for output file names")),
OPT_STRING(0, "suffix", &fmt_patch_suffix, N_("sfx"), OPT_STRING(0, "suffix", &fmt_patch_suffix, N_("sfx"),
N_("use <sfx> instead of '.patch'")), N_("use <sfx> instead of '.patch'")),
OPT_INTEGER(0, "start-number", &start_number, OPT_INTEGER(0, "start-number", &start_number,
N_("start numbering patches at <n> instead of 1")), N_("start numbering patches at <n> instead of 1")),
OPT_INTEGER('v', "reroll-count", &reroll_count,
N_("mark the series as Nth re-roll")),
{ OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"), { OPTION_CALLBACK, 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 },
@ -1164,6 +1171,14 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
PARSE_OPT_KEEP_DASHDASH); PARSE_OPT_KEEP_DASHDASH);
if (0 < reroll_count) {
struct strbuf sprefix = STRBUF_INIT;
strbuf_addf(&sprefix, "%s v%d",
rev.subject_prefix, reroll_count);
rev.reroll_count = reroll_count;
rev.subject_prefix = strbuf_detach(&sprefix, NULL);
}
if (do_signoff) { if (do_signoff) {
const char *committer; const char *committer;
const char *endpos; const char *endpos;
@ -1354,12 +1369,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
const char *msgid = clean_message_id(in_reply_to); const char *msgid = clean_message_id(in_reply_to);
string_list_append(rev.ref_message_ids, msgid); string_list_append(rev.ref_message_ids, msgid);
} }
rev.numbered_files = numbered_files; rev.numbered_files = just_numbers;
rev.patch_suffix = fmt_patch_suffix; rev.patch_suffix = fmt_patch_suffix;
if (cover_letter) { if (cover_letter) {
if (thread) if (thread)
gen_message_id(&rev, "cover"); gen_message_id(&rev, "cover");
make_cover_letter(&rev, use_stdout, numbered, numbered_files, make_cover_letter(&rev, use_stdout,
origin, nr, list, head, branch_name, quiet); origin, nr, list, head, branch_name, quiet);
total++; total++;
start_number--; start_number--;
@ -1406,7 +1421,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
} }
if (!use_stdout && if (!use_stdout &&
reopen_stdout(numbered_files ? NULL : commit, NULL, &rev, quiet)) reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
die(_("Failed to create output files")); die(_("Failed to create output files"));
shown = log_tree_commit(&rev, commit); shown = log_tree_commit(&rev, commit);
free(commit->buffer); free(commit->buffer);

View File

@ -299,26 +299,34 @@ static unsigned int digits_in_number(unsigned int number)
return result; return result;
} }
void get_patch_filename(struct commit *commit, const char *subject, int nr, void fmt_output_subject(struct strbuf *filename,
const char *suffix, struct strbuf *buf) const char *subject,
struct rev_info *info)
{ {
int suffix_len = strlen(suffix) + 1; const char *suffix = info->patch_suffix;
int start_len = buf->len; int nr = info->nr;
int start_len = filename->len;
int max_len = start_len + FORMAT_PATCH_NAME_MAX - (strlen(suffix) + 1);
strbuf_addf(buf, commit || subject ? "%04d-" : "%d", nr); if (0 < info->reroll_count)
if (commit || subject) { strbuf_addf(filename, "v%d-", info->reroll_count);
int max_len = start_len + FORMAT_PATCH_NAME_MAX - suffix_len; strbuf_addf(filename, "%04d-%s", nr, subject);
struct pretty_print_context ctx = {0};
if (subject) if (max_len < filename->len)
strbuf_addstr(buf, subject); strbuf_setlen(filename, max_len);
else if (commit) strbuf_addstr(filename, suffix);
format_commit_message(commit, "%f", buf, &ctx); }
if (max_len < buf->len) void fmt_output_commit(struct strbuf *filename,
strbuf_setlen(buf, max_len); struct commit *commit,
strbuf_addstr(buf, suffix); struct rev_info *info)
} {
struct pretty_print_context ctx = {0};
struct strbuf subject = STRBUF_INIT;
format_commit_message(commit, "%f", &subject, &ctx);
fmt_output_subject(filename, subject.buf, info);
strbuf_release(&subject);
} }
void log_write_email_headers(struct rev_info *opt, struct commit *commit, void log_write_email_headers(struct rev_info *opt, struct commit *commit,
@ -387,8 +395,10 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
mime_boundary_leader, opt->mime_boundary); mime_boundary_leader, opt->mime_boundary);
extra_headers = subject_buffer; extra_headers = subject_buffer;
get_patch_filename(opt->numbered_files ? NULL : commit, NULL, if (opt->numbered_files)
opt->nr, opt->patch_suffix, &filename); strbuf_addf(&filename, "%d", opt->nr);
else
fmt_output_commit(&filename, commit, opt);
snprintf(buffer, sizeof(buffer) - 1, snprintf(buffer, sizeof(buffer) - 1,
"\n--%s%s\n" "\n--%s%s\n"
"Content-Type: text/x-patch;" "Content-Type: text/x-patch;"

View File

@ -21,7 +21,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
void load_ref_decorations(int flags); void load_ref_decorations(int flags);
#define FORMAT_PATCH_NAME_MAX 64 #define FORMAT_PATCH_NAME_MAX 64
void get_patch_filename(struct commit *commit, const char *subject, int nr, void fmt_output_commit(struct strbuf *, struct commit *, struct rev_info *);
const char *suffix, struct strbuf *buf); void fmt_output_subject(struct strbuf *, const char *subject, struct rev_info *);
#endif #endif

View File

@ -135,6 +135,7 @@ struct rev_info {
const char *mime_boundary; const char *mime_boundary;
const char *patch_suffix; const char *patch_suffix;
int numbered_files; int numbered_files;
int reroll_count;
char *message_id; char *message_id;
struct string_list *ref_message_ids; struct string_list *ref_message_ids;
const char *add_signoff; const char *add_signoff;

View File

@ -271,6 +271,22 @@ test_expect_success 'multiple files' '
ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch
' '
test_expect_success 'reroll count' '
rm -fr patches &&
git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
! grep -v "^patches/v4-000[0-3]-" list &&
sed -n -e "/^Subject: /p" $(cat list) >subjects &&
! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
'
test_expect_success 'reroll count (-v)' '
rm -fr patches &&
git format-patch -o patches --cover-letter -v4 master..side >list &&
! grep -v "^patches/v4-000[0-3]-" list &&
sed -n -e "/^Subject: /p" $(cat list) >subjects &&
! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
'
check_threading () { check_threading () {
expect="$1" && expect="$1" &&
shift && shift &&