On Thu, Feb 14, 2008 at 04:00:13AM -0500, Shawn O. Pearce wrote:
quoted text >
> +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?
quoted text > 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?
quoted text > 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@vger.kernel.org
More majordomo info at
http://vger.kernel.org/majordomo-info.html