Re: [PATCH] C version of git-count-objects

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Peter Hagervall <hager@xxxxxxxxx> writes:

> Thanks, I'll make a third stab at it tomorrow, if anyone is interested
> that is?

How about something like this instead?

-- >8 --

 Makefile        |    2 -
 builtin-count.c |  124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 builtin.h       |    1 
 git.c           |    1 
 4 files changed, 127 insertions(+), 1 deletions(-)

diff --git a/Makefile b/Makefile
index 8ce27a6..14193aa 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 0000000..cbbb7dd
--- /dev/null
+++ b/builtin-count.c
@@ -0,0 +1,124 @@
+/*
+ * Builtin "git count-objects".
+ *
+ * Copyright (c) 2006 Junio C Hamano
+ */
+
+#include "cache.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 (stat(path, &st)) {
+				die("OOPS <%s>", path);
+				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 47408a0..76169e3 100644
--- a/builtin.h
+++ b/builtin.h
@@ -19,5 +19,6 @@ extern int cmd_version(int argc, const c
 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_count_objects(int argc, const char **argv, char **envp);
 
 #endif
diff --git a/git.c b/git.c
index 01b7e28..00fb399 100644
--- a/git.c
+++ b/git.c
@@ -46,6 +46,7 @@ static void handle_internal_command(int 
 		{ "log", cmd_log },
 		{ "whatchanged", cmd_whatchanged },
 		{ "show", cmd_show },
+		{ "count-objects", cmd_count_objects },
 	};
 	int i;
 

-
: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]