count-objects: use for_each_loose_file_in_objdir

This drops our line count considerably, and should make things more readable by keeping the counting logic separate from the traversal. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Oct 15, 2014 at 18:41 UTC 4a1e693a30c816fa5293c5f9e83e1e98ee87584e
1 file changed +30 -71
builtin/count-objects.c
+30 -71
@@ -11,6 +11,9 @@
11
12 static unsigned long garbage;
13 static off_t size_garbage;
14 +static int verbose;
15 +static unsigned long loose, packed, packed_loose;
16 +static off_t loose_size;
17
18 static void real_report_garbage(const char *desc, const char *path)
19 {
@@ -21,61 +24,31 @@ static void real_report_garbage(const char *desc, const char *path)
24 garbage++;
25 }
26
24 -static void count_objects(DIR *d, char *path, int len, int verbose,
25 - unsigned long *loose,
26 - off_t *loose_size,
27 - unsigned long *packed_loose)
27 +static void loose_garbage(const char *path)
28 {
29 - struct dirent *ent;
30 - while ((ent = readdir(d)) != NULL) {
31 - char hex[41];
32 - unsigned char sha1[20];
33 - const char *cp;
34 - int bad = 0;
29 + if (verbose)
30 + report_garbage("garbage found", path);
31 +}
32
36 - if (is_dot_or_dotdot(ent->d_name))
37 - continue;
38 - for (cp = ent->d_name; *cp; cp++) {
39 - int ch = *cp;
40 - if (('0' <= ch && ch <= '9') ||
41 - ('a' <= ch && ch <= 'f'))
42 - continue;
43 - bad = 1;
44 - break;
45 - }
46 - if (cp - ent->d_name != 38)
47 - bad = 1;
48 - else {
49 - struct stat st;
50 - memcpy(path + len + 3, ent->d_name, 38);
51 - path[len + 2] = '/';
52 - path[len + 41] = 0;
53 - if (lstat(path, &st) || !S_ISREG(st.st_mode))
54 - bad = 1;
55 - else
56 - (*loose_size) += on_disk_bytes(st);
57 - }
58 - if (bad) {
59 - if (verbose) {
60 - struct strbuf sb = STRBUF_INIT;
61 - strbuf_addf(&sb, "%.*s/%s",
62 - len + 2, path, ent->d_name);
63 - report_garbage("garbage found", sb.buf);
64 - strbuf_release(&sb);
65 - }
66 - continue;
67 - }
68 - (*loose)++;
69 - if (!verbose)
70 - continue;
71 - memcpy(hex, path+len, 2);
72 - memcpy(hex+2, ent->d_name, 38);
73 - hex[40] = 0;
74 - if (get_sha1_hex(hex, sha1))
75 - die("internal error");
76 - if (has_sha1_pack(sha1))
77 - (*packed_loose)++;
33 +static int count_loose(const unsigned char *sha1, const char *path, void *data)
34 +{
35 + struct stat st;
36 +
37 + if (lstat(path, &st) || !S_ISREG(st.st_mode))
38 + loose_garbage(path);
39 + else {
40 + loose_size += on_disk_bytes(st);
41 + loose++;
42 + if (verbose && has_sha1_pack(sha1))
43 + packed_loose++;
44 }
45 + return 0;
46 +}
47 +
48 +static int count_cruft(const char *basename, const char *path, void *data)
49 +{
50 + loose_garbage(path);
51 + return 0;
52 }
53
54 static char const * const count_objects_usage[] = {
@@ -85,12 +58,7 @@ static char const * const count_objects_usage[] = {
58
59 int cmd_count_objects(int argc, const char **argv, const char *prefix)
60 {
88 - int i, verbose = 0, human_readable = 0;
89 - const char *objdir = get_object_directory();
90 - int len = strlen(objdir);
91 - char *path = xmalloc(len + 50);
92 - unsigned long loose = 0, packed = 0, packed_loose = 0;
93 - off_t loose_size = 0;
61 + int human_readable = 0;
62 struct option opts[] = {
63 OPT__VERBOSE(&verbose, N_("be verbose")),
64 OPT_BOOL('H', "human-readable", &human_readable,
@@ -104,19 +72,10 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
72 usage_with_options(count_objects_usage, opts);
73 if (verbose)
74 report_garbage = real_report_garbage;
107 - memcpy(path, objdir, len);
108 - if (len && objdir[len-1] != '/')
109 - path[len++] = '/';
110 - for (i = 0; i < 256; i++) {
111 - DIR *d;
112 - sprintf(path + len, "%02x", i);
113 - d = opendir(path);
114 - if (!d)
115 - continue;
116 - count_objects(d, path, len, verbose,
117 - &loose, &loose_size, &packed_loose);
118 - closedir(d);
119 - }
75 +
76 + for_each_loose_file_in_objdir(get_object_directory(),
77 + count_loose, count_cruft, NULL, NULL);
78 +
79 if (verbose) {
80 struct packed_git *p;
81 unsigned long num_pack = 0;