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:
@ -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.
|
||||||
|
@ -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);
|
||||||
|
46
log-tree.c
46
log-tree.c
@ -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;"
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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 &&
|
||||||
|
Reference in New Issue
Block a user