From b079c50e03a812f5c8197b8f38e0a5fe6dd31321 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 19 Feb 2009 22:26:31 +0100 Subject: format-patch: track several references Currently, format-patch can only track a single reference (the In-Reply-To:) for each mail. To ensure proper threading, we should list all known references for every mail. Change the rev_info.ref_message_id field to a string_list, so that we can append references at will, and change the output formatting routines to print all of them in the References: header. The last entry in the list is implicitly assumed to be the In-Reply-To:, which gives output consistent with RFC 2822: The "References:" field will contain the contents of the parent's "References:" field (if any) followed by the contents of the parent's "Message-ID:" field (if any). Note that this is just preparatory work; nothing uses it yet, so all "References:" fields in the output are still only one deep. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- builtin-log.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 2ae39afcc..59671139b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -17,6 +17,7 @@ #include "run-command.h" #include "shortlog.h" #include "remote.h" +#include "string-list.h" /* Set a default date-time format for git log ("log.date" config variable) */ static const char *default_date_mode = NULL; @@ -1011,8 +1012,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) numbered = 1; if (numbered) rev.total = total + start_number - 1; - if (in_reply_to) - rev.ref_message_id = clean_message_id(in_reply_to); + if (in_reply_to || thread || cover_letter) + rev.ref_message_ids = xcalloc(1, sizeof(struct string_list)); + if (in_reply_to) { + const char *msgid = clean_message_id(in_reply_to); + string_list_append(msgid, rev.ref_message_ids); + } if (cover_letter) { if (thread) gen_message_id(&rev, "cover"); @@ -1036,10 +1041,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * otherwise, make everything a reply * to that. */ - if (rev.ref_message_id) + if (rev.ref_message_ids->nr > 0) free(rev.message_id); else - rev.ref_message_id = rev.message_id; + string_list_append(rev.message_id, + rev.ref_message_ids); } gen_message_id(&rev, sha1_to_hex(commit->object.sha1)); } -- cgit v1.2.1 From 2175c10d5ad2769936f5bf5bcca5ea32715a7307 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 19 Feb 2009 22:26:32 +0100 Subject: format-patch: thread as reply to cover letter even with in-reply-to Currently, format-patch --thread --cover-letter --in-reply-to $parent makes all mails, including the cover letter, a reply to $parent. However, we would want the reader to consider the cover letter above all the patches. This changes the semantics so that only the cover letter is a reply to $parent, while all the patches are formatted as replies to the cover letter. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- builtin-log.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 59671139b..1df38e17a 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -1036,12 +1036,22 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* Have we already had a message ID? */ if (rev.message_id) { /* - * If we've got the ID to be a reply - * to, discard the current ID; - * otherwise, make everything a reply - * to that. + * Without --cover-letter and + * --in-reply-to, make every mail a + * reply to the one before. + * + * With --in-reply-to but no + * --cover-letter, make every mail a + * reply to the . + * + * With --cover-letter, make every + * mail but the cover letter a reply + * to the cover letter. The cover + * letter is a reply to the + * --in-reply-to, if specified. */ - if (rev.ref_message_ids->nr > 0) + if (rev.ref_message_ids->nr > 0 + && (!cover_letter || rev.nr > 1)) free(rev.message_id); else string_list_append(rev.message_id, -- cgit v1.2.1 From 30984ed2e92651962c6b8bdacf1f84da75d1da95 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Thu, 19 Feb 2009 22:26:33 +0100 Subject: format-patch: support deep threading For deep threading mode, i.e., the mode that gives a thread structured like + [PATCH 0/n] Cover letter `-+ [PATCH 1/n] First patch `-+ [PATCH 2/n] Second patch `-+ ... we currently have to use 'git send-email --thread' (the default). On the other hand, format-patch also has a --thread option which gives shallow mode, i.e., + [PATCH 0/n] Cover letter |-+ [PATCH 1/n] First patch |-+ [PATCH 2/n] Second patch ... To reduce the confusion resulting from having two indentically named features in different tools giving different results, let format-patch take an optional argument '--thread=deep' that gives the same output as 'send-mail --thread'. With no argument, or 'shallow', behave as before. Also add a configuration variable format.thread with the same semantics. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- builtin-log.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'builtin-log.c') diff --git a/builtin-log.c b/builtin-log.c index 1df38e17a..6bf04e8af 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -460,6 +460,10 @@ static void add_header(const char *value) extra_hdr[extra_hdr_nr++] = xstrndup(value, len); } +#define THREAD_SHALLOW 1 +#define THREAD_DEEP 2 +static int thread = 0; + static int git_format_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "format.headers")) { @@ -489,6 +493,18 @@ static int git_format_config(const char *var, const char *value, void *cb) auto_number = auto_number && numbered; return 0; } + if (!strcmp(var, "format.thread")) { + if (value && !strcasecmp(value, "deep")) { + thread = THREAD_DEEP; + return 0; + } + if (value && !strcasecmp(value, "shallow")) { + thread = THREAD_SHALLOW; + return 0; + } + thread = git_config_bool(var, value) && THREAD_SHALLOW; + return 0; + } return git_log_config(var, value, cb); } @@ -767,7 +783,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int numbered_files = 0; /* _just_ numbers */ int subject_prefix = 0; int ignore_if_in_upstream = 0; - int thread = 0; int cover_letter = 0; int boundary_count = 0; int no_binary_diff = 0; @@ -860,8 +875,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } else if (!strcmp(argv[i], "--ignore-if-in-upstream")) ignore_if_in_upstream = 1; - else if (!strcmp(argv[i], "--thread")) - thread = 1; + else if (!strcmp(argv[i], "--thread") + || !strcmp(argv[i], "--thread=shallow")) + thread = THREAD_SHALLOW; + else if (!strcmp(argv[i], "--thread=deep")) + thread = THREAD_DEEP; + else if (!strcmp(argv[i], "--no-thread")) + thread = 0; else if (!prefixcmp(argv[i], "--in-reply-to=")) in_reply_to = argv[i] + 14; else if (!strcmp(argv[i], "--in-reply-to")) { @@ -1036,6 +1056,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* Have we already had a message ID? */ if (rev.message_id) { /* + * For deep threading: make every mail + * a reply to the previous one, no + * matter what other options are set. + * + * For shallow threading: + * * Without --cover-letter and * --in-reply-to, make every mail a * reply to the one before. @@ -1050,7 +1076,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * letter is a reply to the * --in-reply-to, if specified. */ - if (rev.ref_message_ids->nr > 0 + if (thread == THREAD_SHALLOW + && rev.ref_message_ids->nr > 0 && (!cover_letter || rev.nr > 1)) free(rev.message_id); else -- cgit v1.2.1