X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=fsck-cache.c;h=5db07e0f6dbac6b41f31d6ef308dfc7a31915136;hb=ae7c0c92c0713307986bcd1fb54fa0694aae962a;hp=cb010957479976b9d8fdec6dc76e7a6c30e83a1b;hpb=7e8c174a97c45ea87306aad56c762e7752cab324;p=git.git diff --git a/fsck-cache.c b/fsck-cache.c index cb010957..5db07e0f 100644 --- a/fsck-cache.c +++ b/fsck-cache.c @@ -12,6 +12,7 @@ static int show_root = 0; static int show_tags = 0; static int show_unreachable = 0; +static int keep_cache_objects = 0; static unsigned char head_sha1[20]; static void check_connectivity(void) @@ -34,7 +35,7 @@ static void check_connectivity(void) printf("broken link from %7s %s\n", obj->type, sha1_to_hex(obj->sha1)); printf(" to %7s %s\n", - obj->type, sha1_to_hex(refs->item->sha1)); + refs->item->type, sha1_to_hex(refs->item->sha1)); } /* Don't bother with tag reachability. */ @@ -53,13 +54,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; } @@ -77,14 +134,17 @@ static int fsck_commit(struct commit *commit) static int fsck_tag(struct tag *tag) { + struct object *tagged = tag->tagged; + + if (!tagged) { + printf("bad object in tag %s\n", sha1_to_hex(tag->object.sha1)); + return -1; + } if (!show_tags) return 0; - printf("tagged %s %s", - tag->tagged->type, - sha1_to_hex(tag->tagged->sha1)); - printf(" (%s) in %s\n", - tag->tag, sha1_to_hex(tag->object.sha1)); + printf("tagged %s %s", tagged->type, sha1_to_hex(tagged->sha1)); + printf(" (%s) in %s\n", tag->tag, sha1_to_hex(tag->object.sha1)); return 0; } @@ -216,8 +276,12 @@ int main(int argc, char **argv) show_root = 1; continue; } + if (!strcmp(arg, "--cache")) { + keep_cache_objects = 1; + continue; + } if (*arg == '-') - usage("fsck-cache [--tags] [[--unreachable] *]"); + usage("fsck-cache [--tags] [[--unreachable] [--cache] *]"); } sha1_dir = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT; @@ -252,12 +316,27 @@ int main(int argc, char **argv) error("expected sha1, got %s", arg); } - if (!heads) { + if (keep_cache_objects) { + int i; + read_cache(); + for (i = 0; i < active_nr; i++) { + struct blob *blob = lookup_blob(active_cache[i]->sha1); + struct object *obj; + if (!blob) + continue; + obj = &blob->object; + obj->used = 1; + mark_reachable(obj, REACHABLE); + } + } + + if (!heads && !keep_cache_objects) { if (show_unreachable) { - fprintf(stderr, "unable to do reachability without a head\n"); + fprintf(stderr, "unable to do reachability without a head nor --cache\n"); show_unreachable = 0; } - fprintf(stderr, "expect dangling commits - potential heads - due to lack of head information\n"); + if (!heads) + fprintf(stderr, "expect dangling commits - potential heads - due to lack of head information\n"); } check_connectivity();