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>
This commit is contained in:
parent
e3ff4b2447
commit
18af29f247
133
fsck-objects.c
133
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user