Browse Source

merge: make usage of commit->util more extensible

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>
maint
Junio C Hamano 13 years ago
parent
commit
ae8e4c9ce1
  1. 63
      builtin/merge.c
  2. 19
      commit.c
  3. 13
      commit.h
  4. 13
      merge-recursive.c

63
builtin/merge.c

@ -406,20 +406,10 @@ static void finish(struct commit *head_commit,
strbuf_release(&reflog_message); 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. */ /* Get the name for the merge commit's message. */
static void merge_name(const char *remote, struct strbuf *msg) 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]; unsigned char branch_head[20], buf_sha[20];
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
struct strbuf bname = STRBUF_INIT; struct strbuf bname = STRBUF_INIT;
@ -431,7 +421,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
remote = bname.buf; remote = bname.buf;


memset(branch_head, 0, sizeof(branch_head)); memset(branch_head, 0, sizeof(branch_head));
remote_head = want_commit(remote); remote_head = get_merge_parent(remote);
if (!remote_head) if (!remote_head)
die(_("'%s' does not point to a commit"), remote); 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)) { if (resolve_ref(truname.buf, buf_sha, 1, NULL)) {
strbuf_addf(msg, strbuf_addf(msg,
"%s\t\tbranch '%s'%s of .\n", "%s\t\tbranch '%s'%s of .\n",
sha1_to_hex(remote_head->sha1), sha1_to_hex(remote_head->object.sha1),
truname.buf + 11, truname.buf + 11,
(early ? " (early part)" : "")); (early ? " (early part)" : ""));
strbuf_release(&truname); strbuf_release(&truname);
@ -515,7 +505,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
goto cleanup; goto cleanup;
} }
strbuf_addf(msg, "%s\t\tcommit '%s'\n", strbuf_addf(msg, "%s\t\tcommit '%s'\n",
sha1_to_hex(remote_head->sha1), remote); sha1_to_hex(remote_head->object.sha1), remote);
cleanup: cleanup:
strbuf_release(&buf); strbuf_release(&buf);
strbuf_release(&bname); 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]); die(_("Unknown option for merge-recursive: -X%s"), xopts[x]);


o.branch1 = head_arg; o.branch1 = head_arg;
o.branch2 = remoteheads->item->util; o.branch2 = merge_remote_util(remoteheads->item)->name;


for (j = common; j; j = j->next) for (j = common; j; j = j->next)
commit_list_insert(j->item, &reversed); commit_list_insert(j->item, &reversed);
@ -1190,7 +1180,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
argv += 2; argv += 2;
argc -= 2; argc -= 2;
} else if (!head_commit) { } else if (!head_commit) {
struct object *remote_head; struct commit *remote_head;
/* /*
* If the merged head is a valid one there is no reason * If the merged head is a valid one there is no reason
* to forbid "git merge" into a branch yet to be born. * 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) if (!allow_fast_forward)
die(_("Non-fast-forward commit does not make sense into " die(_("Non-fast-forward commit does not make sense into "
"an empty head")); "an empty head"));
remote_head = want_commit(argv[0]); remote_head = get_merge_parent(argv[0]);
if (!remote_head) if (!remote_head)
die(_("%s - not something we can merge"), argv[0]); die(_("%s - not something we can merge"), argv[0]);
read_empty(remote_head->sha1, 0); read_empty(remote_head->object.sha1, 0);
update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0, update_ref("initial pull", "HEAD", remote_head->object.sha1,
DIE_ON_ERR); NULL, 0, DIE_ON_ERR);
return 0; return 0;
} else { } else {
struct strbuf merge_names = STRBUF_INIT; struct strbuf merge_names = STRBUF_INIT;
@ -1218,12 +1208,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
head_arg = "HEAD"; head_arg = "HEAD";


/* /*
* All the rest are the commits being merged; * All the rest are the commits being merged; prepare
* prepare the standard merge summary message to * the standard merge summary message to be appended
* be appended to the given message. If remote * to the given message.
* is invalid we will die later in the common
* codepath so we discard the error in this
* loop.
*/ */
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
merge_name(argv[i], &merge_names); merge_name(argv[i], &merge_names);
@ -1251,17 +1238,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
strbuf_reset(&buf); strbuf_reset(&buf);


for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
struct object *o; struct commit *commit = get_merge_parent(argv[i]);
struct commit *commit; if (!commit)

o = want_commit(argv[i]);
if (!o)
die(_("%s - not something we can merge"), argv[i]); 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; remotes = &commit_list_insert(commit, remotes)->next;

strbuf_addf(&buf, "GITHEAD_%s",
strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(o->sha1)); sha1_to_hex(commit->object.sha1));
setenv(buf.buf, argv[i], 1); setenv(buf.buf, argv[i], 1);
strbuf_reset(&buf); 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)) { !hashcmp(common->item->object.sha1, head_commit->object.sha1)) {
/* Again the most common case of merging one remote. */ /* Again the most common case of merging one remote. */
struct strbuf msg = STRBUF_INIT; struct strbuf msg = STRBUF_INIT;
struct object *o; struct commit *commit;
char hex[41]; char hex[41];


strcpy(hex, find_unique_abbrev(head_commit->object.sha1, DEFAULT_ABBREV)); 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) if (have_message)
strbuf_addstr(&msg, strbuf_addstr(&msg,
" (no commit created; -m option ignored)"); " (no commit created; -m option ignored)");
o = want_commit(sha1_to_hex(remoteheads->item->object.sha1)); commit = remoteheads->item;
if (!o) if (!commit)
return 1; 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; return 1;


finish(head_commit, o->sha1, msg.buf); finish(head_commit, commit->object.sha1, msg.buf);
drop_save(); drop_save();
return 0; return 0;
} else if (!remoteheads->next && common->next) } else if (!remoteheads->next && common->next)

19
commit.c

@ -894,3 +894,22 @@ int commit_tree(const char *msg, unsigned char *tree,
strbuf_release(&buffer); strbuf_release(&buffer);
return result; 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;
}

13
commit.h

@ -185,4 +185,17 @@ extern int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret, struct commit_list *parents, unsigned char *ret,
const char *author); 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 */ #endif /* COMMIT_H */

13
merge-recursive.c

@ -38,16 +38,15 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two,
return lookup_tree(shifted); 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) static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
{ {
struct commit *commit = xcalloc(1, sizeof(struct commit)); 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->tree = tree;
commit->util = (void*)comment; commit->util = desc;
/* avoid warnings */
commit->object.parsed = 1; commit->object.parsed = 1;
return commit; return commit;
} }
@ -184,7 +183,7 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)
for (i = o->call_depth; i--;) for (i = o->call_depth; i--;)
fputs(" ", stdout); fputs(" ", stdout);
if (commit->util) if (commit->util)
printf("virtual %s\n", (char *)commit->util); printf("virtual %s\n", merge_remote_util(commit)->name);
else { else {
printf("%s ", find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV)); printf("%s ", find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
if (parse_commit(commit) != 0) if (parse_commit(commit) != 0)

Loading…
Cancel
Save