builtin / count-objects.con commit worktree: fix "add -B" (0ebf4a2)
   1/*
   2 * Builtin "git count-objects".
   3 *
   4 * Copyright (c) 2006 Junio C Hamano
   5 */
   6
   7#include "cache.h"
   8#include "dir.h"
   9#include "builtin.h"
  10#include "parse-options.h"
  11
  12static unsigned long garbage;
  13static off_t size_garbage;
  14static int verbose;
  15static unsigned long loose, packed, packed_loose;
  16static off_t loose_size;
  17
  18static const char *bits_to_msg(unsigned seen_bits)
  19{
  20        switch (seen_bits) {
  21        case 0:
  22                return "no corresponding .idx or .pack";
  23        case PACKDIR_FILE_GARBAGE:
  24                return "garbage found";
  25        case PACKDIR_FILE_PACK:
  26                return "no corresponding .idx";
  27        case PACKDIR_FILE_IDX:
  28                return "no corresponding .pack";
  29        case PACKDIR_FILE_PACK|PACKDIR_FILE_IDX:
  30        default:
  31                return NULL;
  32        }
  33}
  34
  35static void real_report_garbage(unsigned seen_bits, const char *path)
  36{
  37        struct stat st;
  38        const char *desc = bits_to_msg(seen_bits);
  39
  40        if (!desc)
  41                return;
  42
  43        if (!stat(path, &st))
  44                size_garbage += st.st_size;
  45        warning("%s: %s", desc, path);
  46        garbage++;
  47}
  48
  49static void loose_garbage(const char *path)
  50{
  51        if (verbose)
  52                report_garbage(PACKDIR_FILE_GARBAGE, path);
  53}
  54
  55static int count_loose(const unsigned char *sha1, const char *path, void *data)
  56{
  57        struct stat st;
  58
  59        if (lstat(path, &st) || !S_ISREG(st.st_mode))
  60                loose_garbage(path);
  61        else {
  62                loose_size += on_disk_bytes(st);
  63                loose++;
  64                if (verbose && has_sha1_pack(sha1))
  65                        packed_loose++;
  66        }
  67        return 0;
  68}
  69
  70static int count_cruft(const char *basename, const char *path, void *data)
  71{
  72        loose_garbage(path);
  73        return 0;
  74}
  75
  76static char const * const count_objects_usage[] = {
  77        N_("git count-objects [-v] [-H | --human-readable]"),
  78        NULL
  79};
  80
  81int cmd_count_objects(int argc, const char **argv, const char *prefix)
  82{
  83        int human_readable = 0;
  84        struct option opts[] = {
  85                OPT__VERBOSE(&verbose, N_("be verbose")),
  86                OPT_BOOL('H', "human-readable", &human_readable,
  87                         N_("print sizes in human readable format")),
  88                OPT_END(),
  89        };
  90
  91        argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);
  92        /* we do not take arguments other than flags for now */
  93        if (argc)
  94                usage_with_options(count_objects_usage, opts);
  95        if (verbose) {
  96                report_garbage = real_report_garbage;
  97                report_linked_checkout_garbage();
  98        }
  99
 100        for_each_loose_file_in_objdir(get_object_directory(),
 101                                      count_loose, count_cruft, NULL, NULL);
 102
 103        if (verbose) {
 104                struct packed_git *p;
 105                unsigned long num_pack = 0;
 106                off_t size_pack = 0;
 107                struct strbuf loose_buf = STRBUF_INIT;
 108                struct strbuf pack_buf = STRBUF_INIT;
 109                struct strbuf garbage_buf = STRBUF_INIT;
 110                if (!packed_git)
 111                        prepare_packed_git();
 112                for (p = packed_git; p; p = p->next) {
 113                        if (!p->pack_local)
 114                                continue;
 115                        if (open_pack_index(p))
 116                                continue;
 117                        packed += p->num_objects;
 118                        size_pack += p->pack_size + p->index_size;
 119                        num_pack++;
 120                }
 121
 122                if (human_readable) {
 123                        strbuf_humanise_bytes(&loose_buf, loose_size);
 124                        strbuf_humanise_bytes(&pack_buf, size_pack);
 125                        strbuf_humanise_bytes(&garbage_buf, size_garbage);
 126                } else {
 127                        strbuf_addf(&loose_buf, "%lu",
 128                                    (unsigned long)(loose_size / 1024));
 129                        strbuf_addf(&pack_buf, "%lu",
 130                                    (unsigned long)(size_pack / 1024));
 131                        strbuf_addf(&garbage_buf, "%lu",
 132                                    (unsigned long)(size_garbage / 1024));
 133                }
 134
 135                printf("count: %lu\n", loose);
 136                printf("size: %s\n", loose_buf.buf);
 137                printf("in-pack: %lu\n", packed);
 138                printf("packs: %lu\n", num_pack);
 139                printf("size-pack: %s\n", pack_buf.buf);
 140                printf("prune-packable: %lu\n", packed_loose);
 141                printf("garbage: %lu\n", garbage);
 142                printf("size-garbage: %s\n", garbage_buf.buf);
 143                strbuf_release(&loose_buf);
 144                strbuf_release(&pack_buf);
 145                strbuf_release(&garbage_buf);
 146        } else {
 147                struct strbuf buf = STRBUF_INIT;
 148                if (human_readable)
 149                        strbuf_humanise_bytes(&buf, loose_size);
 150                else
 151                        strbuf_addf(&buf, "%lu kilobytes",
 152                                    (unsigned long)(loose_size / 1024));
 153                printf("%lu objects, %s\n", loose, buf.buf);
 154                strbuf_release(&buf);
 155        }
 156        return 0;
 157}