Skip to content

Commit ae8e4c9

Browse files
committed
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 <[email protected]>
1 parent 895680f commit ae8e4c9

File tree

4 files changed

+61
-47
lines changed

4 files changed

+61
-47
lines changed

builtin/merge.c

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -406,20 +406,10 @@ static void finish(struct commit *head_commit,
406406
strbuf_release(&reflog_message);
407407
}
408408

409-
static struct object *want_commit(const char *name)
410-
{
411-
struct object *obj;
412-
unsigned char sha1[20];
413-
if (get_sha1(name, sha1))
414-
return NULL;
415-
obj = parse_object(sha1);
416-
return peel_to_type(name, 0, obj, OBJ_COMMIT);
417-
}
418-
419409
/* Get the name for the merge commit's message. */
420410
static void merge_name(const char *remote, struct strbuf *msg)
421411
{
422-
struct object *remote_head;
412+
struct commit *remote_head;
423413
unsigned char branch_head[20], buf_sha[20];
424414
struct strbuf buf = STRBUF_INIT;
425415
struct strbuf bname = STRBUF_INIT;
@@ -431,7 +421,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
431421
remote = bname.buf;
432422

433423
memset(branch_head, 0, sizeof(branch_head));
434-
remote_head = want_commit(remote);
424+
remote_head = get_merge_parent(remote);
435425
if (!remote_head)
436426
die(_("'%s' does not point to a commit"), remote);
437427

@@ -487,7 +477,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
487477
if (resolve_ref(truname.buf, buf_sha, 1, NULL)) {
488478
strbuf_addf(msg,
489479
"%s\t\tbranch '%s'%s of .\n",
490-
sha1_to_hex(remote_head->sha1),
480+
sha1_to_hex(remote_head->object.sha1),
491481
truname.buf + 11,
492482
(early ? " (early part)" : ""));
493483
strbuf_release(&truname);
@@ -515,7 +505,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
515505
goto cleanup;
516506
}
517507
strbuf_addf(msg, "%s\t\tcommit '%s'\n",
518-
sha1_to_hex(remote_head->sha1), remote);
508+
sha1_to_hex(remote_head->object.sha1), remote);
519509
cleanup:
520510
strbuf_release(&buf);
521511
strbuf_release(&bname);
@@ -719,7 +709,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
719709
die(_("Unknown option for merge-recursive: -X%s"), xopts[x]);
720710

721711
o.branch1 = head_arg;
722-
o.branch2 = remoteheads->item->util;
712+
o.branch2 = merge_remote_util(remoteheads->item)->name;
723713

724714
for (j = common; j; j = j->next)
725715
commit_list_insert(j->item, &reversed);
@@ -1190,7 +1180,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
11901180
argv += 2;
11911181
argc -= 2;
11921182
} else if (!head_commit) {
1193-
struct object *remote_head;
1183+
struct commit *remote_head;
11941184
/*
11951185
* If the merged head is a valid one there is no reason
11961186
* 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)
12041194
if (!allow_fast_forward)
12051195
die(_("Non-fast-forward commit does not make sense into "
12061196
"an empty head"));
1207-
remote_head = want_commit(argv[0]);
1197+
remote_head = get_merge_parent(argv[0]);
12081198
if (!remote_head)
12091199
die(_("%s - not something we can merge"), argv[0]);
1210-
read_empty(remote_head->sha1, 0);
1211-
update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0,
1212-
DIE_ON_ERR);
1200+
read_empty(remote_head->object.sha1, 0);
1201+
update_ref("initial pull", "HEAD", remote_head->object.sha1,
1202+
NULL, 0, DIE_ON_ERR);
12131203
return 0;
12141204
} else {
12151205
struct strbuf merge_names = STRBUF_INIT;
@@ -1218,12 +1208,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
12181208
head_arg = "HEAD";
12191209

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

12531240
for (i = 0; i < argc; i++) {
1254-
struct object *o;
1255-
struct commit *commit;
1256-
1257-
o = want_commit(argv[i]);
1258-
if (!o)
1241+
struct commit *commit = get_merge_parent(argv[i]);
1242+
if (!commit)
12591243
die(_("%s - not something we can merge"), argv[i]);
1260-
commit = lookup_commit(o->sha1);
1261-
commit->util = (void *)argv[i];
12621244
remotes = &commit_list_insert(commit, remotes)->next;
1263-
1264-
strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
1245+
strbuf_addf(&buf, "GITHEAD_%s",
1246+
sha1_to_hex(commit->object.sha1));
12651247
setenv(buf.buf, argv[i], 1);
12661248
strbuf_reset(&buf);
12671249
}
@@ -1307,7 +1289,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
13071289
!hashcmp(common->item->object.sha1, head_commit->object.sha1)) {
13081290
/* Again the most common case of merging one remote. */
13091291
struct strbuf msg = STRBUF_INIT;
1310-
struct object *o;
1292+
struct commit *commit;
13111293
char hex[41];
13121294

13131295
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)
13211303
if (have_message)
13221304
strbuf_addstr(&msg,
13231305
" (no commit created; -m option ignored)");
1324-
o = want_commit(sha1_to_hex(remoteheads->item->object.sha1));
1325-
if (!o)
1306+
commit = remoteheads->item;
1307+
if (!commit)
13261308
return 1;
13271309

