[PATCH 1/3] format-patch: add --complete

From: Vegard Nossum
Date: Sat Oct 05 2019 - 10:15:59 EST


Include the raw commit data between the changelog and the diffstat.
This will allow 'git am' to reconstruct the commit exactly to the point
where the sha1 will be the same.

Signed-off-by: Vegard Nossum <vegard.nossum@xxxxxxxxxx>
---
commit 622a0469a4970c5daac0c0323e2d6a77b3bebbdb
tree 8f09d9d6ed78f8617b2fe54fe9712990ba808546
parent 108b97dc372828f0e72e56bbb40cae8e1e83ece6
author Vegard Nossum <vegard.nossum@xxxxxxxxxx> 1570284959 +0200
committer Vegard Nossum <vegard.nossum@xxxxxxxxxx> 1571219301 +0200

---
builtin/log.c | 12 ++++++++++++
log-tree.c | 17 +++++++++++++++++
revision.h | 3 ++-
3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/builtin/log.c b/builtin/log.c
index c4b35fdaf9..81c1164ae5 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1545,6 +1545,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
char *branch_name = NULL;
char *base_commit = NULL;
struct base_tree_info bases;
+ int complete = 0;
int show_progress = 0;
struct progress *progress = NULL;
struct oid_array idiff_prev = OID_ARRAY_INIT;
@@ -1622,6 +1623,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", &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")),
@@ -1905,6 +1908,15 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
prepare_bases(&bases, base, list, nr);
}

+ if (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;
+ rev.show_raw_buffer = 1;
+ }
+
if (in_reply_to || thread || cover_letter)
rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
if (in_reply_to) {
diff --git a/log-tree.c b/log-tree.c
index 923a299e70..2c9788b25a 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -774,6 +774,22 @@ void show_log(struct rev_info *opt)

memcpy(&diff_queued_diff, &dq, sizeof(diff_queued_diff));
}
+
+ if (opt->show_raw_buffer) {
+ 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);
+ }
}

int log_tree_diff_flush(struct rev_info *opt)
@@ -791,6 +807,7 @@ int log_tree_diff_flush(struct rev_info *opt)

if (opt->loginfo && !opt->no_commit_id) {
show_log(opt);
+
if ((opt->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT) &&
opt->verbose_header &&
opt->commit_format != CMIT_FMT_ONELINE &&
diff --git a/revision.h b/revision.h
index 4134dc6029..5297dc9f3c 100644
--- a/revision.h
+++ b/revision.h
@@ -190,7 +190,8 @@ struct rev_info {
use_terminator:1,
missing_newline:1,
date_mode_explicit:1,
- preserve_subject:1;
+ preserve_subject:1,
+ show_raw_buffer:1;
unsigned int disable_stdin:1;
/* --show-linear-break */
unsigned int track_linear:1,
--
2.23.0.718.g3120370db8


--------------8457B549DA2D505D3C75C377
Content-Type: text/x-patch;
name="0002-mailinfo-collect-commit-metadata-from-mail.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0002-mailinfo-collect-commit-metadata-from-mail.patch"