Make the revision tracking track the object types too.

This allows fsck to verify not just that an object exists, but
also that it has the type it was expected to have.
This commit is contained in:
Linus Torvalds 2005-04-17 16:19:32 -07:00
Родитель d0d7cbe730
Коммит 08ca0b04ba
3 изменённых файлов: 29 добавлений и 23 удалений

Просмотреть файл

@ -17,33 +17,33 @@ static void check_connectivity(void)
struct revision *rev = revs[i]; struct revision *rev = revs[i];
if (show_unreachable && !(rev->flags & REACHABLE)) { if (show_unreachable && !(rev->flags & REACHABLE)) {
printf("unreachable %s\n", sha1_to_hex(rev->sha1)); printf("unreachable %s %s\n", rev->tag, sha1_to_hex(rev->sha1));
continue; continue;
} }
switch (rev->flags & (SEEN | USED)) { switch (rev->flags & (SEEN | USED)) {
case 0: case 0:
printf("bad %s\n", sha1_to_hex(rev->sha1)); printf("bad %s %s\n", rev->tag, sha1_to_hex(rev->sha1));
break; break;
case USED: case USED:
printf("missing %s\n", sha1_to_hex(rev->sha1)); printf("missing %s, %s\n", rev->tag, sha1_to_hex(rev->sha1));
break; break;
case SEEN: case SEEN:
printf("dangling %s\n", sha1_to_hex(rev->sha1)); printf("dangling %s %s\n", rev->tag, sha1_to_hex(rev->sha1));
break; break;
} }
} }
} }
static void mark_needs_sha1(unsigned char *parent, const char * tag, unsigned char *child) static void mark_needs_sha1(unsigned char *parent, const char *ptag, unsigned char *child, const char *ctag)
{ {
struct revision * child_rev = add_relationship(lookup_rev(parent), child); struct revision * child_rev = add_relationship(lookup_rev(parent, ptag), child, ctag);
child_rev->flags |= USED; child_rev->flags |= USED;
} }
static int mark_sha1_seen(unsigned char *sha1, char *tag) static int mark_sha1_seen(unsigned char *sha1, const char *tag)
{ {
struct revision *rev = lookup_rev(sha1); struct revision *rev = lookup_rev(sha1, tag);
rev->flags |= SEEN; rev->flags |= SEEN;
return 0; return 0;
@ -69,7 +69,7 @@ static int fsck_tree(unsigned char *sha1, void *data, unsigned long size)
data += len + 20; data += len + 20;
size -= len + 20; size -= len + 20;
mark_needs_sha1(sha1, S_ISDIR(mode) ? "tree" : "blob", file_sha1); mark_needs_sha1(sha1, "tree", file_sha1, S_ISDIR(mode) ? "tree" : "blob");
} }
return 0; return 0;
} }
@ -84,13 +84,13 @@ static int fsck_commit(unsigned char *sha1, void *data, unsigned long size)
return -1; return -1;
if (get_sha1_hex(data + 5, tree_sha1) < 0) if (get_sha1_hex(data + 5, tree_sha1) < 0)
return -1; return -1;
mark_needs_sha1(sha1, "tree", tree_sha1); mark_needs_sha1(sha1, "commit", tree_sha1, "tree");
data += 5 + 40 + 1; /* "tree " + <hex sha1> + '\n' */ data += 5 + 40 + 1; /* "tree " + <hex sha1> + '\n' */
parents = 0; parents = 0;
while (!memcmp(data, "parent ", 7)) { while (!memcmp(data, "parent ", 7)) {
if (get_sha1_hex(data + 7, parent_sha1) < 0) if (get_sha1_hex(data + 7, parent_sha1) < 0)
return -1; return -1;
mark_needs_sha1(sha1, "commit", parent_sha1); mark_needs_sha1(sha1, "commit", parent_sha1, "commit");
data += 7 + 40 + 1; /* "parent " + <hex sha1> + '\n' */ data += 7 + 40 + 1; /* "parent " + <hex sha1> + '\n' */
parents++; parents++;
} }
@ -186,7 +186,7 @@ int main(int argc, char **argv)
continue; continue;
} }
if (!get_sha1_hex(argv[i], head_sha1)) { if (!get_sha1_hex(argv[i], head_sha1)) {
mark_reachable(lookup_rev(head_sha1), REACHABLE); mark_reachable(lookup_rev(head_sha1, "commit"), REACHABLE);
heads++; heads++;
continue; continue;
} }

Просмотреть файл

