Accept tags in HEAD or MERGE_HEAD

HEAD and MERGE_HEAD (among other branch tips) should never hold a tag. That can only be caused by broken tools and is cumbersome to fix by an end user with: $ git update-ref HEAD $(git rev-parse HEAD^{commit}) which may look like a magic to a new person. Be easy, warn users (so broken tools can be fixed if they bother to report) and move on. Be robust, if the given SHA-1 cannot be resolved to a commit object, die (therefore return value is always valid). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Sep 17, 2011 at 21:57 UTC baf18fc261ca475343fe3cb9cd2c0dded4bc1bb7
7 files changed +34 -14
builtin/commit.c
+4 -2
@@ -1396,7 +1396,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
1396 if (get_sha1("HEAD", sha1))
1397 current_head = NULL;
1398 else {
1399 - current_head = lookup_commit(sha1);
1399 + current_head = lookup_commit_or_die(sha1, "HEAD");
1400 if (!current_head || parse_commit(current_head))
1401 die(_("could not parse HEAD commit"));
1402 }
@@ -1431,6 +1431,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
1431 pptr = &commit_list_insert(c->item, pptr)->next;
1432 } else if (whence == FROM_MERGE) {
1433 struct strbuf m = STRBUF_INIT;
1434 + struct commit *commit;
1435 FILE *fp;
1436
1437 if (!reflog_msg)
@@ -1444,7 +1445,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
1445 unsigned char sha1[20];
1446 if (get_sha1_hex(m.buf, sha1) < 0)
1447 die(_("Corrupt MERGE_HEAD file (%s)"), m.buf);
1447 - pptr = &commit_list_insert(lookup_commit(sha1), pptr)->next;
1448 + commit = lookup_commit_or_die(sha1, "MERGE_HEAD");
1449 + pptr = &commit_list_insert(commit, pptr)->next;
1450 }
1451 fclose(fp);
1452 strbuf_release(&m);
builtin/fmt-merge-msg.c
+1 -1
@@ -293,7 +293,7 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,
293 struct commit *head;
294 struct rev_info rev;
295
296 - head = lookup_commit(head_sha1);
296 + head = lookup_commit_or_die(head_sha1, "HEAD");
297 init_revisions(&rev, NULL);
298 rev.commit_format = CMIT_FMT_ONELINE;
299 rev.ignore_merges = 1;
builtin/merge.c
+2 -5
@@ -1036,11 +1036,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1036 branch += 11;
1037 if (!branch || is_null_sha1(head_sha1))
1038 head_commit = NULL;
1039 - else {
1040 - head_commit = lookup_commit(head_sha1);
1041 - if (!head_commit)
1042 - die(_("could not parse HEAD"));
1043 - }
1039 + else
1040 + head_commit = lookup_commit_or_die(head_sha1, "HEAD");
1041
1042 git_config(git_merge_config, NULL);
1043
commit.c
+12
@@ -39,6 +39,18 @@ struct commit *lookup_commit_reference(const unsigned char *sha1)
39 return lookup_commit_reference_gently(sha1, 0);
40 }
41
42 +struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name)
43 +{
44 + struct commit *c = lookup_commit_reference(sha1);
45 + if (!c)
46 + die(_("could not parse %s"), ref_name);
47 + if (hashcmp(sha1, c->object.sha1)) {
48 + warning(_("%s %s is not a commit!"),
49 + ref_name, sha1_to_hex(sha1));
50 + }
51 + return c;
52 +}
53 +
54 struct commit *lookup_commit(const unsigned char *sha1)
55 {
56 struct object *obj = lookup_object(sha1);
commit.h
+7
@@ -38,6 +38,13 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
38 int quiet);
39 struct commit *lookup_commit_reference_by_name(const char *name);
40
41 +/*
42 + * Look up object named by "sha1", dereference tag as necessary,
43 + * get a commit and return it. If "sha1" does not dereference to
44 + * a commit, use ref_name to report an error and die.
45 + */
46 +struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name);
47 +
48 int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
49 int parse_commit(struct commit *item);
50
http-push.c
+4 -4
@@ -1606,10 +1606,10 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
1606 strbuf_release(&buffer);
1607 }
1608
1609 -static int verify_merge_base(unsigned char *head_sha1, unsigned char *branch_sha1)
1609 +static int verify_merge_base(unsigned char *head_sha1, struct ref *remote)
1610 {
1611 - struct commit *head = lookup_commit(head_sha1);
1612 - struct commit *branch = lookup_commit(branch_sha1);
1611 + struct commit *head = lookup_commit_or_die(head_sha1, "HEAD");
1612 + struct commit *branch = lookup_commit_or_die(remote->old_sha1, remote->name);
1613 struct commit_list *merge_bases = get_merge_bases(head, branch, 1);
1614
1615 return (merge_bases && !merge_bases->next && merge_bases->item == branch);
@@ -1680,7 +1680,7 @@ static int delete_remote_branch(const char *pattern, int force)
1680 return error("Remote branch %s resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", remote_ref->name, sha1_to_hex(remote_ref->old_sha1));
1681
1682 /* Remote branch must be an ancestor of remote HEAD */
1683 - if (!verify_merge_base(head_sha1, remote_ref->old_sha1)) {
1683 + if (!verify_merge_base(head_sha1, remote_ref)) {
1684 return error("The branch '%s' is not an ancestor "
1685 "of your current HEAD.\n"
1686 "If you are sure you want to delete it,"
revision.c
+4 -2
@@ -986,10 +986,12 @@ static void prepare_show_merge(struct rev_info *revs)
986 const char **prune = NULL;
987 int i, prune_num = 1; /* counting terminating NULL */
988
989 - if (get_sha1("HEAD", sha1) || !(head = lookup_commit(sha1)))
989 + if (get_sha1("HEAD", sha1))
990 die("--merge without HEAD?");
991 - if (get_sha1("MERGE_HEAD", sha1) || !(other = lookup_commit(sha1)))
991 + head = lookup_commit_or_die(sha1, "HEAD");
992 + if (get_sha1("MERGE_HEAD", sha1))
993 die("--merge without MERGE_HEAD?");
994 + other = lookup_commit_or_die(sha1, "MERGE_HEAD");
995 add_pending_object(revs, &head->object, "HEAD");
996 add_pending_object(revs, &other->object, "MERGE_HEAD");
997 bases = get_merge_bases(head, other, 1);