All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vegard Nossum <vegard.nossum@oracle.com>
To: Junio C Hamano <gitster@pobox.com>, git@vger.kernel.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Vegard Nossum <vegard.nossum@oracle.com>
Subject: [RFC PATCH v2 1/3] format-patch: add --complete
Date: Tue, 22 Oct 2019 13:45:16 +0200	[thread overview]
Message-ID: <20191022114518.32055-2-vegard.nossum@oracle.com> (raw)
In-Reply-To: <20191022114518.32055-1-vegard.nossum@oracle.com>

This option causes the raw commit data to be inserted between the
changelog and the diffstat when you run git-format-patch. With a
following patch to 'git am', this will allow the exact reconstruction
of the commit to the point where the sha1 will be the same.

There is also a new config option controlling the default behaviour:

  format.complete

Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
Previous-version: 622a0469a4970c5daac0c0323e2d6a77b3bebbdb
---
 Documentation/config/format.txt    |  7 ++++++
 Documentation/git-format-patch.txt |  9 ++++++++
 builtin/log.c                      | 35 ++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)

diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt
index 40cad9278f..3a38679837 100644
--- a/Documentation/config/format.txt
+++ b/Documentation/config/format.txt
@@ -87,6 +87,13 @@ format.useAutoBase::
 	A boolean value which lets you enable the `--base=auto` option of
 	format-patch by default.
 
+format.complete::
+	Provides the default value for the `--complete` option to
+	format-patch. If true, the raw commit metadata (including the
+	SHA1) is included at the bottom of the diff, before the signature.
+	This allows a recipient who has all the parent commits and/or the
+	tree to reconstruct the commit with the same SHA1.
+
 format.notes::
 	Provides the default value for the `--notes` option to
 	format-patch. Accepts a boolean value, or a ref which specifies
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 2035d4d5d5..74fc6d8a8c 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -26,6 +26,7 @@ SYNOPSIS
 		   [--no-notes | --notes[=<ref>]]
 		   [--interdiff=<previous>]
 		   [--range-diff=<previous> [--creation-factor=<percent>]]
+		   [--[no-]complete]
 		   [--progress]
 		   [<common diff options>]
 		   [ <since> | <revision range> ]
@@ -325,6 +326,14 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.
 	range are always formatted as creation patches, independently
 	of this flag.
 
+--[no-]complete::
+	Include the raw commit metadata (including the SHA1) at the
+	bottom of the diff, before the signature. This allows a
+	recipient who has all the parent commits and/or the tree to
+	reconstruct the commit with the same SHA1. The default is
+	`--no-complete`, unless the `format.complete` configuration
+	option is set.
+
 --progress::
 	Show progress reports on stderr as patches are generated.
 
diff --git a/builtin/log.c b/builtin/log.c
index 89873d2dc2..822a0838b6 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -783,6 +783,8 @@ enum {
 	COVER_AUTO
 };
 
+static int fmt_complete;
+
 static int git_format_config(const char *var, const char *value, void *cb)
 {
 	struct rev_info *rev = cb;
@@ -888,6 +890,10 @@ static int git_format_config(const char *var, const char *value, void *cb)
 		}
 		return 0;
 	}
+	if (!strcmp(var, "format.complete")) {
+		fmt_complete = git_config_bool(var, value);
+		return 0;
+	}
 
 	return git_log_config(var, value, cb);
 }
@@ -1490,6 +1496,23 @@ static void print_bases(struct base_tree_info *bases, FILE *file)
 	oidclr(&bases->base_commit);
 }
 
+static void print_meta(struct rev_info *opt, struct commit *commit)
+{
+	const char *buffer = get_commit_buffer(commit, NULL);
+	const char *subject;
+
+	fprintf(opt->diffopt.file, "--\n");
+	fprintf(opt->diffopt.file, "commit %s\n", oid_to_hex(&commit->object.oid));
+
+	/*
+	 * TODO: hex-encode to avoid mailer mangling?
+	 */
+	if (find_commit_subject(buffer, &subject))
+		fprintf(opt->diffopt.file, "%.*s", (int) (subject - buffer), buffer);
+	else
+		fprintf(opt->diffopt.file, "%s", buffer);
+}
+
 static const char *diff_title(struct strbuf *sb, int reroll_count,
 		       const char *generic, const char *rerolled)
 {
@@ -1622,6 +1645,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 			    N_("add a signature")),
 		OPT_STRING(0, "base", &base_commit, N_("base-commit"),
 			   N_("add prerequisite tree info to the patch series")),
+		OPT_BOOL(0, "complete", &fmt_complete,
+			 N_("include all the information necessary to reconstruct commit exactly")),
 		OPT_FILENAME(0, "signature-file", &signature_file,
 				N_("add a signature from a file")),
 		OPT__QUIET(&quiet, N_("don't print the patch filenames")),
@@ -1921,6 +1946,14 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		prepare_bases(&bases, base, list, nr);
 	}
 
+	if (fmt_complete) {
+		/*
+		 * We need the commit buffer so that we can output the exact
+		 * sequence of bytes that gets hashed as part of a commit.
+		 */
+		save_commit_buffer = 1;
+	}
+
 	if (in_reply_to || thread || cover_letter)
 		rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
 	if (in_reply_to) {
@@ -2004,6 +2037,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 			rev.shown_one = 0;
 		if (shown) {
 			print_bases(&bases, rev.diffopt.file);
+			if (fmt_complete)
+				print_meta(&rev, commit);
 			if (rev.mime_boundary)
 				fprintf(rev.diffopt.file, "\n--%s%s--\n\n\n",
 				       mime_boundary_leader,
--
commit 7fa59e79ef5474fb4c657fb2ff6a8341cc17c897
tree 891d334e23f950afbaaafc182384309fd8c73e48
parent d966095db01190a2196e31195ea6fa0c722aa732
author Vegard Nossum <vegard.nossum@oracle.com> 1570284959 +0200
committer Vegard Nossum <vegard.nossum@oracle.com> 1571666151 +0200

-- 
2.24.0.rc0.3.g4ba423c3c2


  reply	other threads:[~2019-10-22 11:48 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-22 11:45 [RFC PATCH v2 0/3] format-patch --complete / am --exact Vegard Nossum
2019-10-22 11:45 ` Vegard Nossum [this message]
2019-10-22 11:45 ` [RFC PATCH v2 2/3] mailinfo: collect commit metadata from mail Vegard Nossum
2019-10-27 18:44   ` brian m. carlson
2019-10-28 11:48     ` Vegard Nossum
2019-10-29  1:39       ` brian m. carlson
2019-10-22 11:45 ` [RFC PATCH v2 3/3] am: add --exact Vegard Nossum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191022114518.32055-2-vegard.nossum@oracle.com \
    --to=vegard.nossum@oracle.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=pbonzini@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.