builtin-count-objects.con commit diff --cumulative is a sub-option of --dirstat (f88d225)
   1/*
   2 * Builtin "git count-objects".
   3 *
   4 * Copyright (c) 2006 Junio C Hamano
   5 */
   6
   7#include "cache.h"
   8#include "builtin.h"
   9#include "parse-options.h"
  10
  11static void count_objects(DIR *d, char *path, int len, int verbose,
  12                          unsigned long *loose,
  13                          unsigned long *loose_size,
  14                          unsigned long *packed_loose,
  15                          unsigned long *garbage)
  16{
  17        struct dirent *ent;
  18        while ((ent = readdir(d)) != NULL) {
  19                char hex[41];
  20                unsigned char sha1[20];
  21                const char *cp;
  22                int bad = 0;
  23
  24                if ((ent->d_name[0] == '.') &&
  25                    (ent->d_name[1] == 0 ||
  26                     ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))))
  27                        continue;
  28                for (cp = ent->d_name; *cp; cp++) {
  29                        int ch = *cp;
  30                        if (('0' <= ch && ch <= '9') ||
  31                            ('a' <= ch && ch <= 'f'))
  32                                continue;
  33                        bad = 1;
  34                        break;
  35                }
  36                if (cp - ent->d_name != 38)
  37                        bad = 1;
  38                else {
  39                        struct stat st;
  40                        memcpy(path + len + 3, ent->d_name, 38);
  41                        path[len + 2] = '/';
  42                        path[len + 41] = 0;
  43                        if (lstat(path, &st) || !S_ISREG(st.st_mode))
  44                                bad = 1;
  45                        else
  46                                (*loose_size) += xsize_t(st.st_blocks);
  47                }
  48                if (bad) {
  49                        if (verbose) {
  50                                error("garbage found: %.*s/%s",
  51                                      len + 2, path, ent->d_name);
  52                                (*garbage)++;
  53                        }
  54                        continue;
  55                }
  56                (*loose)++;
  57                if (!verbose)
  58                        continue;
  59                memcpy(hex, path+len, 2);
  60                memcpy(hex+2, ent->d_name, 38);
  61                hex[40] = 0;
  62                if (get_sha1_hex(hex, sha1))
  63                        die("internal error");
  64                if (has_sha1_pack(sha1, NULL))
  65                        (*packed_loose)++;
  66        }
  67}
  68
  69static char const * const count_objects_usage[] = {
  70        "git count-objects [-v]",
  71        NULL
  72};
  73
  74int cmd_count_objects(int argc, const char **argv, const char *prefix)
  75{
  76        int i, verbose = 0;
  77        const char *objdir = get_object_directory();
  78        int len = strlen(objdir);
  79        char *path = xmalloc(len + 50);
  80        unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
  81        unsigned long loose_size = 0;
  82        struct option opts[] = {
  83                OPT__VERBOSE(&verbose),
  84                OPT_END(),
  85        };
  86
  87        argc = parse_options(argc, argv, opts, count_objects_usage, 0);
  88        /* we do not take arguments other than flags for now */
  89        if (argc)
  90                usage_with_options(count_objects_usage, opts);
  91        memcpy(path, objdir, len);
  92        if (len && objdir[len-1] != '/')
  93                path[len++] = '/';
  94        for (i = 0; i < 256; i++) {
  95                DIR *d;
  96                sprintf(path + len, "%02x", i);
  97                d = opendir(path);
  98                if (!d)
  99                        continue;
 100                count_objects(d, path, len, verbose,
 101                              &loose, &loose_size, &packed_loose, &garbage);
 102                closedir(d);
 103        }
 104        if (verbose) {
 105                struct packed_git *p;
 106                unsigned long num_pack = 0;
 107                if (!packed_git)
 108                        prepare_packed_git();
 109                for (p = packed_git; p; p = p->next) {
 110                        if (!p->pack_local)
 111                                continue;
 112                        if (open_pack_index(p))
 113                                continue;
 114                        packed += p->num_objects;
 115                        num_pack++;
 116                }
 117                printf("count: %lu\n", loose);
 118                printf("size: %lu\n", loose_size / 2);
 119                printf("in-pack: %lu\n", packed);
 120                printf("packs: %lu\n", num_pack);
 121                printf("prune-packable: %lu\n", packed_loose);
 122                printf("garbage: %lu\n", garbage);
 123        }
 124        else
 125                printf("%lu objects, %lu kilobytes\n",
 126                       loose, loose_size / 2);
 127        return 0;
 128}