From 18af29f247f79b6fb61335f98a21daea67f5632f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 21 Jan 2007 22:26:41 -0800 Subject: [PATCH] fsck-objects: refactor checking for connectivity This separates the connectivity check into separate codepaths, one for reachable objects and the other for unreachable ones, while adding a lot of comments to explain what is going on. When checking an unreachable object, unlike a reachable one, we do not have to complain if it does not exist (we used to complain about a missing blob even when the only thing that references it is a tree that is dangling). Also we do not have to check and complain about objects that are referenced by an unreachable object. This makes the messages from fsck-objects a lot less noisy and more useful. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- fsck-objects.c | 133 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 38 deletions(-) diff --git a/fsck-objects.c b/fsck-objects.c index 81f00db90b..ecfb014fff 100644 --- a/fsck-objects.c +++ b/fsck-objects.c @@ -54,6 +54,99 @@ static int objwarning(struct object *obj, const char *err, ...) return -1; } +/* + * 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 + * do a full fsck + */ + if (!obj->parsed) { + if (has_sha1_file(obj->sha1)) + return; /* it is in pack - forget about it */ + printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1)); + return; + } + + /* + * Check that everything that we try to reference is also good. + */ + 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)); + } + } +} + +/* + * Check a single unreachable object + */ +static void check_unreachable_object(struct object *obj) +{ + /* + * Missing unreachable object? Ignore it. It's not like + * we miss it (since it can't be reached), nor do we want + * to complain about it being unreachable (since it does + * not exist). + */ + if (!obj->parsed) + return; + + /* + * Unreachable object that exists? Show it if asked to, + * since this is something that is prunable. + */ + if (show_unreachable) { + printf("unreachable %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1)); + return; + } + + /* + * "!used" means that nothing at all points to it, including + * other unreacahble objects. In other words, it's the "tip" + * of some set of unreachable objects, usually a commit that + * got dropped. + * + * Such starting points are more interesting than some random + * set of unreachable objects, so we show them even if the user + * hasn't asked for _all_ unreachable objects. If you have + * deleted a branch by mistake, this is a prime candidate to + * start looking at, for example. + */ + if (!obj->used) { + printf("dangling %s %s\n", typename(obj->type), + sha1_to_hex(obj->sha1)); + return; + } + + /* + * Otherwise? It's there, it's unreachable, and some other unreachable + * object points to it. Ignore it - it's not interesting, and we showed + * all the interesting cases above. + */ +} + +static void check_object(struct object *obj) +{ + if (obj->flags & REACHABLE) + check_reachable_object(obj); + else + check_unreachable_object(obj); +} static void check_connectivity(void) { @@ -62,46 +155,10 @@ static void check_connectivity(void) /* Look up all the requirements, warn about missing objects.. */ max = get_max_object_index(); for (i = 0; i < max; i++) { - const struct object_refs *refs; struct object *obj = get_indexed_object(i); - if (!obj) - continue; - - if (!obj->parsed) { - if (has_sha1_file(obj->sha1)) - ; /* it is in pack */ - else - printf("missing %s %s\n", - typename(obj->type), sha1_to_hex(obj->sha1)); - continue; - } - - 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)); - } - } - - if (show_unreachable && !(obj->flags & REACHABLE)) { - printf("unreachable %s %s\n", - typename(obj->type), sha1_to_hex(obj->sha1)); - continue; - } - - if (!obj->used) { - printf("dangling %s %s\n", typename(obj->type), - sha1_to_hex(obj->sha1)); - } + if (obj) + check_object(obj); } } -- 2.47.1