summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <junkio@cox.net>2006-04-27 21:38:43 -0700
committerLibravatar Junio C Hamano <junkio@cox.net>2006-04-27 21:38:43 -0700
commitac92095ff2c47731ba9a2a7779cd797b973ffc74 (patch)
treebcefd5a751f8289883965c12858cb6c8b9213782
parentMerge branch 'np/delta' into next (diff)
parentbuilt-in count-objects. (diff)
downloadtgif-ac92095ff2c47731ba9a2a7779cd797b973ffc74.tar.xz
Merge branch 'jc/count' into next
* jc/count: built-in count-objects. pack-objects: update size heuristucs. verify-pack: check integrity in a saner order.
-rw-r--r--Makefile2
-rw-r--r--builtin-count.c123
-rw-r--r--builtin.h1
-rw-r--r--git.c1
-rw-r--r--pack-check.c6
5 files changed, 129 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index d2cc01a265..4416af9bb0 100644
--- a/Makefile
+++ b/Makefile
@@ -214,7 +214,7 @@ LIB_OBJS = \
$(DIFF_OBJS)
BUILTIN_OBJS = \
- builtin-log.o builtin-help.o
+ builtin-log.o builtin-help.o builtin-count.o
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
LIBS = $(GITLIBS) -lz
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;
+}
diff --git a/builtin.h b/builtin.h
index 94dc0732f9..15bb313ee2 100644
--- a/builtin.h
+++ b/builtin.h
@@ -20,5 +20,6 @@ extern int cmd_whatchanged(int argc, const char **argv, char **envp);
extern int cmd_show(int argc, const char **argv, char **envp);
extern int cmd_log(int argc, const char **argv, char **envp);
extern int cmd_format_patch(int argc, const char **argv, char **envp);
+extern int cmd_count_objects(int argc, const char **argv, char **envp);
#endif
diff --git a/git.c b/git.c
index b761150c29..6d030b01cc 100644
--- a/git.c
+++ b/git.c
@@ -47,6 +47,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "whatchanged", cmd_whatchanged },
{ "show", cmd_show },
{ "fmt-patch", cmd_format_patch },
+ { "count-objects", cmd_count_objects },
};
int i;
diff --git a/pack-check.c b/pack-check.c
index 84ed90d369..e57587909e 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -29,12 +29,12 @@ static int verify_packfile(struct packed_git *p)
pack_base = p->pack_base;
SHA1_Update(&ctx, pack_base, pack_size - 20);
SHA1_Final(sha1, &ctx);
- if (memcmp(sha1, index_base + index_size - 40, 20))
- return error("Packfile %s SHA1 mismatch with idx",
- p->pack_name);
if (memcmp(sha1, pack_base + pack_size - 20, 20))
return error("Packfile %s SHA1 mismatch with itself",
p->pack_name);
+ if (memcmp(sha1, index_base + index_size - 40, 20))
+ return error("Packfile %s SHA1 mismatch with idx",
+ p->pack_name);
/* Make sure everything reachable from idx is valid. Since we
* have verified that nr_objects matches between idx and pack,