Merge branch 'jk/colors-fix'
[gitweb.git] / builtin / count-objects.c
index a7f70cb858e6574562957b739b8a3d42f0353b40..e47ef0b1af06a1abd63f7818c363db6c859a9bf6 100644 (file)
@@ -11,6 +11,9 @@
 
 static unsigned long garbage;
 static off_t size_garbage;
+static int verbose;
+static unsigned long loose, packed, packed_loose;
+static off_t loose_size;
 
 static void real_report_garbage(const char *desc, const char *path)
 {
@@ -21,61 +24,31 @@ static void real_report_garbage(const char *desc, const char *path)
        garbage++;
 }
 
-static void count_objects(DIR *d, char *path, int len, int verbose,
-                         unsigned long *loose,
-                         off_t *loose_size,
-                         unsigned long *packed_loose)
+static void loose_garbage(const char *path)
 {
-       struct dirent *ent;
-       while ((ent = readdir(d)) != NULL) {
-               char hex[41];
-               unsigned char sha1[20];
-               const char *cp;
-               int bad = 0;
+       if (verbose)
+               report_garbage("garbage found", path);
+}
 
-               if (is_dot_or_dotdot(ent->d_name))
-                       continue;
-               for (cp = ent->d_name; *cp; cp++) {
-                       int ch = *cp;
-                       if (('0' <= ch && ch <= '9') ||
-                           ('a' <= ch && ch <= 'f'))
-                               continue;
-                       bad = 1;
-                       break;
-               }
-               if (cp - ent->d_name != 38)
-                       bad = 1;
-               else {
-                       struct stat st;
-                       memcpy(path + len + 3, ent->d_name, 38);
-                       path[len + 2] = '/';
-                       path[len + 41] = 0;
-                       if (lstat(path, &st) || !S_ISREG(st.st_mode))
-                               bad = 1;
-                       else
-                               (*loose_size) += xsize_t(on_disk_bytes(st));
-               }
-               if (bad) {
-                       if (verbose) {
-                               struct strbuf sb = STRBUF_INIT;
-                               strbuf_addf(&sb, "%.*s/%s",
-                                           len + 2, path, ent->d_name);
-                               report_garbage("garbage found", sb.buf);
-                               strbuf_release(&sb);
-                       }
-                       continue;
-               }
-               (*loose)++;
-               if (!verbose)
-                       continue;
-               memcpy(hex, path+len, 2);
-               memcpy(hex+2, ent->d_name, 38);
-               hex[40] = 0;
-               if (get_sha1_hex(hex, sha1))
-                       die("internal error");
-               if (has_sha1_pack(sha1))
-                       (*packed_loose)++;
+static int count_loose(const unsigned char *sha1, const char *path, void *data)
+{
+       struct stat st;
+
+       if (lstat(path, &st) || !S_ISREG(st.st_mode))
+               loose_garbage(path);
+       else {
+               loose_size += on_disk_bytes(st);
+               loose++;
+               if (verbose && has_sha1_pack(sha1))
+                       packed_loose++;
        }
+       return 0;
+}
+
+static int count_cruft(const char *basename, const char *path, void *data)
+{
+       loose_garbage(path);
+       return 0;
 }
 
 static char const * const count_objects_usage[] = {
@@ -85,12 +58,7 @@ static char const * const count_objects_usage[] = {
 
 int cmd_count_objects(int argc, const char **argv, const char *prefix)
 {
-       int i, verbose = 0, human_readable = 0;
-       const char *objdir = get_object_directory();
-       int len = strlen(objdir);
-       char *path = xmalloc(len + 50);
-       unsigned long loose = 0, packed = 0, packed_loose = 0;
-       off_t loose_size = 0;
+       int human_readable = 0;
        struct option opts[] = {
                OPT__VERBOSE(&verbose, N_("be verbose")),
                OPT_BOOL('H', "human-readable", &human_readable,
@@ -104,19 +72,10 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
                usage_with_options(count_objects_usage, opts);
        if (verbose)
                report_garbage = real_report_garbage;
-       memcpy(path, objdir, len);
-       if (len && objdir[len-1] != '/')
-               path[len++] = '/';
-       for (i = 0; i < 256; i++) {
-               DIR *d;
-               sprintf(path + len, "%02x", i);
-               d = opendir(path);
-               if (!d)
-                       continue;
-               count_objects(d, path, len, verbose,
-                             &loose, &loose_size, &packed_loose);
-               closedir(d);
-       }
+
+       for_each_loose_file_in_objdir(get_object_directory(),
+                                     count_loose, count_cruft, NULL, NULL);
+
        if (verbose) {
                struct packed_git *p;
                unsigned long num_pack = 0;