While it's unusual to have strange files in loose object database,
.git/objects/pack/tmp_* is normal after a broken fetch and they
can eat up a lot of disk space if the user does not pay attention.
Report them.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 The hook in prepare_packed_git_one is ugly, but I don't want to
 duplicate the search file logic there in count-objects. Maybe I'm
 wrong.

 Interestingly it reports .commits file in my repo too. A nice
 reminder to myself to remind Jeff about count-objects improvements
 for his commit-cache work :)

 Way may also need a more friendly format than this one, which I
 assume is plumbing. Something that average git user can understand
 without looking up the document. If "git stats" is too much for this
 purpose, perhaps "git gc --stats"?

 Documentation/git-count-objects.txt |  4 ++--
 builtin/count-objects.c             | 27 ++++++++++++++++++++++++++-
 sha1_file.c                         | 23 ++++++++++++++++++++---
 3 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-count-objects.txt 
b/Documentation/git-count-objects.txt
index e816823..1611d7c 100644
--- a/Documentation/git-count-objects.txt
+++ b/Documentation/git-count-objects.txt
@@ -33,8 +33,8 @@ size-pack: disk space consumed by the packs, in KiB
 prune-packable: the number of loose objects that are also present in
 the packs. These objects could be pruned using `git prune-packed`.
 +
-garbage: the number of files in loose object database that are not
-valid loose objects
+garbage: the number of files in object database that are not valid
+loose objects nor valid packs
 
 GIT
 ---
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 9afaa88..e8fabcf 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -9,6 +9,8 @@
 #include "builtin.h"
 #include "parse-options.h"
 
+static unsigned long garbage;
+
 static void count_objects(DIR *d, char *path, int len, int verbose,
                          unsigned long *loose,
                          off_t *loose_size,
@@ -65,6 +67,27 @@ static void count_objects(DIR *d, char *path, int len, int 
verbose,
        }
 }
 
+extern void (*report_pack_garbage)(const char *path, int len, const char 
*name);
+static void real_report_pack_garbage(const char *path, int len, const char 
*name)
+{
+       if (is_dot_or_dotdot(name))
+               return;
+       if (has_extension(name, ".pack")) {
+               struct strbuf idx_file = STRBUF_INIT;
+               struct stat st;
+
+               strbuf_addf(&idx_file, "%.*s/%.*s.idx", len, path,
+                           (int)strlen(name) - 5, name);
+               if (!stat(idx_file.buf, &st) && S_ISREG(st.st_mode)) {
+                       strbuf_release(&idx_file);
+                       return;
+               }
+               strbuf_release(&idx_file);
+       }
+       error("garbage found: %.*s/%s", len, path, name);
+       garbage++;
+}
+
 static char const * const count_objects_usage[] = {
        N_("git count-objects [-v]"),
        NULL
@@ -76,7 +99,7 @@ int cmd_count_objects(int argc, const char **argv, const char 
*prefix)
        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 = 0, packed = 0, packed_loose = 0;
        off_t loose_size = 0;
        struct option opts[] = {
                OPT__VERBOSE(&verbose, N_("be verbose")),
@@ -87,6 +110,8 @@ int cmd_count_objects(int argc, const char **argv, const 
char *prefix)
        /* we do not take arguments other than flags for now */
        if (argc)
                usage_with_options(count_objects_usage, opts);
+       if (verbose)
+               report_pack_garbage = real_report_pack_garbage;
        memcpy(path, objdir, len);
        if (len && objdir[len-1] != '/')
                path[len++] = '/';
diff --git a/sha1_file.c b/sha1_file.c
index 40b2329..6045946 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1000,6 +1000,17 @@ void install_packed_git(struct packed_git *pack)
        packed_git = pack;
 }
 
+static void dummy_report_pack_garbage(const char *path,
+                                     int len,
+                                     const char *name)
+{
+}
+
+void (*report_pack_garbage)(const char *path,
+                           int len,
+                           const char *name) =
+       dummy_report_pack_garbage;
+
 static void prepare_packed_git_one(char *objdir, int local)
 {
        /* Ensure that this buffer is large enough so that we can
@@ -1024,11 +1035,15 @@ static void prepare_packed_git_one(char *objdir, int 
local)
                int namelen = strlen(de->d_name);
                struct packed_git *p;
 
-               if (!has_extension(de->d_name, ".idx"))
+               if (!has_extension(de->d_name, ".idx")) {
+                       report_pack_garbage(path, len - 1, de->d_name);
                        continue;
+               }
 
-               if (len + namelen + 1 > sizeof(path))
+               if (len + namelen + 1 > sizeof(path)) {
+                       report_pack_garbage(path, len - 1, de->d_name);
                        continue;
+               }
 
                /* Don't reopen a pack we already have. */
                strcpy(path + len, de->d_name);
@@ -1042,8 +1057,10 @@ static void prepare_packed_git_one(char *objdir, int 
local)
                 * .pack file that we can map.
                 */
                p = add_packed_git(path, len + namelen, local);
-               if (!p)
+               if (!p) {
+                       report_pack_garbage(path, len - 1, de->d_name);
                        continue;
+               }
                install_packed_git(p);
        }
        closedir(dir);
-- 
1.8.1.2.536.gf441e6d

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

Reply via email to