Merge branch 'jc/maint-1.6.0-keep-pack' into maint-1.6.1
[git/git.git] / builtin-fsck.c
index d3f3de9..a60d199 100644 (file)
@@ -64,11 +64,11 @@ static int fsck_error_func(struct object *obj, int type, const char *err, ...)
        return (type == FSCK_WARN) ? 0 : 1;
 }
 
+static struct object_array pending;
+
 static int mark_object(struct object *obj, int type, void *data)
 {
-       struct tree *tree = NULL;
        struct object *parent = data;
-       int result;
 
        if (!obj) {
                printf("broken link from %7s %s\n",
@@ -96,6 +96,20 @@ static int mark_object(struct object *obj, int type, void *data)
                return 1;
        }
 
+       add_object_array(obj, (void *) parent, &pending);
+       return 0;
+}
+
+static void mark_object_reachable(struct object *obj)
+{
+       mark_object(obj, OBJ_ANY, 0);
+}
+
+static int traverse_one_object(struct object *obj, struct object *parent)
+{
+       int result;
+       struct tree *tree = NULL;
+
        if (obj->type == OBJ_TREE) {
                obj->parsed = 0;
                tree = (struct tree *)obj;
@@ -107,15 +121,22 @@ static int mark_object(struct object *obj, int type, void *data)
                free(tree->buffer);
                tree->buffer = NULL;
        }
-       if (result < 0)
-               result = 1;
-
        return result;
 }
 
-static void mark_object_reachable(struct object *obj)
+static int traverse_reachable(void)
 {
-       mark_object(obj, OBJ_ANY, 0);
+       int result = 0;
+       while (pending.nr) {
+               struct object_array_entry *entry;
+               struct object *obj, *parent;
+
+               entry = pending.objects + --pending.nr;
+               obj = entry->item;
+               parent = (struct object *) entry->name;
+               result |= traverse_one_object(obj, parent);
+       }
+       return !!result;
 }
 
 static int mark_used(struct object *obj, int type, void *data)
@@ -137,7 +158,7 @@ static void check_reachable_object(struct object *obj)
         * do a full fsck
         */
        if (!obj->parsed) {
-               if (has_sha1_pack(obj->sha1, NULL))
+               if (has_sha1_pack(obj->sha1))
                        return; /* it is in pack - forget about it */
                printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1));
                errors_found |= ERROR_REACHABLE;
@@ -201,12 +222,16 @@ static void check_unreachable_object(struct object *obj)
                                char *buf = read_sha1_file(obj->sha1,
                                                &type, &size);
                                if (buf) {
-                                       fwrite(buf, size, 1, f);
+                                       if (fwrite(buf, size, 1, f) != 1)
+                                               die("Could not write %s: %s",
+                                                   filename, strerror(errno));
                                        free(buf);
                                }
                        } else
                                fprintf(f, "%s\n", sha1_to_hex(obj->sha1));
-                       fclose(f);
+                       if (fclose(f))
+                               die("Could not finish %s: %s",
+                                   filename, strerror(errno));
                }
                return;
        }
@@ -233,6 +258,9 @@ static void check_connectivity(void)
 {
        int i, max;
 
+       /* Traverse the pending reachable objects */
+       traverse_reachable();
+
        /* Look up all the requirements, warn about missing objects.. */
        max = get_max_object_index();
        if (verbose)
@@ -600,7 +628,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
        }
 
        heads = 0;
-       for (i = 1; i < argc; i++) {
+       for (i = 0; i < argc; i++) {
                const char *arg = argv[i];
                if (!get_sha1(arg, head_sha1)) {
                        struct object *obj = lookup_object(head_sha1);