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