From: Linus Torvalds Date: Mon, 2 May 2005 23:13:18 +0000 (-0700) Subject: Make fsck-cache do better tree checking. X-Git-Tag: v0.99~657 X-Git-Url: https://git.octo.it/?p=git.git;a=commitdiff_plain;h=8500349208e6bfd0e8bc67d294bfea93da2328a2 Make fsck-cache do better tree checking. We check the ordering of the entries, and we verify that none of the entries has a slash in it (this allows us to remove the hacky "has_full_path" member from the tree structure, since we now just test it by walking the tree entries instead). --- diff --git a/fsck-cache.c b/fsck-cache.c index cb010957..7dda9c3e 100644 --- a/fsck-cache.c +++ b/fsck-cache.c @@ -53,13 +53,69 @@ static void check_connectivity(void) } } +/* + * The entries in a tree are ordered in the _path_ order, + * which means that a directory entry is ordered by adding + * a slash to the end of it. + * + * So a directory called "a" is ordered _after_ a file + * called "a.c", because "a/" sorts after "a.c". + */ +static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) +{ + int len1 = strlen(a->name); + int len2 = strlen(b->name); + int len = len1 < len2 ? len1 : len2; + unsigned char c1, c2; + int cmp; + + cmp = memcmp(a->name, b->name, len); + if (cmp < 0) + return 0; + if (cmp > 0) + return -1; + + /* + * Ok, the first characters are the same. + * Now we need to order the next one, but turn + * a '\0' into a '/' for a directory entry. + */ + c1 = a->name[len]; + c2 = b->name[len]; + if (!c1 && a->directory) + c1 = '/'; + if (!c2 && b->directory) + c2 = '/'; + return c1 < c2 ? 0 : -1; +} + static int fsck_tree(struct tree *item) { - if (item->has_full_path) { + int has_full_path = 0; + struct tree_entry_list *entry, *last; + + last = NULL; + for (entry = item->entries; entry; entry = entry->next) { + if (strchr(entry->name, '/')) + has_full_path = 1; + + if (last) { + if (verify_ordered(last, entry) < 0) { + fprintf(stderr, "tree %s not ordered\n", + sha1_to_hex(item->object.sha1)); + return -1; + } + } + + last = entry; + } + + if (has_full_path) { fprintf(stderr, "warning: fsck-cache: tree %s " "has full pathnames in it\n", sha1_to_hex(item->object.sha1)); } + return 0; } diff --git a/tree.c b/tree.c index 15a16d56..72305a35 100644 --- a/tree.c +++ b/tree.c @@ -122,11 +122,6 @@ int parse_tree(struct tree *item) entry->executable = mode & S_IXUSR; entry->next = NULL; - /* Warn about trees that don't do the recursive thing.. */ - if (strchr(path, '/')) { - item->has_full_path = 1; - } - bufptr += len + 20; size -= len + 20; diff --git a/tree.h b/tree.h index 19b19056..96cf4291 100644 --- a/tree.h +++ b/tree.h @@ -18,7 +18,6 @@ struct tree_entry_list { struct tree { struct object object; - unsigned has_full_path : 1; struct tree_entry_list *entries; };