From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH v3 11/17] commit: copy merged signed tags to headers of merge commit
Date: Tue, 8 Nov 2011 17:01:57 -0800 [thread overview]
Message-ID: <1320800523-5407-12-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1320800523-5407-1-git-send-email-gitster@pobox.com>
Now MERGE_HEAD records the tag objects without peeling, we could record
the result of manual conflict resolution via "git commit" without losing
the tag information. Introduce a new "mergetag" multi-line header field to
the commit object, and use it to store the entire contents of each signed
tag merged.
A commit header that has a multi-line payload begins with the header tag
(e.g. "mergetag" in this case), SP, the first line of payload, LF, and all
the remaining lines have a SP inserted at the beginning.
In hindsight, it would have been better to make "merge --continue" as the
way to continue from such an interrupted merge, not "commit", but this is
a backward compatibility baggage we would need to carry around for now.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/commit.c | 10 +++---
commit.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++--
commit.h | 21 +++++++++++-
3 files changed, 115 insertions(+), 11 deletions(-)
diff --git a/builtin/commit.c b/builtin/commit.c
index c46f2d1..4688a73 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1425,7 +1425,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
pptr = &commit_list_insert(c->item, pptr)->next;
} else if (whence == FROM_MERGE) {
struct strbuf m = STRBUF_INIT;
- struct commit *commit;
FILE *fp;
if (!reflog_msg)
@@ -1436,11 +1435,12 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
die_errno(_("could not open '%s' for reading"),
git_path("MERGE_HEAD"));
while (strbuf_getline(&m, fp, '\n') != EOF) {
- unsigned char sha1[20];
- if (get_sha1_hex(m.buf, sha1) < 0)
+ struct commit *parent;
+
+ parent = get_merge_parent(m.buf);
+ if (!parent)
die(_("Corrupt MERGE_HEAD file (%s)"), m.buf);
- commit = lookup_commit_or_die(sha1, "MERGE_HEAD");
- pptr = &commit_list_insert(commit, pptr)->next;
+ pptr = &commit_list_insert(parent, pptr)->next;
}
fclose(fp);
strbuf_release(&m);
diff --git a/commit.c b/commit.c
index 83ff503..ee12eff 100644
--- a/commit.c
+++ b/commit.c
@@ -840,14 +840,94 @@ struct commit_list *reduce_heads(struct commit_list *heads)
return result;
}
+static void handle_signed_tag(struct commit *parent, struct commit_extra_header ***tail)
+{
+ struct merge_remote_desc *desc;
+ struct commit_extra_header *mergetag;
+ char *buf;
+ unsigned long size, len;
+ enum object_type type;
+
+ desc = merge_remote_util(parent);
+ if (!desc || !desc->obj)
+ return;
+ buf = read_sha1_file(desc->obj->sha1, &type, &size);
+ if (!buf || type != OBJ_TAG)
+ goto free_return;
+ len = parse_signature(buf, size);
+ if (size == len)
+ goto free_return;
+ /*
+ * We could verify this signature and either omit the tag when
+ * it does not validate, but the integrator may not have the
+ * public key of the signer of the tag he is merging, while a
+ * later auditor may have it while auditing, so let's not run
+ * verify-signed-buffer here for now...
+ *
+ * if (verify_signed_buffer(buf, len, buf + len, size - len, ...))
+ * warn("warning: signed tag unverified.");
+ */
+ mergetag = xcalloc(1, sizeof(*mergetag));
+ mergetag->key = "mergetag";
+ mergetag->value = buf;
+ mergetag->len = size;
+
+ **tail = mergetag;
+ *tail = &mergetag->next;
+ return;
+
+free_return:
+ free(buf);
+}
+
+void append_merge_tag_headers(struct commit_list *parents,
+ struct commit_extra_header ***tail)
+{
+ while (parents) {
+ struct commit *parent = parents->item;
+ handle_signed_tag(parent, tail);
+ parents = parents->next;
+ }
+}
+
+static void add_extra_header(struct strbuf *buffer,
+ struct commit_extra_header *extra)
+{
+ strbuf_addstr(buffer, extra->key);
+ strbuf_add_lines(buffer, " ", extra->value, extra->len);
+}
+
+void free_commit_extra_headers(struct commit_extra_header *extra)
+{
+ while (extra) {
+ struct commit_extra_header *next = extra->next;
+ free(extra->value);
+ free(extra);
+ extra = next;
+ }
+}
+
+int commit_tree(const char *msg, unsigned char *tree,
+ struct commit_list *parents, unsigned char *ret,
+ const char *author)
+{
+ struct commit_extra_header *extra = NULL, **tail = &extra;
+ int result;
+
+ append_merge_tag_headers(parents, &tail);
+ result = commit_tree_extended(msg, tree, parents, ret, author, extra);
+ free_commit_extra_headers(extra);
+ return result;
+}
+
static const char commit_utf8_warn[] =
"Warning: commit message does not conform to UTF-8.\n"
"You may want to amend it after fixing the message, or set the config\n"
"variable i18n.commitencoding to the encoding your project uses.\n";
-int commit_tree(const char *msg, unsigned char *tree,
- struct commit_list *parents, unsigned char *ret,
- const char *author)
+int commit_tree_extended(const char *msg, unsigned char *tree,
+ struct commit_list *parents, unsigned char *ret,
+ const char *author, struct commit_extra_header *extra)
{
int result;
int encoding_is_utf8;
@@ -868,8 +948,10 @@ int commit_tree(const char *msg, unsigned char *tree,
*/
while (parents) {
struct commit_list *next = parents->next;
+ struct commit *parent = parents->item;
+
strbuf_addf(&buffer, "parent %s\n",
- sha1_to_hex(parents->item->object.sha1));
+ sha1_to_hex(parent->object.sha1));
free(parents);
parents = next;
}
@@ -881,6 +963,11 @@ int commit_tree(const char *msg, unsigned char *tree,
strbuf_addf(&buffer, "committer %s\n", git_committer_info(IDENT_ERROR_ON_NO_NAME));
if (!encoding_is_utf8)
strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding);
+
+ while (extra) {
+ add_extra_header(&buffer, extra);
+ extra = extra->next;
+ }
strbuf_addch(&buffer, '\n');
/* And add the comment */
diff --git a/commit.h b/commit.h
index 5b57eab..c1a723e 100644
--- a/commit.h
+++ b/commit.h
@@ -181,9 +181,26 @@ static inline int single_parent(struct commit *commit)
struct commit_list *reduce_heads(struct commit_list *heads);
+struct commit_extra_header {
+ struct commit_extra_header *next;
+ char *key;
+ char *value;
+ size_t len;
+};
+
+extern void append_merge_tag_headers(struct commit_list *parents,
+ struct commit_extra_header ***tail);
+
extern int commit_tree(const char *msg, unsigned char *tree,
- struct commit_list *parents, unsigned char *ret,
- const char *author);
+ struct commit_list *parents, unsigned char *ret,
+ const char *author);
+
+extern int commit_tree_extended(const char *msg, unsigned char *tree,
+ struct commit_list *parents, unsigned char *ret,
+ const char *author,
+ struct commit_extra_header *);
+
+extern void free_commit_extra_headers(struct commit_extra_header *extra);
struct merge_remote_desc {
struct object *obj; /* the named object, could be a tag */
--
1.7.8.rc1.82.g90e080
next prev parent reply other threads:[~2011-11-09 1:02 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-11-09 1:01 [PATCH v3 00/17] Pulling signed tags Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 01/17] Split GPG interface into its own helper library Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 02/17] fetch: do not store peeled tag object names in FETCH_HEAD Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 03/17] merge: notice local merging of tags and keep it unwrapped Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 04/17] fetch: allow "git fetch $there v1.0" to fetch a tag Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 05/17] refs DWIMmery: use the same rule for both "git fetch" and others Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 06/17] fmt-merge-msg: avoid early returns Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 07/17] fmt-merge-msg: package options into a structure Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 08/17] fmt-merge-msg: Add contents of merged tag in the merge message Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 09/17] merge: make usage of commit->util more extensible Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 10/17] merge: record tag objects without peeling in MERGE_HEAD Junio C Hamano
2011-11-09 1:01 ` Junio C Hamano [this message]
2011-11-09 1:01 ` [PATCH v3 12/17] merge: force edit mode when merging a tag object Junio C Hamano
2011-11-09 1:01 ` [PATCH v3 13/17] commit: teach --amend to carry forward extra headers Junio C Hamano
2011-11-09 1:02 ` [PATCH v3 14/17] commit: teach --gpg-sign option Junio C Hamano
2011-11-09 1:02 ` [PATCH v3 15/17] log: --show-signature Junio C Hamano
2011-11-09 1:02 ` [PATCH v3 16/17] test "commit -S" and "log --show-signature" Junio C Hamano
2011-11-09 1:02 ` [PATCH v3 17/17] pretty: %G[?GS] placeholders Junio C Hamano
2011-11-09 10:32 ` [PATCH v3 00/17] Pulling signed tags Robin H. Johnson
2011-11-09 13:20 ` [PATCH 18/17] request-pull: use the annotated tag contents Junio C Hamano
2011-11-09 13:39 ` [PATCH 19/17] merge: do not fast-forward when merging a tag Junio C Hamano
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=1320800523-5407-12-git-send-email-gitster@pobox.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).