git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH v3 09/17] merge: make usage of commit->util more extensible
Date: Tue,  8 Nov 2011 17:01:55 -0800	[thread overview]
Message-ID: <1320800523-5407-10-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1320800523-5407-1-git-send-email-gitster@pobox.com>

The merge-recursive code uses the commit->util field directly to annotate
the commit objects given from the command line, i.e. the remote heads to
be merged, with a single string to be used to describe it in its trace
messages and conflict markers.

Correct this short-signtedness by redefining the field to be a pointer to
a structure "struct merge_remote_desc" that later enhancements can add
more information. Store the original objects we were told to merge in a
field "obj" in this struct, so that we can recover the tag we were told to
merge.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/merge.c   |   63 +++++++++++++++++++---------------------------------
 commit.c          |   19 ++++++++++++++++
 commit.h          |   13 +++++++++++
 merge-recursive.c |   13 +++++------
 4 files changed, 61 insertions(+), 47 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 48e7f00..8d4eb4e 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -406,20 +406,10 @@ static void finish(struct commit *head_commit,
 	strbuf_release(&reflog_message);
 }
 
-static struct object *want_commit(const char *name)
-{
-	struct object *obj;
-	unsigned char sha1[20];
-	if (get_sha1(name, sha1))
-		return NULL;
-	obj = parse_object(sha1);
-	return peel_to_type(name, 0, obj, OBJ_COMMIT);
-}
-
 /* Get the name for the merge commit's message. */
 static void merge_name(const char *remote, struct strbuf *msg)
 {
-	struct object *remote_head;
+	struct commit *remote_head;
 	unsigned char branch_head[20], buf_sha[20];
 	struct strbuf buf = STRBUF_INIT;
 	struct strbuf bname = STRBUF_INIT;
@@ -431,7 +421,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
 	remote = bname.buf;
 
 	memset(branch_head, 0, sizeof(branch_head));
-	remote_head = want_commit(remote);
+	remote_head = get_merge_parent(remote);
 	if (!remote_head)
 		die(_("'%s' does not point to a commit"), remote);
 
@@ -487,7 +477,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
 		if (resolve_ref(truname.buf, buf_sha, 1, NULL)) {
 			strbuf_addf(msg,
 				    "%s\t\tbranch '%s'%s of .\n",
-				    sha1_to_hex(remote_head->sha1),
+				    sha1_to_hex(remote_head->object.sha1),
 				    truname.buf + 11,
 				    (early ? " (early part)" : ""));
 			strbuf_release(&truname);
@@ -515,7 +505,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
 		goto cleanup;
 	}
 	strbuf_addf(msg, "%s\t\tcommit '%s'\n",
-		sha1_to_hex(remote_head->sha1), remote);
+		sha1_to_hex(remote_head->object.sha1), remote);
 cleanup:
 	strbuf_release(&buf);
 	strbuf_release(&bname);
@@ -719,7 +709,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
 				die(_("Unknown option for merge-recursive: -X%s"), xopts[x]);
 
 		o.branch1 = head_arg;
-		o.branch2 = remoteheads->item->util;
+		o.branch2 = merge_remote_util(remoteheads->item)->name;
 
 		for (j = common; j; j = j->next)
 			commit_list_insert(j->item, &reversed);
