aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-count-objects.txt12
-rw-r--r--Makefile6
-rw-r--r--builtin-count.c125
-rw-r--r--builtin.h1
-rwxr-xr-xgit-count-objects.sh31
-rw-r--r--git.c1
6 files changed, 141 insertions, 35 deletions
diff --git a/Documentation/git-count-objects.txt b/Documentation/git-count-objects.txt
index 47216f488..198ce77a8 100644
--- a/Documentation/git-count-objects.txt
+++ b/Documentation/git-count-objects.txt
@@ -7,13 +7,23 @@ git-count-objects - Reports on unpacked objects
SYNOPSIS
--------
-'git-count-objects'
+'git-count-objects' [-v]
DESCRIPTION
-----------
This counts the number of unpacked object files and disk space consumed by
them, to help you decide when it is a good time to repack.
+
+OPTIONS
+-------
+-v::
+ In addition to the number of loose objects and disk
+ space consumed, it reports the number of in-pack
+ objects, and number of objects that can be removed by
+ running `git-prune-packed`.
+
+
Author
------
Written by Junio C Hamano <junkio@cox.net>
diff --git a/Makefile b/Makefile
index 9cb40a816..67559c9f4 100644
--- a/Makefile
+++ b/Makefile
@@ -115,7 +115,7 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
SCRIPT_SH = \
git-add.sh git-bisect.sh git-branch.sh git-checkout.sh \
git-cherry.sh git-clean.sh git-clone.sh git-commit.sh \
- git-count-objects.sh git-diff.sh git-fetch.sh \
+ git-diff.sh git-fetch.sh \
git-format-patch.sh git-ls-remote.sh \
git-merge-one-file.sh git-parse-remote.sh \
git-prune.sh git-pull.sh git-rebase.sh \
@@ -168,7 +168,7 @@ PROGRAMS = \
git-describe$X git-merge-tree$X git-blame$X git-imap-send$X
BUILT_INS = git-log$X \
- git-push$X
+ git-count-objects$X git-push$X
# what 'all' will build and 'install' will install, in gitexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
@@ -215,7 +215,7 @@ LIB_OBJS = \
$(DIFF_OBJS)
BUILTIN_OBJS = \
- builtin-log.o builtin-help.o builtin-push.o
+ builtin-log.o builtin-help.o builtin-count.o builtin-push.o
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
LIBS = $(GITLIBS) -lz
diff --git a/builtin-count.c b/builtin-count.c
new file mode 100644
index 000000000..5ee72df24
--- /dev/null
+++ b/builtin-count.c
@@ -0,0 +1,125 @@
+/*
+ * 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;
+ if (!packed_git)
+ prepare_packed_git();
+ 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 94fa9b546..dca69632d 100644
--- a/builtin.h
+++ b/builtin.h
@@ -19,6 +19,7 @@ extern int cmd_version(int argc, const char **argv, char **envp);
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);
extern int cmd_push(int argc, const char **argv, char **envp);
diff --git a/git-count-objects.sh b/git-count-objects.sh
deleted file mode 100755
index 40c58efe0..000000000
--- a/git-count-objects.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Junio C Hamano
-#
-
-GIT_DIR=`git-rev-parse --git-dir` || exit $?
-
-dc </dev/null 2>/dev/null || {
- # This is not a real DC at all -- it just knows how
- # this script feeds DC and does the computation itself.
- dc () {
- while read a b
- do
- case $a,$b in
- 0,) acc=0 ;;
- *,+) acc=$(($acc + $a)) ;;
- p,) echo "$acc" ;;
- esac
- done
- }
-}
-
-echo $(find "$GIT_DIR/objects"/?? -type f -print 2>/dev/null | wc -l) objects, \
-$({
- echo 0
- # "no-such" is to help Darwin folks by not using xargs -r.
- find "$GIT_DIR/objects"/?? -type f -print 2>/dev/null |
- xargs du -k "$GIT_DIR/objects/no-such" 2>/dev/null |
- sed -e 's/[ ].*/ +/'
- echo p
-} | dc) kilobytes
diff --git a/git.c b/git.c
index fd479e97c..4d3a5a30a 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 },
{ "push", cmd_push },
+ { "count-objects", cmd_count_objects },
};
int i;