Skip to content

Commit 5a5bd23

Browse files
committed
Merge branch 'tr/format-patch-thread'
* tr/format-patch-thread: format-patch: support deep threading format-patch: thread as reply to cover letter even with in-reply-to format-patch: track several references format-patch: threading test reactivation Conflicts: builtin-log.c
2 parents 72e3c32 + 30984ed commit 5a5bd23

File tree

6 files changed

+307
-55
lines changed

6 files changed

+307
-55
lines changed

Documentation/config.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,16 @@ format.pretty::
677677
See linkgit:git-log[1], linkgit:git-show[1],
678678
linkgit:git-whatchanged[1].
679679

680+
format.thread::
681+
The default threading style for 'git-format-patch'. Can be
682+
either a boolean value, `shallow` or `deep`. 'Shallow'
683+
threading makes every mail a reply to the head of the series,
684+
where the head is chosen from the cover letter, the
685+
`\--in-reply-to`, and the first patch mail, in this order.
686+
'Deep' threading makes every mail a reply to the previous one.
687+
A true boolean value is the same as `shallow`, and a false
688+
value disables threading.
689+
680690
gc.aggressiveWindow::
681691
The window size parameter used in the delta compression
682692
algorithm used by 'git-gc --aggressive'. This defaults

Documentation/git-format-patch.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,18 @@ include::diff-options.txt[]
127127
which is the commit message and the patch itself in the
128128
second part, with "Content-Disposition: inline".
129129

130-
--thread::
130+
--thread[=<style>]::
131131
Add In-Reply-To and References headers to make the second and
132132
subsequent mails appear as replies to the first. Also generates
133133
the Message-Id header to reference.
134+
+
135+
The optional <style> argument can be either `shallow` or `deep`.
136+
'Shallow' threading makes every mail a reply to the head of the
137+
series, where the head is chosen from the cover letter, the
138+
`\--in-reply-to`, and the first patch mail, in this order. 'Deep'
139+
threading makes every mail a reply to the previous one. If not
140+
specified, defaults to the 'format.thread' configuration, or `shallow`
141+
if that is not set.
134142

135143
--in-reply-to=Message-Id::
136144
Make the first mail (or all the mails with --no-thread) appear as a

builtin-log.c

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "run-command.h"
1818
#include "shortlog.h"
1919
#include "remote.h"
20+
#include "string-list.h"
2021

2122
/* Set a default date-time format for git log ("log.date" config variable) */
2223
static const char *default_date_mode = NULL;
@@ -461,6 +462,10 @@ static void add_header(const char *value)
461462
extra_hdr[extra_hdr_nr++] = xstrndup(value, len);
462463
}
463464