@@ -1190,7 +1180,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		argv += 2;
 		argc -= 2;
 	} else if (!head_commit) {
-		struct object *remote_head;
+		struct commit *remote_head;
 		/*
 		 * If the merged head is a valid one there is no reason
 		 * to forbid "git merge" into a branch yet to be born.
@@ -1204,12 +1194,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		if (!allow_fast_forward)
 			die(_("Non-fast-forward commit does not make sense into "
 			    "an empty head"));
-		remote_head = want_commit(argv[0]);
+		remote_head = get_merge_parent(argv[0]);
 		if (!remote_head)
 			die(_("%s - not something we can merge"), argv[0]);
-		read_empty(remote_head->sha1, 0);
-		update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0,
-				DIE_ON_ERR);
+		read_empty(remote_head->object.sha1, 0);
+		update_ref("initial pull", "HEAD", remote_head->object.sha1,
+			   NULL, 0, DIE_ON_ERR);
 		return 0;
 	} else {
 		struct strbuf merge_names = STRBUF_INIT;
@@ -1218,12 +1208,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		head_arg = "HEAD";
 
 		/*
-		 * All the rest are the commits being merged;
-		 * prepare the standard merge summary message to
-		 * be appended to the given message.  If remote
-		 * is invalid we will die later in the common
-		 * codepath so we discard the error in this
-		 * loop.
+		 * All the rest are the commits being merged; prepare
+		 * the standard merge summary message to be appended
+		 * to the given message.
 		 */
 		for (i = 0; i < argc; i++)
 			merge_name(argv[i], &merge_names);
@@ -1251,17 +1238,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	strbuf_reset(&buf);
 
 	for (i = 0; i < argc; i++) {
-		struct object *o;
-		struct commit *commit;
-
-		o = want_commit(argv[i]);
-		if (!o)
+		struct commit *commit = get_merge_parent(argv[i]);
+		if (!commit)
 			die(_("%s - not something we can merge"), argv[i]);
-		commit = lookup_commit(o->sha1);
-		commit->util = (void *)argv[i];
 		remotes = &commit_list_insert(commit, remotes)->next;
-
-		strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
+		strbuf_addf(&buf, "GITHEAD_%s",
+			    sha1_to_hex(commit->object.sha1));
 		setenv(buf.buf, argv[i], 1);
 		strbuf_reset(&buf);
 	}
@@ -1307,7 +1289,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			!hashcmp(common->item->object.sha1, head_commit->object.sha1)) {
 		/* Again the most common case of merging one remote. */
 		struct strbuf msg = STRBUF_INIT;
-		struct object *o;
+		struct commit *commit;
 		char hex[41];
 
 		strcpy(hex, find_unique_abbrev(head_commit->object.sha1, DEFAULT_ABBREV));
@@ -1321,14 +1303,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		if (have_message)
 			strbuf_addstr(&msg,
 				" (no commit created; -m option ignored)");
-		o = want_commit(sha1_to_hex(remoteheads->item->object.sha1));
-		if (!o)
+		commit = remoteheads->item;
+		if (!commit)
 			return 1;
 
-		if (checkout_fast_forward(head_commit->object.sha1, remoteheads->item->object.sha1))
+		if (checkout_fast_forward(head_commit->object.sha1,
+					  commit->object.sha1))
 			return 1;
 
-		finish(head_commit, o->sha1, msg.buf);
+		finish(head_commit, commit->object.sha1, msg.buf);
 		drop_save();
 		return 0;
 	} else if (!remoteheads->next && common->next)
diff --git a/commit.c b/commit.c
index 73b7e00..83ff503 100644
--- a/commit.c
+++ b/commit.c
@@ -894,3 +894,22 @@ int commit_tree(const char *msg, unsigned char *tree,
 	strbuf_release(&buffer);
 	return result;
 }
+
+struct commit *get_merge_parent(const char *name)
+{
+	struct object *obj;
+	struct commit *commit;
+	unsigned char sha1[20];
+	if (get_sha1(name, sha1))
+		return NULL;
+	obj = parse_object(sha1);
+	commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
+	if (commit && !commit->util) {
+		struct merge_remote_desc *desc;
+		desc = xmalloc(sizeof(*desc));
+		desc->obj = obj;
+		desc->name = strdup(name);
+		commit->util = desc;
+	}
+	return commit;
+}
diff --git a/commit.h b/commit.h
index 009b113..5b57eab 100644
--- a/commit.h
+++ b/commit.h
@@ -185,4 +185,17 @@ extern int commit_tree(const char *msg, unsigned char *tree,
 		struct commit_list *parents, unsigned char *ret,
 		const char *author);
 
+struct merge_remote_desc {
+	struct object *obj; /* the named object, could be a tag */
+	const char *name;
+};
+#define merge_remote_util(commit) ((struct merge_remote_desc *)((commit)->util))
+
+/*
+ * Given "name" from the command line to merge, find the commit object
+ * and return it, while storing merge_remote_desc in its ->util field,
+ * to allow callers to tell if we are told to merge a tag.
+ */
+struct commit *get_merge_parent(const char *name);
+
 #endif /* COMMIT_H */
diff --git a/merge-recursive.c b/merge-recursive.c
index cc664c3..5a2db29 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -38,16 +38,15 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two,
 	return lookup_tree(shifted);
 }
 
-/*
- * A virtual commit has (const char *)commit->util set to the name.
- */
-
 static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
 {
 	struct commit *commit = xcalloc(1, sizeof(struct commit));
+	struct merge_remote_desc *desc = xmalloc(sizeof(*desc));
+
+	desc->name = comment;
+	desc->obj = (struct object *)commit;
 	commit->tree = tree;
-	commit->util = (void*)comment;
-	/* avoid warnings */
+	commit->util = desc;
 	commit->object.parsed = 1;
 	return commit;
 }
@@ -184,7 +183,7 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)
 	for (i = o->call_depth; i--;)
 		fputs("  ", stdout);
 	if (commit->util)
-		printf("virtual %s\n", (char *)commit->util);
+		printf("virtual %s\n", merge_remote_util(commit)->name);
 	else {
 		printf("%s ", find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
 		if (parse_commit(commit) != 0)
-- 
1.7.8.rc1.82.g90e080

  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 ` Junio C Hamano [this message]
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 ` [PATCH v3 11/17] commit: copy merged signed tags to headers of merge commit Junio C Hamano
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-10-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).