return buf.buf;
}
+static const char *printable_type(struct object *obj)
+{
+ const char *ret;
+
+ if (obj->type == OBJ_NONE) {
+ enum object_type type = sha1_object_info(obj->oid.hash, NULL);
+ if (type > 0)
+ object_as_type(obj, type, 0);
+ }
+
+ ret = typename(obj->type);
+ if (!ret)
+ ret = "unknown";
+
+ return ret;
+}
+
static int fsck_config(const char *var, const char *value, void *cb)
{
if (strcmp(var, "fsck.skiplist") == 0) {
const char *err)
{
fprintf(stderr, "%s in %s %s: %s\n",
- msg_type, typename(obj->type), describe_object(obj), err);
+ msg_type, printable_type(obj), describe_object(obj), err);
}
static int objerror(struct object *obj, const char *err)
if (!obj) {
/* ... these references to parent->fld are safe here */
printf("broken link from %7s %s\n",
- typename(parent->type), describe_object(parent));
+ printable_type(parent), describe_object(parent));
printf("broken link from %7s %s\n",
(type == OBJ_ANY ? "unknown" : typename(type)), "unknown");
errors_found |= ERROR_REACHABLE;
if (!(obj->flags & HAS_OBJ)) {
if (parent && !has_object_file(&obj->oid)) {
printf("broken link from %7s %s\n",
- typename(parent->type), describe_object(parent));
+ printable_type(parent), describe_object(parent));
printf(" to %7s %s\n",
- typename(obj->type), describe_object(obj));
+ printable_type(obj), describe_object(obj));
errors_found |= ERROR_REACHABLE;
}
return 1;
if (!(obj->flags & HAS_OBJ)) {
if (has_sha1_pack(obj->oid.hash))
return; /* it is in pack - forget about it */
- printf("missing %s %s\n", typename(obj->type),
+ printf("missing %s %s\n", printable_type(obj),
describe_object(obj));
errors_found |= ERROR_REACHABLE;
return;
* since this is something that is prunable.
*/
if (show_unreachable) {
- printf("unreachable %s %s\n", typename(obj->type),
+ printf("unreachable %s %s\n", printable_type(obj),
describe_object(obj));
return;
}
*/
if (!obj->used) {
if (show_dangling)
- printf("dangling %s %s\n", typename(obj->type),
+ printf("dangling %s %s\n", printable_type(obj),
describe_object(obj));
if (write_lost_and_found) {
char *filename = git_pathdup("lost-found/%s/%s",
if (verbose)
fprintf(stderr, "Checking %s %s\n",
- typename(obj->type), describe_object(obj));
+ printable_type(obj), describe_object(obj));
if (fsck_walk(obj, NULL, &fsck_obj_options))
objerror(obj, "broken links");
struct tag *tag = (struct tag *) obj;
if (show_tags && tag->tagged) {
- printf("tagged %s %s", typename(tag->tagged->type),
+ printf("tagged %s %s", printable_type(tag->tagged),
describe_object(tag->tagged));
printf(" (%s) in %s\n", tag->tag,
describe_object(&tag->object));
return 0;
}
-static int fsck_sha1(const unsigned char *sha1)
-{
- struct object *obj = parse_object(sha1);
- if (!obj) {
- errors_found |= ERROR_OBJECT;
- return error("%s: object corrupt or missing",
- sha1_to_hex(sha1));
- }
- obj->flags |= HAS_OBJ;
- return fsck_obj(obj);
-}
-
static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type,
unsigned long size, void *buffer, int *eaten)
{
if (!is_null_sha1(sha1)) {
obj = lookup_object(sha1);
- if (obj) {
+ if (obj && (obj->flags & HAS_OBJ)) {
if (timestamp && name_objects)
add_decoration(fsck_walk_options.object_names,
obj,
}
}
+static struct object *parse_loose_object(const unsigned char *sha1,
+ const char *path)
+{
+ struct object *obj;
+ void *contents;
+ enum object_type type;
+ unsigned long size;
+ int eaten;
+
+ if (read_loose_object(path, sha1, &type, &size, &contents) < 0)
+ return NULL;
+
+ if (!contents && type != OBJ_BLOB)
+ die("BUG: read_loose_object streamed a non-blob");
+
+ obj = parse_object_buffer(sha1, type, size, contents, &eaten);
+
+ if (!eaten)
+ free(contents);
+ return obj;
+}
+
static int fsck_loose(const unsigned char *sha1, const char *path, void *data)
{
- if (fsck_sha1(sha1))
+ struct object *obj = parse_loose_object(sha1, path);
+
+ if (!obj) {
+ errors_found |= ERROR_OBJECT;
+ error("%s: object corrupt or missing: %s",
+ sha1_to_hex(sha1), path);
+ return 0; /* keep checking other objects */
+ }
+
+ obj->flags = HAS_OBJ;
+ if (fsck_obj(obj))
errors_found |= ERROR_OBJECT;
return 0;
}
static void mark_object_for_connectivity(const unsigned char *sha1)
{
- struct object *obj = lookup_object(sha1);
-
- /*
- * Setting the object type here isn't strictly necessary for a
- * connectivity check. In most cases, our walk will expect a certain
- * type (e.g., a tree referencing a blob) and will use lookup_blob() to
- * assign the type. But doing it here has two advantages:
- *
- * 1. When the fsck_walk code looks at objects that _don't_ come from
- * links (e.g., the tip of a ref), it may complain about the
- * "unknown object type".
- *
- * 2. This serves as a nice cross-check that the graph links are
- * sane. So --connectivity-only does not check that the bits of
- * blobs are not corrupted, but it _does_ check that 100644 tree
- * entries point to blobs, and so forth.
- *
- * Unfortunately we can't just use parse_object() here, because the
- * whole point of --connectivity-only is to avoid reading the object
- * data more than necessary.
- */
- if (!obj || obj->type == OBJ_NONE) {
- enum object_type type = sha1_object_info(sha1, NULL);
- switch (type) {
- case OBJ_BAD:
- error("%s: unable to read object type",
- sha1_to_hex(sha1));
- break;
- case OBJ_COMMIT:
- obj = (struct object *)lookup_commit(sha1);
- break;
- case OBJ_TREE:
- obj = (struct object *)lookup_tree(sha1);
- break;
- case OBJ_BLOB:
- obj = (struct object *)lookup_blob(sha1);
- break;
- case OBJ_TAG:
- obj = (struct object *)lookup_tag(sha1);
- break;
- default:
- error("%s: unknown object type %d",
- sha1_to_hex(sha1), type);
- }
-
- if (!obj || obj->type == OBJ_NONE) {
- errors_found |= ERROR_OBJECT;
- return;
- }
- }
-
+ struct object *obj = lookup_unknown_object(sha1);
obj->flags |= HAS_OBJ;
}
if (!get_sha1(arg, sha1)) {
struct object *obj = lookup_object(sha1);
- if (!obj) {
+ if (!obj || !(obj->flags & HAS_OBJ)) {
error("%s: object missing", sha1_to_hex(sha1));
errors_found |= ERROR_OBJECT;
continue;