diff options
author | Linus Torvalds <torvalds@osdl.org> | 2007-01-21 22:26:41 -0800 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2007-01-21 23:35:47 -0800 |
commit | 18af29f247f79b6fb61335f98a21daea67f5632f (patch) | |
tree | 64bfa10f911db22c2a973855d316f33d0e9b7098 | |
parent | e3ff4b244726f89620201e3295f097cf00b6b502 (diff) | |
download | git-18af29f247f79b6fb61335f98a21daea67f5632f.tar.gz git-18af29f247f79b6fb61335f98a21daea67f5632f.tar.xz |
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 <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r-- | fsck-objects.c | 133 |
1 files changed, 95 insertions, 38 deletions
diff --git a/fsck-objects.c b/fsck-objects.c index 81f00db90..ecfb014ff 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); } } |