Merge branch 'master' of git://repo.or.cz/git-gui
[gitweb.git] / builtin-fsck.c
index fec1cbd784f598342eb44f385a55dba25a0b9021..b8e71b640b66ebd95a436a5c1c7f3fce0647be0c 100644 (file)
@@ -18,6 +18,9 @@ static int check_full;
 static int check_strict;
 static int keep_cache_objects;
 static unsigned char head_sha1[20];
+static int errors_found;
+#define ERROR_OBJECT 01
+#define ERROR_REACHABLE 02
 
 #ifdef NO_D_INO_IN_DIRENT
 #define SORT_DIRENT 0
@@ -40,6 +43,7 @@ static int objerror(struct object *obj, const char *err, ...)
 {
        va_list params;
        va_start(params, err);
+       errors_found |= ERROR_OBJECT;
        objreport(obj, "error", err, params);
        va_end(params);
        return -1;
@@ -67,9 +71,10 @@ static void check_reachable_object(struct object *obj)
         * do a full fsck
         */
        if (!obj->parsed) {
-               if (has_sha1_file(obj->sha1))
+               if (has_sha1_pack(obj->sha1, NULL))
                        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;
                return;
        }
 
@@ -88,6 +93,7 @@ static void check_reachable_object(struct object *obj)
                               typename(obj->type), sha1_to_hex(obj->sha1));
                        printf("              to %7s %s\n",
                               typename(ref->type), sha1_to_hex(ref->sha1));
+                       errors_found |= ERROR_REACHABLE;
                }
        }
 }
@@ -117,7 +123,7 @@ static void check_unreachable_object(struct object *obj)
 
        /*
         * "!used" means that nothing at all points to it, including
-        * other unreacahble objects. In other words, it's the "tip"
+        * other unreachable objects. In other words, it's the "tip"
         * of some set of unreachable objects, usually a commit that
         * got dropped.
         *
@@ -346,8 +352,11 @@ static int fsck_tag(struct tag *tag)
 static int fsck_sha1(unsigned char *sha1)
 {
        struct object *obj = parse_object(sha1);
-       if (!obj)
-               return error("%s: object corrupt or missing", sha1_to_hex(sha1));
+       if (!obj) {
+               errors_found |= ERROR_OBJECT;
+               return error("%s: object corrupt or missing",
+                            sha1_to_hex(sha1));
+       }
        if (obj->flags & SEEN)
                return 0;
        obj->flags |= SEEN;
@@ -359,8 +368,10 @@ static int fsck_sha1(unsigned char *sha1)
                return fsck_commit((struct commit *) obj);
        if (obj->type == OBJ_TAG)
                return fsck_tag((struct tag *) obj);
+
        /* By now, parse_object() would've returned NULL instead. */
-       return objerror(obj, "unknown type '%d' (internal fsck error)", obj->type);
+       return objerror(obj, "unknown type '%d' (internal fsck error)",
+                       obj->type);
 }
 
 /*
@@ -477,6 +488,12 @@ static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
        return 0;
 }
 
+static int fsck_handle_reflog(const char *logname, const unsigned char *sha1, int flag, void *cb_data)
+{
+       for_each_reflog_ent(logname, fsck_handle_reflog_ent, NULL);
+       return 0;
+}
+
 static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 {
        struct object *obj;
@@ -495,14 +512,13 @@ static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int f
        obj->used = 1;
        mark_reachable(obj, REACHABLE);
 
-       for_each_reflog_ent(refname, fsck_handle_reflog_ent, NULL);
-
        return 0;
 }
 
 static void get_default_heads(void)
 {
        for_each_ref(fsck_handle_ref, NULL);
+       for_each_reflog(fsck_handle_reflog, NULL);
 
        /*
         * Not having any default heads isn't really fatal, but
@@ -541,7 +557,7 @@ static int fsck_head_link(void)
 
        if (!head_points_at || !(flag & REF_ISSYMREF))
                return error("HEAD is not a symbolic ref");
-       if (strncmp(head_points_at, "refs/heads/", 11))
+       if (prefixcmp(head_points_at, "refs/heads/"))
                return error("HEAD points to something strange (%s)",
                             head_points_at);
        if (is_null_sha1(sha1))
@@ -571,11 +587,16 @@ static int fsck_cache_tree(struct cache_tree *it)
        return err;
 }
 
+static const char fsck_usage[] =
+"git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] "
+"[--strict] <head-sha1>*]";
+
 int cmd_fsck(int argc, char **argv, const char *prefix)
 {
        int i, heads;
 
        track_object_refs = 1;
+       errors_found = 0;
 
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
@@ -605,7 +626,7 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
                        continue;
                }
                if (*arg == '-')
-                       usage("git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] [--strict] <head-sha1>*]");
+                       usage(fsck_usage);
        }
 
        fsck_head_link();
@@ -627,7 +648,7 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
                        verify_pack(p, 0);
 
                for (p = packed_git; p; p = p->next) {
-                       int num = num_packed_objects(p);
+                       uint32_t i, num = num_packed_objects(p);
                        for (i = 0; i < num; i++) {
                                unsigned char sha1[20];
                                nth_packed_object_sha1(p, i, sha1);
@@ -685,5 +706,5 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
        }
 
        check_connectivity();
-       return 0;
+       return errors_found;
 }