summaryrefslogtreecommitdiff
path: root/builtin-count.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-04-27 15:37:18 -0700
committerJunio C Hamano <junkio@cox.net>2006-04-27 21:35:27 -0700
commitc74320872b445104fe5c265e60785d9d26d94cc5 (patch)
treed3ba11f96a423221ddf675bd0ead9c7bd9014b35 /builtin-count.c
parent9a8b6a0a9d4de3d9c1005b872b9b57a213d3e9f8 (diff)
downloadgit-c74320872b445104fe5c265e60785d9d26d94cc5.tar.gz
built-in count-objects.
Also it learned to do -v (verbose) to report: - number of loose objects - disk occupied by loose objects - number of objects in local packs - number of loose objects that are also in pack - unrecognised garbage in .git/objects/??/. Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'builtin-count.c')
-rw-r--r--builtin-count.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/builtin-count.c b/builtin-count.c
new file mode 100644
index 0000000000..0256369d5b
--- /dev/null
+++ b/builtin-count.c
@@ -0,0 +1,123 @@
+/*
+ * Builtin "git count-objects".
+ *
+ * Copyright (c) 2006 Junio C Hamano
+ */
+
+#include "cache.h"
+#include "builtin.h"
+
+static const char count_objects_usage[] = "git-count-objects [-v]";
+
+static void count_objects(DIR *d, char *path, int len, int verbose,
+ unsigned long *loose,
+ unsigned long *loose_size,
+ unsigned long *packed_loose,
+ unsigned long *garbage)
+{
+ struct dirent *ent;
+ while ((ent = readdir(d)) != NULL) {
+ char hex[41];
+ unsigned char sha1[20];
+ const char *cp;
+ int bad = 0;
+
+ if ((ent->d_name[0] == '.') &&
+ (ent->d_name[1] == 0 ||
+ ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))))
+ 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) += st.st_blocks;
+ }
+ if (bad) {
+ if (verbose) {
+ error("garbage found: %.*s/%s",
+ len + 2, path, ent->d_name);
+ (*garbage)++;
+ }
+ 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)++;
+ }
+}
+
+int cmd_count_objects(int ac, const char **av, char **ep)
+{
+ int i;
+ int verbose = 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, garbage = 0;
+ unsigned long loose_size = 0;
+
+ for (i = 1; i < ac; i++) {
+ const char *arg = av[i];
+ if (*arg != '-')
+ break;
+ else if (!strcmp(arg, "-v"))
+ verbose = 1;
+ else
+ usage(count_objects_usage);
+ }
+
+ /* we do not take arguments other than flags for now */
+ if (i < ac)
+ usage(count_objects_usage);
+ 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, &garbage);
+ closedir(d);
+ }
+ if (verbose) {
+ struct packed_git *p;
+ for (p = packed_git; p; p = p->next) {
+ if (!p->pack_local)
+ continue;
+ packed += num_packed_objects(p);
+ }
+ printf("count: %lu\n", loose);
+ printf("size: %lu\n", loose_size / 2);
+ printf("in-pack: %lu\n", packed);
+ printf("prune-packable: %lu\n", packed_loose);
+ printf("garbage: %lu\n", garbage);
+ }
+ else
+ printf("%lu objects, %lu kilobytes\n",
+ loose, loose_size / 2);
+ return 0;
+}