465+
#define THREAD_SHALLOW 1
466+
#define THREAD_DEEP 2
467+
static int thread = 0;
468+
464469
static int git_format_config(const char *var, const char *value, void *cb)
465470
{
466471
if (!strcmp(var, "format.headers")) {
@@ -497,7 +502,18 @@ static int git_format_config(const char *var, const char *value, void *cb)
497502
default_attach = xstrdup(git_version_string);
498503
return 0;
499504
}
500-
505+
if (!strcmp(var, "format.thread")) {
506+
if (value && !strcasecmp(value, "deep")) {
507+
thread = THREAD_DEEP;
508+
return 0;
509+
}
510+
if (value && !strcasecmp(value, "shallow")) {
511+
thread = THREAD_SHALLOW;
512+
return 0;
513+
}
514+
thread = git_config_bool(var, value) && THREAD_SHALLOW;
515+
return 0;
516+
}
501517

502518
return git_log_config(var, value, cb);
503519
}
@@ -776,7 +792,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
776792
int numbered_files = 0; /* _just_ numbers */
777793
int subject_prefix = 0;
778794
int ignore_if_in_upstream = 0;
779-
int thread = 0;
780795
int cover_letter = 0;
781796
int boundary_count = 0;
782797
int no_binary_diff = 0;
@@ -878,8 +893,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
878893
}
879894
else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
880895
ignore_if_in_upstream = 1;
881-
else if (!strcmp(argv[i], "--thread"))
882-
thread = 1;
896+
else if (!strcmp(argv[i], "--thread")
897+
|| !strcmp(argv[i], "--thread=shallow"))
898+
thread = THREAD_SHALLOW;
899+
else if (!strcmp(argv[i], "--thread=deep"))
900+
thread = THREAD_DEEP;
901+
else if (!strcmp(argv[i], "--no-thread"))
902+
thread = 0;
883903
else if (!prefixcmp(argv[i], "--in-reply-to="))
884904
in_reply_to = argv[i] + 14;
885905
else if (!strcmp(argv[i], "--in-reply-to")) {
@@ -1030,8 +1050,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
10301050
numbered = 1;
10311051
if (numbered)
10321052
rev.total = total + start_number - 1;
1033-
if (in_reply_to)
1034-
rev.ref_message_id = clean_message_id(in_reply_to);
1053+
if (in_reply_to || thread || cover_letter)
1054+
rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
1055+
if (in_reply_to) {
1056+
const char *msgid = clean_message_id(in_reply_to);
1057+
string_list_append(msgid, rev.ref_message_ids);
1058+
}
10351059
if (cover_letter) {
10361060
if (thread)
10371061
gen_message_id(&rev, "cover");
@@ -1050,15 +1074,33 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
10501074
/* Have we already had a message ID? */
10511075
if (rev.message_id) {
10521076
/*
1053-
* If we've got the ID to be a reply
1054-
* to, discard the current ID;
1055-
* otherwise, make everything a reply
1056-
* to that.
1077+
* For deep threading: make every mail
1078+
* a reply to the previous one, no
1079+
* matter what other options are set.
1080+
*
1081+
* For shallow threading:
1082+
*
1083+
* Without --cover-letter and
1084+
* --in-reply-to, make every mail a
1085+
* reply to the one before.
1086+
*
1087+
* With --in-reply-to but no
1088+
* --cover-letter, make every mail a
1089+
* reply to the <reply-to>.
1090+
*
1091+
* With --cover-letter, make every
1092+
* mail but the cover letter a reply
1093+
* to the cover letter. The cover
1094+
* letter is a reply to the
1095+
* --in-reply-to, if specified.
10571096
*/
1058-
if (rev.ref_message_id)
1097+
if (thread == THREAD_SHALLOW
1098+
&& rev.ref_message_ids->nr > 0
1099+
&& (!cover_letter || rev.nr > 1))
10591100
free(rev.message_id);
10601101
else
1061-
rev.ref_message_id = rev.message_id;
1102+
string_list_append(rev.message_id,
1103+
rev.ref_message_ids);
10621104
}
10631105
gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
10641106
}

log-tree.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "log-tree.h"
77
#include "reflog-walk.h"
88
#include "refs.h"
9+
#include "string-list.h"
910

1011
struct decoration name_decoration = { "object names" };
1112

@@ -211,9 +212,13 @@ void log_write_email_headers(struct rev_info *opt, const char *name,
211212
printf("Message-Id: <%s>\n", opt->message_id);
212213
graph_show_oneline(opt->graph);
213214
}
214-
if (opt->ref_message_id) {
215-
printf("In-Reply-To: <%s>\nReferences: <%s>\n",
216-
opt->ref_message_id, opt->ref_message_id);
215+
if (opt->ref_message_ids && opt->ref_message_ids->nr > 0) {
216+
int i, n;
217+
n = opt->ref_message_ids->nr;
218+
printf("In-Reply-To: <%s>\n", opt->ref_message_ids->items[n-1].string);
219+
for (i = 0; i < n; i++)
220+
printf("%s<%s>\n", (i > 0 ? "\t" : "References: "),
221+
opt->ref_message_ids->items[i].string);
217222
graph_show_oneline(opt->graph);
218223
}
219224
if (opt->mime_boundary) {

revision.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ struct rev_info {
8989
int nr, total;
9090
const char *mime_boundary;
9191
char *message_id;
92-
const char *ref_message_id;
92+
struct string_list *ref_message_ids;
9393
const char *add_signoff;
9494
const char *extra_headers;
9595
const char *log_reencode;

0 commit comments

Comments
 (0)