1328-
if (checkout_fast_forward(head_commit->object.sha1, remoteheads->item->object.sha1))
1310+
if (checkout_fast_forward(head_commit->object.sha1,
1311+
commit->object.sha1))
13291312
return 1;
13301313

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

commit.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,3 +894,22 @@ int commit_tree(const char *msg, unsigned char *tree,
894894
strbuf_release(&buffer);
895895
return result;
896896
}
897+
898+
struct commit *get_merge_parent(const char *name)
899+
{
900+
struct object *obj;
901+
struct commit *commit;
902+
unsigned char sha1[20];
903+
if (get_sha1(name, sha1))
904+
return NULL;
905+
obj = parse_object(sha1);
906+
commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
907+
if (commit && !commit->util) {
908+
struct merge_remote_desc *desc;
909+
desc = xmalloc(sizeof(*desc));
910+
desc->obj = obj;
911+
desc->name = strdup(name);
912+
commit->util = desc;
913+
}
914+
return commit;
915+
}

commit.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,17 @@ extern int commit_tree(const char *msg, unsigned char *tree,
185185
struct commit_list *parents, unsigned char *ret,
186186
const char *author);
187187

188+
struct merge_remote_desc {
189+
struct object *obj; /* the named object, could be a tag */
190+
const char *name;
191+
};
192+
#define merge_remote_util(commit) ((struct merge_remote_desc *)((commit)->util))
193+
194+
/*
195+
* Given "name" from the command line to merge, find the commit object
196+
* and return it, while storing merge_remote_desc in its ->util field,
197+
* to allow callers to tell if we are told to merge a tag.
198+
*/
199+
struct commit *get_merge_parent(const char *name);
200+
188201
#endif /* COMMIT_H */

merge-recursive.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,15 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two,
3838
return lookup_tree(shifted);
3939
}
4040

41-
/*
42-
* A virtual commit has (const char *)commit->util set to the name.
43-
*/
44-
4541
static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
4642
{
4743
struct commit *commit = xcalloc(1, sizeof(struct commit));
44+
struct merge_remote_desc *desc = xmalloc(sizeof(*desc));
45+
46+
desc->name = comment;
47+
desc->obj = (struct object *)commit;
4848
commit->tree = tree;
49-
commit->util = (void*)comment;
50-
/* avoid warnings */
49+
commit->util = desc;
5150
commit->object.parsed = 1;
5251
return commit;
5352
}
@@ -184,7 +183,7 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)
184183
for (i = o->call_depth; i--;)
185184
fputs(" ", stdout);
186185
if (commit->util)
187-
printf("virtual %s\n", (char *)commit->util);
186+
printf("virtual %s\n", merge_remote_util(commit)->name);
188187
else {
189188
printf("%s ", find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
190189
if (parse_commit(commit) != 0)

0 commit comments

Comments
 (0)