builtin-fsck: reports missing parent commits
authorMartin Koegler <mkoegler@auto.tuwien.ac.at>
Mon, 25 Feb 2008 21:46:07 +0000 (22:46 +0100)
committerJunio C Hamano <gitster@pobox.com>
Tue, 26 Feb 2008 07:57:35 +0000 (23:57 -0800)
parse_commit ignores parent commits with certain errors
(eg. a non commit object is already loaded under the sha1 of
the parent). To make fsck reports such errors, it has to compare
the nummer of parent commits returned by parse commit with the
number of parent commits in the object or in the graft/shallow file.

Signed-off-by: Martin Koegler <mkoegler@auto.tuwien.ac.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-fsck.c
commit.c
commit.h

index 7321ab236b6925ef12f9e169b130eb53428d81a5..727310afc2327726dd87f5ad6438cd28c07810c9 100644 (file)
@@ -397,6 +397,8 @@ static int fsck_commit(struct commit *commit)
 {
        char *buffer = commit->buffer;
        unsigned char tree_sha1[20], sha1[20];
+       struct commit_graft *graft;
+       int parents = 0;
 
        if (verbose)
                fprintf(stderr, "Checking commit %s\n",
@@ -411,6 +413,28 @@ static int fsck_commit(struct commit *commit)
                if (get_sha1_hex(buffer+7, sha1) || buffer[47] != '\n')
                        return objerror(&commit->object, "invalid 'parent' line format - bad sha1");
                buffer += 48;
+               parents++;
+       }
+       graft = lookup_commit_graft(commit->object.sha1);
+       if (graft) {
+               struct commit_list *p = commit->parents;
+               parents = 0;
+               while (p) {
+                       p = p->next;
+                       parents++;
+               }
+               if (graft->nr_parent == -1 && !parents)
+                       ; /* shallow commit */
+               else if (graft->nr_parent != parents)
+                       return objerror(&commit->object, "graft objects missing");
+       } else {
+               struct commit_list *p = commit->parents;
+               while (p && parents) {
+                       p = p->next;
+                       parents--;
+               }
+               if (p || parents)
+                       return objerror(&commit->object, "parent objects missing");
        }
        if (memcmp(buffer, "author ", 7))
                return objerror(&commit->object, "invalid format - expected 'author' line");
index 6684c4e73113f50f046c6541af8f2142751dea5b..94d5b3d2618d335585084170ef6a3a8e67f34c62 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -193,7 +193,7 @@ static void prepare_commit_graft(void)
        commit_graft_prepared = 1;
 }
 
-static struct commit_graft *lookup_commit_graft(const unsigned char *sha1)
+struct commit_graft *lookup_commit_graft(const unsigned char *sha1)
 {
        int pos;
        prepare_commit_graft();
index 10e2b5d4cfdc7ac129ead711421ccc51d2667f02..3ad3dd9af17215e2fb12c215911a863be573d50f 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -101,6 +101,7 @@ struct commit_graft {
 struct commit_graft *read_graft_line(char *buf, int len);
 int register_commit_graft(struct commit_graft *, int);
 int read_graft_file(const char *graft_file);
+struct commit_graft *lookup_commit_graft(const unsigned char *sha1);
 
 extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);