@ -37,7 +37,7 @@ static void read_cache_file(const char *path)
break; break;
if (get_sha1_hex(buf+1, sha1)) if (get_sha1_hex(buf+1, sha1))
break; break;
rev = lookup_rev(sha1); rev = lookup_rev(sha1, "commit");
rev->flags |= SEEN; rev->flags |= SEEN;
rev->date = date; rev->date = date;
@ -46,7 +46,7 @@ static void read_cache_file(const char *path)
unsigned char parent[20]; unsigned char parent[20];
if (get_sha1_hex(buf + 1, parent)) if (get_sha1_hex(buf + 1, parent))
break; break;
add_relationship(rev, parent); add_relationship(rev, parent, "commit");
} }
} }
fclose(file); fclose(file);
@ -127,7 +127,7 @@ int main(int argc, char **argv)
* Now we have the maximal tree. Walk the different sha files back to the root. * Now we have the maximal tree. Walk the different sha files back to the root.
*/ */
for (i = 0; i < nr; i++) for (i = 0; i < nr; i++)
mark_reachable(lookup_rev(sha1[i]), 1 << i); mark_reachable(lookup_rev(sha1[i], "commit"), 1 << i);
/* /*
* Now print out the results.. * Now print out the results..

Просмотреть файл

@ -25,6 +25,7 @@ struct revision {
unsigned char sha1[20]; unsigned char sha1[20];
unsigned long date; unsigned long date;
struct parent *parent; struct parent *parent;
char tag[1];
}; };
static struct revision **revs; static struct revision **revs;
@ -51,13 +52,17 @@ static int find_rev(unsigned char *sha1)
return -first-1; return -first-1;
} }
static struct revision *lookup_rev(unsigned char *sha1) static struct revision *lookup_rev(unsigned char *sha1, const char *tag)
{ {
int pos = find_rev(sha1); int pos = find_rev(sha1);
struct revision *n; struct revision *n;
if (pos >= 0) if (pos >= 0) {
return revs[pos]; n = revs[pos];
if (strcmp(n->tag, tag))
error("expected tag %s on object %s: got %s", tag, sha1_to_hex(sha1), n->tag);
return n;
}
pos = -pos-1; pos = -pos-1;
@ -65,11 +70,12 @@ static struct revision *lookup_rev(unsigned char *sha1)
rev_allocs = alloc_nr(rev_allocs); rev_allocs = alloc_nr(rev_allocs);
revs = realloc(revs, rev_allocs * sizeof(struct revision *)); revs = realloc(revs, rev_allocs * sizeof(struct revision *));
} }
n = malloc(sizeof(struct revision)); n = malloc(sizeof(struct revision) + strlen(tag));
n->flags = 0; n->flags = 0;
memcpy(n->sha1, sha1, 20); memcpy(n->sha1, sha1, 20);
n->parent = NULL; n->parent = NULL;
strcpy(n->tag, tag);
/* Insert it into the right place */ /* Insert it into the right place */
memmove(revs + pos + 1, revs + pos, (nr_revs - pos) * sizeof(struct revision *)); memmove(revs + pos + 1, revs + pos, (nr_revs - pos) * sizeof(struct revision *));
@ -79,9 +85,9 @@ static struct revision *lookup_rev(unsigned char *sha1)
return n; return n;
} }
static struct revision *add_relationship(struct revision *rev, unsigned char *needs) static struct revision *add_relationship(struct revision *rev, unsigned char *needs, const char *tag)
{ {
struct revision *parent_rev = lookup_rev(needs); struct revision *parent_rev = lookup_rev(needs, tag);
struct parent **pp = &rev->parent, *p; struct parent **pp = &rev->parent, *p;
while ((p = *pp) != NULL) { while ((p = *pp) != NULL) {
@ -131,7 +137,7 @@ static unsigned long parse_commit_date(const char *buf)
static struct revision * parse_commit(unsigned char *sha1) static struct revision * parse_commit(unsigned char *sha1)
{ {
struct revision *rev = lookup_rev(sha1); struct revision *rev = lookup_rev(sha1, "commit");
if (!(rev->flags & SEEN)) { if (!(rev->flags & SEEN)) {
void *buffer, *bufptr; void *buffer, *bufptr;
@ -145,7 +151,7 @@ static struct revision * parse_commit(unsigned char *sha1)
die("%s is not a commit object", sha1_to_hex(sha1)); die("%s is not a commit object", sha1_to_hex(sha1));
bufptr += 46; /* "tree " + "hex sha1" + "\n" */ bufptr += 46; /* "tree " + "hex sha1" + "\n" */
while (!memcmp(bufptr, "parent ", 7) && !get_sha1_hex(bufptr+7, parent)) { while (!memcmp(bufptr, "parent ", 7) && !get_sha1_hex(bufptr+7, parent)) {
add_relationship(rev, parent); add_relationship(rev, parent, "commit");
parse_commit(parent); parse_commit(parent);
bufptr += 48; /* "parent " + "hex sha1" + "\n" */ bufptr += 48; /* "parent " + "hex sha1" + "\n" */
} }