Merge branch 'jk/tempfile-ferror-fclose-confusion'
[gitweb.git] / builtin / fsck.c
index 3d5ced2d3ac2e9d2fdfacd498a7592902d96ebdb..1a5caccd0f5ee3fa56af06e8f536271f58312665 100644 (file)
@@ -60,6 +60,12 @@ 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";
@@ -371,18 +377,6 @@ static int fsck_obj(struct object *obj)
        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)
 {
@@ -497,9 +491,41 @@ static void get_default_heads(void)
        }
 }
 
+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;
 }
@@ -595,57 +621,7 @@ static int fsck_cache_tree(struct cache_tree *it)
 
 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;
 }