On Thu, Feb 14, 2008 at 04:00:13AM -0500, Shawn O. Pearce wrote: > > +static int object_exists(const unsigned char *sha1) > +{ > + struct object *obj = lookup_object(sha1); > + if (obj && obj->flags & FSCKED) > + return 1; > + return has_sha1_file(sha1); > +} > + > +static void broken_link(struct object *obj, > + enum object_type ref_type, > + const unsigned char *ref_sha1) > +{ > + printf("broken link from %7s %s\n", > + typename(obj->type), sha1_to_hex(obj->sha1)); > + printf(" to %7s %s\n", > + typename(ref_type), sha1_to_hex(ref_sha1)); > + errors_found |= ERROR_REACHABLE; > +} > + > +static void broken_tree(struct tree *item) > +{ > + struct tree_desc desc; > + > + item->object.parsed = 0; > + if (parse_tree(item) < 0) > + return; /* error already displayed */ > + > + init_tree_desc(&desc, item->buffer, item->size); > + while (desc.size) { > + unsigned mode; > + const char *name; > + const unsigned char *sha1; > + > + sha1 = tree_entry_extract(&desc, &name, &mode); > + update_tree_entry(&desc); > + if (S_ISGITLINK(mode) || object_exists(sha1)) > + continue; > + if (S_ISDIR(mode)) > + broken_link(&item->object, OBJ_TREE, sha1); > + else > + broken_link(&item->object, OBJ_BLOB, sha1); > + } > + free(item->buffer); > + item->buffer = NULL; > +} > + > +static void broken_commit(struct commit *commit) > +{ > + struct tree *tree = commit->tree; > + struct commit_list *pp; > + > + if (tree && !object_exists(tree->object.sha1)) > + broken_link(&commit->object, OBJ_TREE, tree->object.sha1); > + > + pp = commit->parents; > + while (pp) { > + struct commit *p = pp->item; > + if (p && !object_exists(p->object.sha1)) > + broken_link(&commit->object, OBJ_COMMIT, p->object.sha1); > + pp = pp->next; > + } > +} > + > +static void broken_tag(struct tag *tag) > +{ > + struct object *ref = tag->tagged; > + if (ref && !object_exists(ref->sha1)) > + broken_link(&tag->object, ref->type, ref->sha1); > +} > + > /* > * Check a single reachable object > */ > static void check_reachable_object(struct object *obj) > { > - const struct object_refs *refs; > - > /* > * We obviously want the object to be parsed, > * except if it was in a pack-file and we didn't > @@ -84,21 +155,28 @@ static void check_reachable_object(struct object *obj) > } > > /* > - * Check that everything that we try to reference is also good. > + * If the fsck routines found this object WANTING > + * then we need to re-evaluate what it wanted and > + * report on those broken links. > */ > - refs = lookup_object_refs(obj); > - if (refs) { > - unsigned j; > - for (j = 0; j < refs->count; j++) { > - struct object *ref = refs->ref[j]; > - if (ref->parsed || > - (has_sha1_file(ref->sha1))) > - continue; > - printf("broken link from %7s %s\n", > - typename(obj->type), sha1_to_hex(obj->sha1)); > - printf(" to %7s %s\n", > - typename(ref->type), sha1_to_hex(ref->sha1)); > - errors_found |= ERROR_REACHABLE; > + if (obj->flags & WANTING) { > + switch (obj->type) { > + case OBJ_TREE: > + broken_tree((struct tree *) obj); > + break; > + > + case OBJ_COMMIT: > + broken_commit((struct commit *) obj); > + break; > + > + case OBJ_TAG: > + broken_tag((struct tag *) obj); > + break; > + > + default: > + objerror(obj, > + "type '%d' has broken link (internal fsck error)", > + obj->type); > } > } > } > @@ -181,7 +259,7 @@ static void check_object(struct object *obj) > if (verbose) > fprintf(stderr, "Checking %s\n", sha1_to_hex(obj->sha1)); > > - if (obj->flags & REACHABLE) > + if (obj->flags & SEEN) > check_reachable_object(obj); > else > check_unreachable_object(obj); > @@ -309,6 +387,15 @@ static int fsck_tree(struct tree *item) > has_bad_modes = 1; > } > > + /* > + * If the SHA-1 should exist in this repository but > + * we are missing it flag this tree as WANTING. We > + * will revisit this error later once we determine > + * this tree is SEEN. > + */ > + if (!S_ISGITLINK(mode) && !object_exists(sha1)) > + item->object.flags |= WANTING; > + > if (o_name) { > switch (verify_ordered(o_mode, o_name, mode, name)) { > case TREE_UNORDERED: > @@ -367,10 +454,15 @@ static int fsck_commit(struct commit *commit) > return objerror(&commit->object, "invalid format - expected 'tree' line"); > if (get_sha1_hex(buffer+5, tree_sha1) || buffer[45] != '\n') > return objerror(&commit->object, "invalid 'tree' line format - bad sha1"); > + if (!object_exists(tree_sha1)) > + commit->object.flags |= WANTING; > + How do we verify, that tree_sha1 is a tree? > buffer += 46; > while (!memcmp(buffer, "parent ", 7)) { > if (get_sha1_hex(buffer+7, sha1) || buffer[47] != '\n') > return objerror(&commit->object, "invalid 'parent' line format - bad sha1"); > + if (!object_exists(sha1)) > + commit->object.flags |= WANTING; How do we verify, that sha1 is a commit? > buffer += 48; > } > if (memcmp(buffer, "author ", 7)) > @@ -395,6 +487,9 @@ static int fsck_tag(struct tag *tag) > if (!tagged) { > return objerror(&tag->object, "could not load tagged object"); > } > + if (!object_exists(tagged->sha1)) > + tag->object.flags |= WANTING; > + Same here. Where do we check the type? mfg Martin Kögler - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html