X-Git-Url: https://git.octo.it/?p=git.git;a=blobdiff_plain;f=fsck-objects.c;h=2b1aab488f2b8d64fa799adf427b6eeca35ac757;hp=9950be264501a5c99eafe7c2438b27b857ba6402;hb=HEAD;hpb=767e130915015f897fb87b939843b4882212574b diff --git a/fsck-objects.c b/fsck-objects.c index 9950be26..2b1aab48 100644 --- a/fsck-objects.c +++ b/fsck-objects.c @@ -8,19 +8,21 @@ #include "tag.h" #include "refs.h" #include "pack.h" +#include "cache-tree.h" +#include "tree-walk.h" #define REACHABLE 0x0001 +#define SEEN 0x0002 static int show_root = 0; static int show_tags = 0; static int show_unreachable = 0; -static int standalone = 0; static int check_full = 0; static int check_strict = 0; -static int keep_cache_objects = 0; +static int keep_cache_objects = 0; static unsigned char head_sha1[20]; -#if NO_D_INO_IN_DIRENT +#ifdef NO_D_INO_IN_DIRENT #define SORT_DIRENT 0 #define DIRENT_SORT_HINT(de) 0 #else @@ -32,7 +34,7 @@ static void objreport(struct object *obj, const char *severity, const char *err, va_list params) { fprintf(stderr, "%s in %s %s: ", - severity, obj->type, sha1_to_hex(obj->sha1)); + severity, typename(obj->type), sha1_to_hex(obj->sha1)); vfprintf(stderr, err, params); fputs("\n", stderr); } @@ -61,15 +63,18 @@ static void check_connectivity(void) int i; /* Look up all the requirements, warn about missing objects.. */ - for (i = 0; i < nr_objs; i++) { + for (i = 0; i < obj_allocs; i++) { struct object *obj = objs[i]; + if (!obj) + continue; + if (!obj->parsed) { - if (!standalone && has_sha1_file(obj->sha1)) + if (has_sha1_file(obj->sha1)) ; /* it is in pack */ else printf("missing %s %s\n", - obj->type, sha1_to_hex(obj->sha1)); + typename(obj->type), sha1_to_hex(obj->sha1)); continue; } @@ -79,23 +84,23 @@ static void check_connectivity(void) for (j = 0; j < refs->count; j++) { struct object *ref = refs->ref[j]; if (ref->parsed || - (!standalone && has_sha1_file(ref->sha1))) + (has_sha1_file(ref->sha1))) continue; printf("broken link from %7s %s\n", - obj->type, sha1_to_hex(obj->sha1)); + typename(obj->type), sha1_to_hex(obj->sha1)); printf(" to %7s %s\n", - ref->type, sha1_to_hex(ref->sha1)); + typename(ref->type), sha1_to_hex(ref->sha1)); } } if (show_unreachable && !(obj->flags & REACHABLE)) { printf("unreachable %s %s\n", - obj->type, sha1_to_hex(obj->sha1)); + typename(obj->type), sha1_to_hex(obj->sha1)); continue; } if (!obj->used) { - printf("dangling %s %s\n", obj->type, + printf("dangling %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1)); } } @@ -112,15 +117,15 @@ static void check_connectivity(void) #define TREE_UNORDERED (-1) #define TREE_HAS_DUPS (-2) -static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) +static int verify_ordered(unsigned mode1, const char *name1, unsigned mode2, const char *name2) { - int len1 = strlen(a->name); - int len2 = strlen(b->name); + int len1 = strlen(name1); + int len2 = strlen(name2); int len = len1 < len2 ? len1 : len2; unsigned char c1, c2; int cmp; - cmp = memcmp(a->name, b->name, len); + cmp = memcmp(name1, name2, len); if (cmp < 0) return 0; if (cmp > 0) @@ -131,8 +136,8 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) * 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]; + c1 = name1[len]; + c2 = name2[len]; if (!c1 && !c2) /* * git-write-tree used to write out a nonsense tree that has @@ -140,9 +145,9 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) * sure we do not have duplicate entries. */ return TREE_HAS_DUPS; - if (!c1 && a->directory) + if (!c1 && S_ISDIR(mode1)) c1 = '/'; - if (!c2 && b->directory) + if (!c2 && S_ISDIR(mode2)) c2 = '/'; return c1 < c2 ? 0 : TREE_UNORDERED; } @@ -155,17 +160,32 @@ static int fsck_tree(struct tree *item) int has_bad_modes = 0; int has_dup_entries = 0; int not_properly_sorted = 0; - struct tree_entry_list *entry, *last; + struct tree_desc desc; + unsigned o_mode; + const char *o_name; + const unsigned char *o_sha1; + + desc.buf = item->buffer; + desc.size = item->size; + + o_mode = 0; + o_name = NULL; + o_sha1 = NULL; + while (desc.size) { + unsigned mode; + const char *name; + const unsigned char *sha1; - last = NULL; - for (entry = item->entries; entry; entry = entry->next) { - if (strchr(entry->name, '/')) + sha1 = tree_entry_extract(&desc, &name, &mode); + + if (strchr(name, '/')) has_full_path = 1; - has_zero_pad |= entry->zeropad; + has_zero_pad |= *(char *)desc.buf == '0'; + update_tree_entry(&desc); - switch (entry->mode) { + switch (mode) { /* - * Standard modes.. + * Standard modes.. */ case S_IFREG | 0755: case S_IFREG | 0644: @@ -184,8 +204,8 @@ static int fsck_tree(struct tree *item) has_bad_modes = 1; } - if (last) { - switch (verify_ordered(last, entry)) { + if (o_name) { + switch (verify_ordered(o_mode, o_name, mode, name)) { case TREE_UNORDERED: not_properly_sorted = 1; break; @@ -195,17 +215,14 @@ static int fsck_tree(struct tree *item) default: break; } - free(last->name); - free(last); } - last = entry; - } - if (last) { - free(last->name); - free(last); + o_mode = mode; + o_name = name; + o_sha1 = sha1; } - item->entries = NULL; + free(item->buffer); + item->buffer = NULL; retval = 0; if (has_full_path) { @@ -265,7 +282,7 @@ static int fsck_tag(struct tag *tag) if (!show_tags) return 0; - printf("tagged %s %s", tagged->type, sha1_to_hex(tagged->sha1)); + printf("tagged %s %s", typename(tagged->type), sha1_to_hex(tagged->sha1)); printf(" (%s) in %s\n", tag->tag, sha1_to_hex(tag->object.sha1)); return 0; } @@ -275,16 +292,19 @@ static int fsck_sha1(unsigned char *sha1) struct object *obj = parse_object(sha1); if (!obj) return error("%s: object not found", sha1_to_hex(sha1)); - if (obj->type == blob_type) + if (obj->flags & SEEN) return 0; - if (obj->type == tree_type) + obj->flags |= SEEN; + if (obj->type == TYPE_BLOB) + return 0; + if (obj->type == TYPE_TREE) return fsck_tree((struct tree *) obj); - if (obj->type == commit_type) + if (obj->type == TYPE_COMMIT) return fsck_commit((struct commit *) obj); - if (obj->type == tag_type) + if (obj->type == TYPE_TAG) return fsck_tag((struct tag *) obj); /* By now, parse_object() would've returned NULL instead. */ - return objerror(obj, "unknown type '%s' (internal fsck error)", obj->type); + return objerror(obj, "unknown type '%d' (internal fsck error)", obj->type); } /* @@ -387,7 +407,7 @@ static int fsck_handle_ref(const char *refname, const unsigned char *sha1) obj = lookup_object(sha1); if (!obj) { - if (!standalone && has_sha1_file(sha1)) { + if (has_sha1_file(sha1)) { default_refs++; return 0; /* it is in a pack */ } @@ -436,10 +456,33 @@ static int fsck_head_link(void) return 0; } +static int fsck_cache_tree(struct cache_tree *it) +{ + int i; + int err = 0; + + if (0 <= it->entry_count) { + struct object *obj = parse_object(it->sha1); + if (!obj) { + error("%s: invalid sha1 pointer in cache-tree", + sha1_to_hex(it->sha1)); + return 1; + } + mark_reachable(obj, REACHABLE); + obj->used = 1; + if (obj->type != TYPE_TREE) + err |= objerror(obj, "non-tree in cache-tree"); + } + for (i = 0; i < it->subtree_nr; i++) + err |= fsck_cache_tree(it->down[i]->cache_tree); + return err; +} + int main(int argc, char **argv) { int i, heads; + track_object_refs = 1; setup_git_directory(); for (i = 1; i < argc; i++) { @@ -461,10 +504,6 @@ int main(int argc, char **argv) keep_cache_objects = 1; continue; } - if (!strcmp(arg, "--standalone")) { - standalone = 1; - continue; - } if (!strcmp(arg, "--full")) { check_full = 1; continue; @@ -474,14 +513,9 @@ int main(int argc, char **argv) continue; } if (*arg == '-') - usage("git-fsck-objects [--tags] [--root] [[--unreachable] [--cache] [--standalone | --full] [--strict] *]"); + usage("git-fsck-objects [--tags] [--root] [[--unreachable] [--cache] [--full] [--strict] *]"); } - if (standalone && check_full) - die("Only one of --standalone or --full can be used."); - if (standalone) - putenv("GIT_ALTERNATE_OBJECT_DIRECTORIES="); - fsck_head_link(); fsck_object_dir(get_object_directory()); if (check_full) { @@ -554,6 +588,8 @@ int main(int argc, char **argv) obj->used = 1; mark_reachable(obj, REACHABLE); } + if (active_cache_tree) + fsck_cache_tree(active_cache_tree); } check_connectivity();