static int mark_object(struct object *obj, int type, void *data, struct fsck_options *options) { struct object *parent = data; /* * The only case data is NULL or type is OBJ_ANY is when * mark_object_reachable() calls us. All the callers of * that function has non-NULL obj hence ... */ if (!obj) { /* ... these references to parent->fld are safe here */ printf("broken link from %7s %s\n", printable_type(parent), describe_object(parent)); printf("broken link from %7s %s\n", (type == OBJ_ANY ? "unknown" : type_name(type)), "unknown"); errors_found |= ERROR_REACHABLE; return 1; } if (type != OBJ_ANY && obj->type != type) /* ... and the reference to parent is safe here */ objerror(parent, "wrong object type in link"); if (obj->flags & REACHABLE) return 0; obj->flags |= REACHABLE; if (is_promisor_object(&obj->oid)) /* * Further recursion does not need to be performed on this * object since it is a promisor object (so it does not need to * be added to "pending"). */ return 0; if (!(obj->flags & HAS_OBJ)) { if (parent && !has_object_file(&obj->oid)) { printf("broken link from %7s %s\n", printable_type(parent), describe_object(parent)); printf(" to %7s %s\n", printable_type(obj), describe_object(obj)); errors_found |= ERROR_REACHABLE; } return 1; } add_object_array(obj, NULL, &pending); return 0; }
printable* make_printable(size_t size, void* data) { printable* result = ALLOCATE(sizeof(printable)); result->size = size; result->val = data; result->type = printable_type(); define_method(result->type, to_string, to_string_default); return result; }
static int fsck_obj(struct object *obj) { int err; if (obj->flags & SEEN) return 0; obj->flags |= SEEN; if (verbose) fprintf(stderr, "Checking %s %s\n", printable_type(obj), describe_object(obj)); if (fsck_walk(obj, NULL, &fsck_obj_options)) objerror(obj, "broken links"); err = fsck_object(obj, NULL, 0, &fsck_obj_options); if (err) goto out; if (obj->type == OBJ_COMMIT) { struct commit *commit = (struct commit *) obj; if (!commit->parents && show_root) printf("root %s\n", describe_object(&commit->object)); } if (obj->type == OBJ_TAG) { struct tag *tag = (struct tag *) obj; if (show_tags && tag->tagged) { printf("tagged %s %s", printable_type(tag->tagged), describe_object(tag->tagged)); printf(" (%s) in %s\n", tag->tag, describe_object(&tag->object)); } } out: if (obj->type == OBJ_TREE) free_tree_buffer((struct tree *)obj); if (obj->type == OBJ_COMMIT) free_commit_buffer((struct commit *)obj); return err; }
static int mark_object(struct object *obj, int type, void *data, struct fsck_options *options) { struct object *parent = data; /* * The only case data is NULL or type is OBJ_ANY is when * mark_object_reachable() calls us. All the callers of * that function has non-NULL obj hence ... */ if (!obj) { /* ... these references to parent->fld are safe here */ printf("broken link from %7s %s\n", printable_type(parent), describe_object(parent)); printf("broken link from %7s %s\n", (type == OBJ_ANY ? "unknown" : typename(type)), "unknown"); errors_found |= ERROR_REACHABLE; return 1; }
/* * Check a single reachable object */ static void check_reachable_object(struct object *obj) { /* * 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->flags & HAS_OBJ)) { if (is_promisor_object(&obj->oid)) return; if (has_sha1_pack(obj->oid.hash)) return; /* it is in pack - forget about it */ printf("missing %s %s\n", printable_type(obj), describe_object(obj)); errors_found |= ERROR_REACHABLE; return; } }
static void objreport(struct object *obj, const char *msg_type, const char *err) { fprintf(stderr, "%s in %s %s: %s\n", msg_type, printable_type(obj), describe_object(obj), err); }
/* * 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->flags & HAS_OBJ)) 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", printable_type(obj), describe_object(obj)); return; } /* * "!USED" means that nothing at all points to it, including * other unreachable 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->flags & USED)) { if (show_dangling) printf("dangling %s %s\n", printable_type(obj), describe_object(obj)); if (write_lost_and_found) { char *filename = git_pathdup("lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", describe_object(obj)); FILE *f; if (safe_create_leading_directories_const(filename)) { error("Could not create lost-found"); free(filename); return; } f = xfopen(filename, "w"); if (obj->type == OBJ_BLOB) { if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1)) die_errno("Could not write '%s'", filename); } else fprintf(f, "%s\n", describe_object(obj)); if (fclose(f)) die_errno("Could not finish '%s'", filename); free(filename); } 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. */ }