summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2013-02-21 12:05:02 -0800
committerJunio C Hamano <gitster@pobox.com>2013-04-22 07:59:22 -0700
commitbe1a07fe27695081537d31748b989f86c82383cc (patch)
tree36bec251b5259cf89c85a47158e6f75070726d43
parent47d6c5f2c112df55997742eab8d974bfa1cf7b3e (diff)
downloadgit-jc/format-patch.tar.gz
format-patch: --inline-singlejc/format-patch
Some people may find it convenient to append a simple patch at the bottom of a discussion e-mail separated by a "scissors" mark, ready to be applied with "git am -c". Introduce "--inline-single" option to format-patch to do so. A typical usage example might be to start 'f'ollow-up to a discussion, write your message, conclude with "a patch to do so may look like this.", and then \C-u M-! git format-patch --inline-single -1 HEAD <ENTER> if you are an Emacs user. Users of other MUA's may want to consult their manuals to find an equivalent command to append output from an external command to the message being composed. It does not make any sense to use this mode when formatting multiple patches, or to combine this with options such as --attach, --inline, and --cover-letter, so some of such uses are forbidden. There may be more insane combination the check in this patch may not even bother to reject. Caveat emptor. Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/log.c32
-rw-r--r--commit.h1
-rw-r--r--log-tree.c7
-rw-r--r--pretty.c27
-rw-r--r--revision.h1
5 files changed, 66 insertions, 2 deletions
diff --git a/builtin/log.c b/builtin/log.c
index f2a11f4853..5696c6764e 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1051,6 +1051,19 @@ static int inline_callback(const struct option *opt, const char *arg, int unset)
return 0;
}
+static int inline_single_callback(const struct option *opt, const char *arg, int unset)
+{
+ struct rev_info *rev = (struct rev_info *)opt->value;
+ rev->mime_boundary = NULL;
+ rev->inline_single = 1;
+
+ /* defeat configured format.attach, format.thread, etc. */
+ free(default_attach);
+ default_attach = NULL;
+ thread = 0;
+ return 0;
+}
+
static int header_callback(const struct option *opt, const char *arg, int unset)
{
if (unset) {
@@ -1160,6 +1173,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
PARSE_OPT_OPTARG, thread_callback },
OPT_STRING(0, "signature", &signature, N_("signature"),
N_("add a signature")),
+ { OPTION_CALLBACK, 0, "inline-single", &rev, NULL,
+ N_("single patch appendable to the end of an e-mail body"),
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+ inline_single_callback },
OPT_BOOLEAN(0, "quiet", &quiet,
N_("don't print the patch filenames")),
OPT_END()
@@ -1196,6 +1213,15 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
PARSE_OPT_KEEP_DASHDASH);
+ /* Set defaults and check incompatible options */
+ if (rev.inline_single) {
+ use_stdout = 1;
+ if (thread)
+ die(_("inline-single and thread are incompatible."));
+ if (output_directory)
+ die(_("inline-single and output-directory are incompatible."));
+ }
+
if (0 < reroll_count) {
struct strbuf sprefix = STRBUF_INIT;
strbuf_addf(&sprefix, "%s v%d",
@@ -1362,6 +1388,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
/* nothing to do */
return 0;
total = nr;
+
+ if (rev.inline_single && total != 1)
+ die(_("inline-single is only for a single commit"));
+
if (!keep_subject && auto_number && total > 1)
numbered = 1;
if (numbered)
@@ -1372,6 +1402,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
else
cover_letter = (config_cover_letter == COVER_ON);
}
+ if (cover_letter > 0 && rev.inline_single)
+ die(_("inline-single and cover-letter are incompatible."));
if (in_reply_to || thread || cover_letter)
rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
diff --git a/commit.h b/commit.h
index 057ff8045e..c7d026bb2d 100644
--- a/commit.h
+++ b/commit.h
@@ -86,6 +86,7 @@ struct pretty_print_context {
int preserve_subject;
enum date_mode date_mode;
unsigned date_mode_explicit:1;
+ unsigned inline_single:1;
int need_8bit_cte;
char *notes_message;
struct reflog_walk_info *reflog_info;
diff --git a/log-tree.c b/log-tree.c
index 5ab821c8f3..254fb285d3 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -276,7 +276,11 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
subject = "Subject: ";
}
- printf("From %s Mon Sep 17 00:00:00 2001\n", name);
+ if (opt->inline_single)
+ printf("-- >8 --\n");
+ else
+ printf("From %s Mon Sep 17 00:00:00 2001\n", name);
+
graph_show_oneline(opt->graph);
if (opt->message_id) {
printf("Message-Id: <%s>\n", opt->message_id);
@@ -600,6 +604,7 @@ void show_log(struct rev_info *opt)
ctx.fmt = opt->commit_format;
ctx.mailmap = opt->mailmap;
ctx.color = opt->diffopt.use_color;
+ ctx.inline_single = opt->inline_single;
pretty_print_commit(&ctx, commit, &msgbuf);
if (opt->add_signoff)
diff --git a/pretty.c b/pretty.c
index d3a82d22d3..4a0495430a 100644
--- a/pretty.c
+++ b/pretty.c
@@ -393,6 +393,29 @@ static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
strbuf_addstr(sb, "?=");
}
+static int is_current_user(const struct pretty_print_context *pp,
+ const char *email, size_t emaillen,
+ const char *name, size_t namelen)
+{
+ const char *me = git_committer_info(0);
+ const char *myname, *mymail;
+ size_t mynamelen, mymaillen;
+ struct ident_split ident;
+
+ if (split_ident_line(&ident, me, strlen(me)))
+ return 0; /* play safe, as we do not know */
+ mymail = ident.mail_begin;
+ mymaillen = ident.mail_end - ident.mail_begin;
+ myname = ident.name_begin;
+ mynamelen = ident.name_end - ident.name_begin;
+ if (pp->mailmap)
+ map_user(pp->mailmap, &mymail, &mymaillen, &myname, &mynamelen);
+ return (mymaillen == emaillen &&
+ mynamelen == namelen &&
+ !memcmp(mymail, email, emaillen) &&
+ !memcmp(myname, name, namelen));
+}
+
void pp_user_info(const struct pretty_print_context *pp,
const char *what, struct strbuf *sb,
const char *line, const char *encoding)
@@ -422,7 +445,6 @@ void pp_user_info(const struct pretty_print_context *pp,
if (split_ident_line(&ident, line, linelen))
return;
-
mailbuf = ident.mail_begin;
maillen = ident.mail_end - ident.mail_begin;
namebuf = ident.name_begin;
@@ -431,6 +453,9 @@ void pp_user_info(const struct pretty_print_context *pp,
if (pp->mailmap)
map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
+ if (pp->inline_single && is_current_user(pp, mailbuf, maillen, namebuf, namelen))
+ return;
+
strbuf_init(&mail, 0);
strbuf_init(&name, 0);
diff --git a/revision.h b/revision.h
index 40b9773b6c..1f7de1b8b9 100644
--- a/revision.h
+++ b/revision.h
@@ -143,6 +143,7 @@ struct rev_info {
const char *log_reencode;
const char *subject_prefix;
int disposition_attachment;
+ int inline_single;
int show_log_size;
struct string_list *mailmap;