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>
This commit is contained in:
Jeff King 2014-10-15 18:41:11 -04:00 committed by Junio C Hamano
parent cac05d4dfd
commit 4a1e693a30

View file

@ -11,6 +11,9 @@
static unsigned long garbage; static unsigned long garbage;
static off_t size_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) 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++; garbage++;
} }
static void count_objects(DIR *d, char *path, int len, int verbose, static void loose_garbage(const char *path)
unsigned long *loose,
off_t *loose_size,
unsigned long *packed_loose)
{ {
struct dirent *ent; if (verbose)
while ((ent = readdir(d)) != NULL) { report_garbage("garbage found", path);
char hex[41]; }
unsigned char sha1[20];
const char *cp;
int bad = 0;
if (is_dot_or_dotdot(ent->d_name)) static int count_loose(const unsigned char *sha1, const char *path, void *data)
continue; {
for (cp = ent->d_name; *cp; cp++) { struct stat st;
int ch = *cp;
if (('0' <= ch && ch <= '9') || if (lstat(path, &st) || !S_ISREG(st.st_mode))
('a' <= ch && ch <= 'f')) loose_garbage(path);
continue; else {
bad = 1; loose_size += on_disk_bytes(st);
break; loose++;
} if (verbose && has_sha1_pack(sha1))
if (cp - ent->d_name != 38) packed_loose++;
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) += 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)++;
} }
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[] = { 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 cmd_count_objects(int argc, const char **argv, const char *prefix)
{ {
int i, verbose = 0, human_readable = 0; int 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;
struct option opts[] = { struct option opts[] = {
OPT__VERBOSE(&verbose, N_("be verbose")), OPT__VERBOSE(&verbose, N_("be verbose")),
OPT_BOOL('H', "human-readable", &human_readable, 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); usage_with_options(count_objects_usage, opts);
if (verbose) if (verbose)
report_garbage = real_report_garbage; report_garbage = real_report_garbage;
memcpy(path, objdir, len);
if (len && objdir[len-1] != '/') for_each_loose_file_in_objdir(get_object_directory(),
path[len++] = '/'; count_loose, count_cruft, NULL, NULL);
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);
}
if (verbose) { if (verbose) {
struct packed_git *p; struct packed_git *p;
unsigned long num_pack = 0; unsigned long num_pack = 0;