summaryrefslogtreecommitdiff
path: root/fsck-cache.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-02 16:13:18 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-02 16:13:18 -0700
commit8500349208e6bfd0e8bc67d294bfea93da2328a2 (patch)
treeba11908cd5f5b6f9e2ddb9b34789f5771a968c07 /fsck-cache.c
parentf220fb6b84e982417dda30b2fd09a0f1d987d2e4 (diff)
downloadgit-8500349208e6bfd0e8bc67d294bfea93da2328a2.tar.gz
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).
Diffstat (limited to 'fsck-cache.c')
-rw-r--r--fsck-cache.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/fsck-cache.c b/fsck-cache.c
index cb01095747..7dda9c3eb7 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 <len> 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;
}