James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 1 | /* |
| 2 | * git gc builtin command |
| 3 | * |
| 4 | * Cleanup unreachable files and optimize the repository. |
| 5 | * |
| 6 | * Copyright (c) 2007 James Bowes |
| 7 | * |
| 8 | * Based on git-gc.sh, which is |
| 9 | * |
| 10 | * Copyright (c) 2006 Shawn O. Pearce |
| 11 | */ |
| 12 | |
Peter Hagervall | baffc0e | 2007-07-15 01:14:45 +0200 | [diff] [blame] | 13 | #include "builtin.h" |
Stefan Beller | a80d72d | 2018-03-23 18:20:59 +0100 | [diff] [blame] | 14 | #include "repository.h" |
Brandon Williams | b2141fc | 2017-06-14 11:07:36 -0700 | [diff] [blame] | 15 | #include "config.h" |
Michael Haggerty | ebebeae | 2015-08-10 11:47:49 +0200 | [diff] [blame] | 16 | #include "tempfile.h" |
Michael Haggerty | 697cc8e | 2014-10-01 12:28:42 +0200 | [diff] [blame] | 17 | #include "lockfile.h" |
James Bowes | 44c637c | 2007-11-01 21:02:27 -0400 | [diff] [blame] | 18 | #include "parse-options.h" |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 19 | #include "run-command.h" |
Jonathan Nieder | 4c5baf0 | 2013-10-16 16:11:46 -0700 | [diff] [blame] | 20 | #include "sigchain.h" |
Jeff King | dbbcd44 | 2020-07-28 16:23:39 -0400 | [diff] [blame] | 21 | #include "strvec.h" |
Nguyễn Thái Ngọc Duy | eab3296 | 2013-12-05 20:02:54 +0700 | [diff] [blame] | 22 | #include "commit.h" |
Derrick Stolee | d5d5d7b | 2018-06-27 09:24:46 -0400 | [diff] [blame] | 23 | #include "commit-graph.h" |
Jonathan Tan | 0abe14f | 2017-08-18 15:20:26 -0700 | [diff] [blame] | 24 | #include "packfile.h" |
Stefan Beller | a80d72d | 2018-03-23 18:20:59 +0100 | [diff] [blame] | 25 | #include "object-store.h" |
Nguyễn Thái Ngọc Duy | 9806f5a | 2018-04-15 17:36:17 +0200 | [diff] [blame] | 26 | #include "pack.h" |
| 27 | #include "pack-objects.h" |
| 28 | #include "blob.h" |
| 29 | #include "tree.h" |
Christian Couder | b14ed5a | 2019-06-25 15:40:31 +0200 | [diff] [blame] | 30 | #include "promisor-remote.h" |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 31 | |
| 32 | #define FAILED_RUN "failed to run %s" |
| 33 | |
James Bowes | 44c637c | 2007-11-01 21:02:27 -0400 | [diff] [blame] | 34 | static const char * const builtin_gc_usage[] = { |
Alex Henrie | 9c9b4f2 | 2015-01-13 00:44:47 -0700 | [diff] [blame] | 35 | N_("git gc [<options>]"), |
James Bowes | 44c637c | 2007-11-01 21:02:27 -0400 | [diff] [blame] | 36 | NULL |
| 37 | }; |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 38 | |
Linus Torvalds | 5675239 | 2007-05-24 11:41:39 -0700 | [diff] [blame] | 39 | static int pack_refs = 1; |
Nguyễn Thái Ngọc Duy | 62aad18 | 2014-05-25 07:38:29 +0700 | [diff] [blame] | 40 | static int prune_reflogs = 1; |
Jeff King | 07e7dbf | 2016-08-11 12:13:09 -0400 | [diff] [blame] | 41 | static int aggressive_depth = 50; |
Johannes Schindelin | 1c192f3 | 2007-12-06 12:03:38 +0000 | [diff] [blame] | 42 | static int aggressive_window = 250; |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 43 | static int gc_auto_threshold = 6700; |
Junio C Hamano | 9706397 | 2008-03-23 00:04:48 -0700 | [diff] [blame] | 44 | static int gc_auto_pack_limit = 50; |
Nguyễn Thái Ngọc Duy | 9f673f9 | 2014-02-08 14:08:52 +0700 | [diff] [blame] | 45 | static int detach_auto = 1; |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 46 | static timestamp_t gc_log_expire_time; |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 47 | static const char *gc_log_expire = "1.day.ago"; |
David Bryson | d3154b4 | 2008-09-30 13:28:58 -0700 | [diff] [blame] | 48 | static const char *prune_expire = "2.weeks.ago"; |
Nguyễn Thái Ngọc Duy | e3df33b | 2014-11-30 15:24:53 +0700 | [diff] [blame] | 49 | static const char *prune_worktrees_expire = "3.months.ago"; |
Nguyễn Thái Ngọc Duy | 55dfe13 | 2018-04-15 17:36:15 +0200 | [diff] [blame] | 50 | static unsigned long big_pack_threshold; |
Nguyễn Thái Ngọc Duy | 9806f5a | 2018-04-15 17:36:17 +0200 | [diff] [blame] | 51 | static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE; |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 52 | |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 53 | static struct strvec pack_refs_cmd = STRVEC_INIT; |
| 54 | static struct strvec reflog = STRVEC_INIT; |
| 55 | static struct strvec repack = STRVEC_INIT; |
| 56 | static struct strvec prune = STRVEC_INIT; |
| 57 | static struct strvec prune_worktrees = STRVEC_INIT; |
| 58 | static struct strvec rerere = STRVEC_INIT; |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 59 | |
Jeff King | 076aa2c | 2017-09-05 08:15:08 -0400 | [diff] [blame] | 60 | static struct tempfile *pidfile; |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 61 | static struct lock_file log_lock; |
Jonathan Nieder | 4c5baf0 | 2013-10-16 16:11:46 -0700 | [diff] [blame] | 62 | |
Doug Kelly | 478f34d | 2015-11-03 21:05:08 -0600 | [diff] [blame] | 63 | static struct string_list pack_garbage = STRING_LIST_INIT_DUP; |
| 64 | |
| 65 | static void clean_pack_garbage(void) |
| 66 | { |
| 67 | int i; |
| 68 | for (i = 0; i < pack_garbage.nr; i++) |
| 69 | unlink_or_warn(pack_garbage.items[i].string); |
| 70 | string_list_clear(&pack_garbage, 0); |
| 71 | } |
| 72 | |
| 73 | static void report_pack_garbage(unsigned seen_bits, const char *path) |
| 74 | { |
| 75 | if (seen_bits == PACKDIR_FILE_IDX) |
| 76 | string_list_append(&pack_garbage, path); |
| 77 | } |
| 78 | |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 79 | static void process_log_file(void) |
| 80 | { |
| 81 | struct stat st; |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 82 | if (fstat(get_lock_file_fd(&log_lock), &st)) { |
| 83 | /* |
| 84 | * Perhaps there was an i/o error or another |
| 85 | * unlikely situation. Try to make a note of |
| 86 | * this in gc.log along with any existing |
| 87 | * messages. |
| 88 | */ |
| 89 | int saved_errno = errno; |
| 90 | fprintf(stderr, _("Failed to fstat %s: %s"), |
Jeff King | 076aa2c | 2017-09-05 08:15:08 -0400 | [diff] [blame] | 91 | get_tempfile_path(log_lock.tempfile), |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 92 | strerror(saved_errno)); |
| 93 | fflush(stderr); |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 94 | commit_lock_file(&log_lock); |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 95 | errno = saved_errno; |
| 96 | } else if (st.st_size) { |
| 97 | /* There was some error recorded in the lock file */ |
| 98 | commit_lock_file(&log_lock); |
| 99 | } else { |
| 100 | /* No error, clean up any old gc.log */ |
| 101 | unlink(git_path("gc.log")); |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 102 | rollback_lock_file(&log_lock); |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 103 | } |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | static void process_log_file_at_exit(void) |
| 107 | { |
| 108 | fflush(stderr); |
| 109 | process_log_file(); |
| 110 | } |
| 111 | |
| 112 | static void process_log_file_on_signal(int signo) |
| 113 | { |
| 114 | process_log_file(); |
| 115 | sigchain_pop(signo); |
| 116 | raise(signo); |
| 117 | } |
| 118 | |
Ævar Arnfjörð Bjarmason | bf3d70f | 2019-03-28 17:14:34 +0100 | [diff] [blame] | 119 | static int gc_config_is_timestamp_never(const char *var) |
| 120 | { |
| 121 | const char *value; |
| 122 | timestamp_t expire; |
| 123 | |
| 124 | if (!git_config_get_value(var, &value) && value) { |
| 125 | if (parse_expiry_date(value, &expire)) |
| 126 | die(_("failed to parse '%s' value '%s'"), var, value); |
| 127 | return expire == 0; |
| 128 | } |
| 129 | return 0; |
| 130 | } |
| 131 | |
Tanay Abhra | 5801d3b | 2014-08-07 09:21:22 -0700 | [diff] [blame] | 132 | static void gc_config(void) |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 133 | { |
Tanay Abhra | 5801d3b | 2014-08-07 09:21:22 -0700 | [diff] [blame] | 134 | const char *value; |
| 135 | |
| 136 | if (!git_config_get_value("gc.packrefs", &value)) { |
Miklos Vajna | c5e5a2c | 2008-02-08 15:26:18 +0100 | [diff] [blame] | 137 | if (value && !strcmp(value, "notbare")) |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 138 | pack_refs = -1; |
| 139 | else |
Tanay Abhra | 5801d3b | 2014-08-07 09:21:22 -0700 | [diff] [blame] | 140 | pack_refs = git_config_bool("gc.packrefs", value); |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 141 | } |
Tanay Abhra | 5801d3b | 2014-08-07 09:21:22 -0700 | [diff] [blame] | 142 | |
Ævar Arnfjörð Bjarmason | bf3d70f | 2019-03-28 17:14:34 +0100 | [diff] [blame] | 143 | if (gc_config_is_timestamp_never("gc.reflogexpire") && |
| 144 | gc_config_is_timestamp_never("gc.reflogexpireunreachable")) |
| 145 | prune_reflogs = 0; |
| 146 | |
Tanay Abhra | 5801d3b | 2014-08-07 09:21:22 -0700 | [diff] [blame] | 147 | git_config_get_int("gc.aggressivewindow", &aggressive_window); |
| 148 | git_config_get_int("gc.aggressivedepth", &aggressive_depth); |
| 149 | git_config_get_int("gc.auto", &gc_auto_threshold); |
| 150 | git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit); |
| 151 | git_config_get_bool("gc.autodetach", &detach_auto); |
Christian Couder | 77d6797 | 2017-02-27 19:00:13 +0100 | [diff] [blame] | 152 | git_config_get_expiry("gc.pruneexpire", &prune_expire); |
| 153 | git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire); |
Junio C Hamano | 94c9b5a | 2017-03-17 13:50:23 -0700 | [diff] [blame] | 154 | git_config_get_expiry("gc.logexpiry", &gc_log_expire); |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 155 | |
Nguyễn Thái Ngọc Duy | 55dfe13 | 2018-04-15 17:36:15 +0200 | [diff] [blame] | 156 | git_config_get_ulong("gc.bigpackthreshold", &big_pack_threshold); |
Nguyễn Thái Ngọc Duy | 9806f5a | 2018-04-15 17:36:17 +0200 | [diff] [blame] | 157 | git_config_get_ulong("pack.deltacachesize", &max_delta_cache_size); |
Nguyễn Thái Ngọc Duy | 55dfe13 | 2018-04-15 17:36:15 +0200 | [diff] [blame] | 158 | |
Tanay Abhra | 5801d3b | 2014-08-07 09:21:22 -0700 | [diff] [blame] | 159 | git_config(git_default_config, NULL); |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 160 | } |
| 161 | |
Junio C Hamano | a087cc9 | 2007-09-17 00:44:17 -0700 | [diff] [blame] | 162 | static int too_many_loose_objects(void) |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 163 | { |
| 164 | /* |
| 165 | * Quickly check if a "gc" is needed, by estimating how |
| 166 | * many loose objects there are. Because SHA-1 is evenly |
| 167 | * distributed, we can check only one and get a reasonable |
| 168 | * estimate. |
| 169 | */ |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 170 | DIR *dir; |
| 171 | struct dirent *ent; |
| 172 | int auto_threshold; |
| 173 | int num_loose = 0; |
| 174 | int needed = 0; |
Ævar Arnfjörð Bjarmason | e5cdbd5 | 2019-03-15 16:59:53 +0100 | [diff] [blame] | 175 | const unsigned hexsz_loose = the_hash_algo->hexsz - 2; |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 176 | |
Jeff King | 07af889 | 2017-03-28 15:47:03 -0400 | [diff] [blame] | 177 | dir = opendir(git_path("objects/17")); |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 178 | if (!dir) |
| 179 | return 0; |
| 180 | |
René Scharfe | 42c78a2 | 2017-07-08 12:35:35 +0200 | [diff] [blame] | 181 | auto_threshold = DIV_ROUND_UP(gc_auto_threshold, 256); |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 182 | while ((ent = readdir(dir)) != NULL) { |
Ævar Arnfjörð Bjarmason | e5cdbd5 | 2019-03-15 16:59:53 +0100 | [diff] [blame] | 183 | if (strspn(ent->d_name, "0123456789abcdef") != hexsz_loose || |
| 184 | ent->d_name[hexsz_loose] != '\0') |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 185 | continue; |
| 186 | if (++num_loose > auto_threshold) { |
| 187 | needed = 1; |
| 188 | break; |
| 189 | } |
| 190 | } |
| 191 | closedir(dir); |
| 192 | return needed; |
| 193 | } |
| 194 | |
Nguyễn Thái Ngọc Duy | 9806f5a | 2018-04-15 17:36:17 +0200 | [diff] [blame] | 195 | static struct packed_git *find_base_packs(struct string_list *packs, |
| 196 | unsigned long limit) |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 197 | { |
| 198 | struct packed_git *p, *base = NULL; |
| 199 | |
Derrick Stolee | 454ea2e | 2018-08-20 16:52:04 +0000 | [diff] [blame] | 200 | for (p = get_all_packs(the_repository); p; p = p->next) { |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 201 | if (!p->pack_local) |
| 202 | continue; |
Nguyễn Thái Ngọc Duy | 55dfe13 | 2018-04-15 17:36:15 +0200 | [diff] [blame] | 203 | if (limit) { |
| 204 | if (p->pack_size >= limit) |
| 205 | string_list_append(packs, p->pack_name); |
| 206 | } else if (!base || base->pack_size < p->pack_size) { |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 207 | base = p; |
| 208 | } |
| 209 | } |
| 210 | |
| 211 | if (base) |
| 212 | string_list_append(packs, base->pack_name); |
Nguyễn Thái Ngọc Duy | 9806f5a | 2018-04-15 17:36:17 +0200 | [diff] [blame] | 213 | |
| 214 | return base; |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 215 | } |
| 216 | |
Junio C Hamano | 1781550 | 2007-09-17 00:55:13 -0700 | [diff] [blame] | 217 | static int too_many_packs(void) |
| 218 | { |
| 219 | struct packed_git *p; |
| 220 | int cnt; |
| 221 | |
| 222 | if (gc_auto_pack_limit <= 0) |
| 223 | return 0; |
| 224 | |
Derrick Stolee | 454ea2e | 2018-08-20 16:52:04 +0000 | [diff] [blame] | 225 | for (cnt = 0, p = get_all_packs(the_repository); p; p = p->next) { |
Junio C Hamano | 1781550 | 2007-09-17 00:55:13 -0700 | [diff] [blame] | 226 | if (!p->pack_local) |
| 227 | continue; |
Brandon Casey | 01af249 | 2008-11-12 11:59:07 -0600 | [diff] [blame] | 228 | if (p->pack_keep) |
Junio C Hamano | 1781550 | 2007-09-17 00:55:13 -0700 | [diff] [blame] | 229 | continue; |
| 230 | /* |
| 231 | * Perhaps check the size of the pack and count only |
| 232 | * very small ones here? |
| 233 | */ |
| 234 | cnt++; |
| 235 | } |
Eric Wong | 5f4e3bf | 2016-06-25 06:46:47 +0000 | [diff] [blame] | 236 | return gc_auto_pack_limit < cnt; |
Junio C Hamano | 1781550 | 2007-09-17 00:55:13 -0700 | [diff] [blame] | 237 | } |
| 238 | |
Nguyễn Thái Ngọc Duy | 9806f5a | 2018-04-15 17:36:17 +0200 | [diff] [blame] | 239 | static uint64_t total_ram(void) |
| 240 | { |
| 241 | #if defined(HAVE_SYSINFO) |
| 242 | struct sysinfo si; |
| 243 | |
| 244 | if (!sysinfo(&si)) |
| 245 | return si.totalram; |
| 246 | #elif defined(HAVE_BSD_SYSCTL) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM)) |
| 247 | int64_t physical_memory; |
| 248 | int mib[2]; |
| 249 | size_t length; |
| 250 | |
| 251 | mib[0] = CTL_HW; |
| 252 | # if defined(HW_MEMSIZE) |
| 253 | mib[1] = HW_MEMSIZE; |
| 254 | # else |
| 255 | mib[1] = HW_PHYSMEM; |
| 256 | # endif |
| 257 | length = sizeof(int64_t); |
| 258 | if (!sysctl(mib, 2, &physical_memory, &length, NULL, 0)) |
| 259 | return physical_memory; |
| 260 | #elif defined(GIT_WINDOWS_NATIVE) |
| 261 | MEMORYSTATUSEX memInfo; |
| 262 | |
| 263 | memInfo.dwLength = sizeof(MEMORYSTATUSEX); |
| 264 | if (GlobalMemoryStatusEx(&memInfo)) |
| 265 | return memInfo.ullTotalPhys; |
| 266 | #endif |
| 267 | return 0; |
| 268 | } |
| 269 | |
| 270 | static uint64_t estimate_repack_memory(struct packed_git *pack) |
| 271 | { |
| 272 | unsigned long nr_objects = approximate_object_count(); |
| 273 | size_t os_cache, heap; |
| 274 | |
| 275 | if (!pack || !nr_objects) |
| 276 | return 0; |
| 277 | |
| 278 | /* |
| 279 | * First we have to scan through at least one pack. |
| 280 | * Assume enough room in OS file cache to keep the entire pack |
| 281 | * or we may accidentally evict data of other processes from |
| 282 | * the cache. |
| 283 | */ |
| 284 | os_cache = pack->pack_size + pack->index_size; |
| 285 | /* then pack-objects needs lots more for book keeping */ |
| 286 | heap = sizeof(struct object_entry) * nr_objects; |
| 287 | /* |
| 288 | * internal rev-list --all --objects takes up some memory too, |
| 289 | * let's say half of it is for blobs |
| 290 | */ |
| 291 | heap += sizeof(struct blob) * nr_objects / 2; |
| 292 | /* |
| 293 | * and the other half is for trees (commits and tags are |
| 294 | * usually insignificant) |
| 295 | */ |
| 296 | heap += sizeof(struct tree) * nr_objects / 2; |
| 297 | /* and then obj_hash[], underestimated in fact */ |
| 298 | heap += sizeof(struct object *) * nr_objects; |
| 299 | /* revindex is used also */ |
| 300 | heap += sizeof(struct revindex_entry) * nr_objects; |
| 301 | /* |
| 302 | * read_sha1_file() (either at delta calculation phase, or |
| 303 | * writing phase) also fills up the delta base cache |
| 304 | */ |
| 305 | heap += delta_base_cache_limit; |
| 306 | /* and of course pack-objects has its own delta cache */ |
| 307 | heap += max_delta_cache_size; |
| 308 | |
| 309 | return os_cache + heap; |
| 310 | } |
| 311 | |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 312 | static int keep_one_pack(struct string_list_item *item, void *data) |
| 313 | { |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 314 | strvec_pushf(&repack, "--keep-pack=%s", basename(item->string)); |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 315 | return 0; |
| 316 | } |
| 317 | |
| 318 | static void add_repack_all_option(struct string_list *keep_pack) |
Jeff King | 7e52f56 | 2012-04-07 06:30:09 -0400 | [diff] [blame] | 319 | { |
| 320 | if (prune_expire && !strcmp(prune_expire, "now")) |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 321 | strvec_push(&repack, "-a"); |
Jeff King | 7e52f56 | 2012-04-07 06:30:09 -0400 | [diff] [blame] | 322 | else { |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 323 | strvec_push(&repack, "-A"); |
Jeff King | 234587f | 2012-04-18 14:10:19 -0700 | [diff] [blame] | 324 | if (prune_expire) |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 325 | strvec_pushf(&repack, "--unpack-unreachable=%s", prune_expire); |
Jeff King | 7e52f56 | 2012-04-07 06:30:09 -0400 | [diff] [blame] | 326 | } |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 327 | |
| 328 | if (keep_pack) |
| 329 | for_each_string_list(keep_pack, keep_one_pack, NULL); |
Jeff King | 7e52f56 | 2012-04-07 06:30:09 -0400 | [diff] [blame] | 330 | } |
| 331 | |
David Turner | bdf56de | 2016-12-28 17:45:41 -0500 | [diff] [blame] | 332 | static void add_repack_incremental_option(void) |
| 333 | { |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 334 | strvec_push(&repack, "--no-write-bitmap-index"); |
David Turner | bdf56de | 2016-12-28 17:45:41 -0500 | [diff] [blame] | 335 | } |
| 336 | |
Junio C Hamano | a087cc9 | 2007-09-17 00:44:17 -0700 | [diff] [blame] | 337 | static int need_to_gc(void) |
| 338 | { |
| 339 | /* |
Brandon Casey | b14d255 | 2008-03-19 16:53:20 -0500 | [diff] [blame] | 340 | * Setting gc.auto to 0 or negative can disable the |
| 341 | * automatic gc. |
Junio C Hamano | a087cc9 | 2007-09-17 00:44:17 -0700 | [diff] [blame] | 342 | */ |
Brandon Casey | b14d255 | 2008-03-19 16:53:20 -0500 | [diff] [blame] | 343 | if (gc_auto_threshold <= 0) |
Junio C Hamano | a087cc9 | 2007-09-17 00:44:17 -0700 | [diff] [blame] | 344 | return 0; |
| 345 | |
Junio C Hamano | 1781550 | 2007-09-17 00:55:13 -0700 | [diff] [blame] | 346 | /* |
| 347 | * If there are too many loose objects, but not too many |
| 348 | * packs, we run "repack -d -l". If there are too many packs, |
| 349 | * we run "repack -A -d -l". Otherwise we tell the caller |
| 350 | * there is no need. |
| 351 | */ |
Nguyễn Thái Ngọc Duy | 55dfe13 | 2018-04-15 17:36:15 +0200 | [diff] [blame] | 352 | if (too_many_packs()) { |
| 353 | struct string_list keep_pack = STRING_LIST_INIT_NODUP; |
| 354 | |
Nguyễn Thái Ngọc Duy | 8fc6776 | 2018-04-15 17:36:16 +0200 | [diff] [blame] | 355 | if (big_pack_threshold) { |
Nguyễn Thái Ngọc Duy | 55dfe13 | 2018-04-15 17:36:15 +0200 | [diff] [blame] | 356 | find_base_packs(&keep_pack, big_pack_threshold); |
Nguyễn Thái Ngọc Duy | 8fc6776 | 2018-04-15 17:36:16 +0200 | [diff] [blame] | 357 | if (keep_pack.nr >= gc_auto_pack_limit) { |
| 358 | big_pack_threshold = 0; |
| 359 | string_list_clear(&keep_pack, 0); |
| 360 | find_base_packs(&keep_pack, 0); |
| 361 | } |
Nguyễn Thái Ngọc Duy | 9806f5a | 2018-04-15 17:36:17 +0200 | [diff] [blame] | 362 | } else { |
| 363 | struct packed_git *p = find_base_packs(&keep_pack, 0); |
| 364 | uint64_t mem_have, mem_want; |
| 365 | |
| 366 | mem_have = total_ram(); |
| 367 | mem_want = estimate_repack_memory(p); |
| 368 | |
| 369 | /* |
| 370 | * Only allow 1/2 of memory for pack-objects, leave |
| 371 | * the rest for the OS and other processes in the |
| 372 | * system. |
| 373 | */ |
| 374 | if (!mem_have || mem_want < mem_have / 2) |
| 375 | string_list_clear(&keep_pack, 0); |
Nguyễn Thái Ngọc Duy | 8fc6776 | 2018-04-15 17:36:16 +0200 | [diff] [blame] | 376 | } |
Nguyễn Thái Ngọc Duy | 55dfe13 | 2018-04-15 17:36:15 +0200 | [diff] [blame] | 377 | |
| 378 | add_repack_all_option(&keep_pack); |
| 379 | string_list_clear(&keep_pack, 0); |
| 380 | } else if (too_many_loose_objects()) |
David Turner | bdf56de | 2016-12-28 17:45:41 -0500 | [diff] [blame] | 381 | add_repack_incremental_option(); |
| 382 | else |
Junio C Hamano | 1781550 | 2007-09-17 00:55:13 -0700 | [diff] [blame] | 383 | return 0; |
Miklos Vajna | bde3054 | 2008-04-02 21:34:38 +0200 | [diff] [blame] | 384 | |
Benoit Pierre | 15048f8 | 2014-03-18 11:00:53 +0100 | [diff] [blame] | 385 | if (run_hook_le(NULL, "pre-auto-gc", NULL)) |
Miklos Vajna | bde3054 | 2008-04-02 21:34:38 +0200 | [diff] [blame] | 386 | return 0; |
Junio C Hamano | 95143f9 | 2007-09-17 00:48:39 -0700 | [diff] [blame] | 387 | return 1; |
Junio C Hamano | a087cc9 | 2007-09-17 00:44:17 -0700 | [diff] [blame] | 388 | } |
| 389 | |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 390 | /* return NULL on success, else hostname running the gc */ |
| 391 | static const char *lock_repo_for_gc(int force, pid_t* ret_pid) |
| 392 | { |
Martin Ågren | b227586 | 2018-05-09 22:55:38 +0200 | [diff] [blame] | 393 | struct lock_file lock = LOCK_INIT; |
René Scharfe | da25bdb | 2017-04-18 17:57:42 -0400 | [diff] [blame] | 394 | char my_host[HOST_NAME_MAX + 1]; |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 395 | struct strbuf sb = STRBUF_INIT; |
| 396 | struct stat st; |
| 397 | uintmax_t pid; |
| 398 | FILE *fp; |
Elia Pinto | 4f1c0b2 | 2014-01-29 08:59:37 -0800 | [diff] [blame] | 399 | int fd; |
Michael Haggerty | 00539ce | 2015-08-10 11:47:48 +0200 | [diff] [blame] | 400 | char *pidfile_path; |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 401 | |
Jeff King | 076aa2c | 2017-09-05 08:15:08 -0400 | [diff] [blame] | 402 | if (is_tempfile_active(pidfile)) |
Jonathan Nieder | 4c5baf0 | 2013-10-16 16:11:46 -0700 | [diff] [blame] | 403 | /* already locked */ |
| 404 | return NULL; |
| 405 | |
David Turner | 5781a9a | 2017-04-18 17:57:43 -0400 | [diff] [blame] | 406 | if (xgethostname(my_host, sizeof(my_host))) |
Jeff King | 5096d49 | 2015-09-24 17:06:08 -0400 | [diff] [blame] | 407 | xsnprintf(my_host, sizeof(my_host), "unknown"); |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 408 | |
Michael Haggerty | 00539ce | 2015-08-10 11:47:48 +0200 | [diff] [blame] | 409 | pidfile_path = git_pathdup("gc.pid"); |
| 410 | fd = hold_lock_file_for_update(&lock, pidfile_path, |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 411 | LOCK_DIE_ON_ERROR); |
| 412 | if (!force) { |
René Scharfe | da25bdb | 2017-04-18 17:57:42 -0400 | [diff] [blame] | 413 | static char locking_host[HOST_NAME_MAX + 1]; |
| 414 | static char *scan_fmt; |
Elia Pinto | 4f1c0b2 | 2014-01-29 08:59:37 -0800 | [diff] [blame] | 415 | int should_exit; |
René Scharfe | da25bdb | 2017-04-18 17:57:42 -0400 | [diff] [blame] | 416 | |
| 417 | if (!scan_fmt) |
Junio C Hamano | afe2fab | 2017-09-17 12:16:55 +0900 | [diff] [blame] | 418 | scan_fmt = xstrfmt("%s %%%ds", "%"SCNuMAX, HOST_NAME_MAX); |
Michael Haggerty | 00539ce | 2015-08-10 11:47:48 +0200 | [diff] [blame] | 419 | fp = fopen(pidfile_path, "r"); |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 420 | memset(locking_host, 0, sizeof(locking_host)); |
| 421 | should_exit = |
| 422 | fp != NULL && |
| 423 | !fstat(fileno(fp), &st) && |
| 424 | /* |
| 425 | * 12 hour limit is very generous as gc should |
| 426 | * never take that long. On the other hand we |
| 427 | * don't really need a strict limit here, |
| 428 | * running gc --auto one day late is not a big |
| 429 | * problem. --force can be used in manual gc |
| 430 | * after the user verifies that no gc is |
| 431 | * running. |
| 432 | */ |
| 433 | time(NULL) - st.st_mtime <= 12 * 3600 && |
René Scharfe | da25bdb | 2017-04-18 17:57:42 -0400 | [diff] [blame] | 434 | fscanf(fp, scan_fmt, &pid, locking_host) == 2 && |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 435 | /* be gentle to concurrent "gc" on remote hosts */ |
Kyle J. McKay | ed7eda8 | 2013-12-31 04:07:39 -0800 | [diff] [blame] | 436 | (strcmp(locking_host, my_host) || !kill(pid, 0) || errno == EPERM); |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 437 | if (fp != NULL) |
| 438 | fclose(fp); |
| 439 | if (should_exit) { |
| 440 | if (fd >= 0) |
| 441 | rollback_lock_file(&lock); |
| 442 | *ret_pid = pid; |
Michael Haggerty | 00539ce | 2015-08-10 11:47:48 +0200 | [diff] [blame] | 443 | free(pidfile_path); |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 444 | return locking_host; |
| 445 | } |
| 446 | } |
| 447 | |
| 448 | strbuf_addf(&sb, "%"PRIuMAX" %s", |
| 449 | (uintmax_t) getpid(), my_host); |
| 450 | write_in_full(fd, sb.buf, sb.len); |
| 451 | strbuf_release(&sb); |
| 452 | commit_lock_file(&lock); |
Jeff King | 076aa2c | 2017-09-05 08:15:08 -0400 | [diff] [blame] | 453 | pidfile = register_tempfile(pidfile_path); |
Michael Haggerty | ebebeae | 2015-08-10 11:47:49 +0200 | [diff] [blame] | 454 | free(pidfile_path); |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 455 | return NULL; |
| 456 | } |
| 457 | |
Jonathan Nieder | 3029970 | 2018-07-16 23:57:40 -0700 | [diff] [blame] | 458 | /* |
| 459 | * Returns 0 if there was no previous error and gc can proceed, 1 if |
| 460 | * gc should not proceed due to an error in the last run. Prints a |
Elijah Newren | 15beaaa | 2019-11-05 17:07:23 +0000 | [diff] [blame] | 461 | * message and returns -1 if an error occurred while reading gc.log |
Jonathan Nieder | 3029970 | 2018-07-16 23:57:40 -0700 | [diff] [blame] | 462 | */ |
| 463 | static int report_last_gc_error(void) |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 464 | { |
| 465 | struct strbuf sb = STRBUF_INIT; |
Jonathan Nieder | 3029970 | 2018-07-16 23:57:40 -0700 | [diff] [blame] | 466 | int ret = 0; |
Jonathan Nieder | 3c426ec | 2018-07-16 23:53:21 -0700 | [diff] [blame] | 467 | ssize_t len; |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 468 | struct stat st; |
| 469 | char *gc_log_path = git_pathdup("gc.log"); |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 470 | |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 471 | if (stat(gc_log_path, &st)) { |
| 472 | if (errno == ENOENT) |
| 473 | goto done; |
| 474 | |
Jonathan Nieder | 3029970 | 2018-07-16 23:57:40 -0700 | [diff] [blame] | 475 | ret = error_errno(_("cannot stat '%s'"), gc_log_path); |
| 476 | goto done; |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 477 | } |
| 478 | |
| 479 | if (st.st_mtime < gc_log_expire_time) |
| 480 | goto done; |
| 481 | |
Jonathan Nieder | 3c426ec | 2018-07-16 23:53:21 -0700 | [diff] [blame] | 482 | len = strbuf_read_file(&sb, gc_log_path, 0); |
| 483 | if (len < 0) |
Jonathan Nieder | 3029970 | 2018-07-16 23:57:40 -0700 | [diff] [blame] | 484 | ret = error_errno(_("cannot read '%s'"), gc_log_path); |
| 485 | else if (len > 0) { |
| 486 | /* |
| 487 | * A previous gc failed. Report the error, and don't |
| 488 | * bother with an automatic gc run since it is likely |
| 489 | * to fail in the same way. |
| 490 | */ |
| 491 | warning(_("The last gc run reported the following. " |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 492 | "Please correct the root cause\n" |
| 493 | "and remove %s.\n" |
| 494 | "Automatic cleanup will not be performed " |
| 495 | "until the file is removed.\n\n" |
| 496 | "%s"), |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 497 | gc_log_path, sb.buf); |
Jonathan Nieder | 3029970 | 2018-07-16 23:57:40 -0700 | [diff] [blame] | 498 | ret = 1; |
| 499 | } |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 500 | strbuf_release(&sb); |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 501 | done: |
| 502 | free(gc_log_path); |
Jonathan Nieder | 3029970 | 2018-07-16 23:57:40 -0700 | [diff] [blame] | 503 | return ret; |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 504 | } |
| 505 | |
Jonathan Nieder | fec2ed2 | 2018-07-16 23:54:16 -0700 | [diff] [blame] | 506 | static void gc_before_repack(void) |
Nguyễn Thái Ngọc Duy | 62aad18 | 2014-05-25 07:38:29 +0700 | [diff] [blame] | 507 | { |
Ævar Arnfjörð Bjarmason | cd8eb3a | 2019-03-15 16:59:54 +0100 | [diff] [blame] | 508 | /* |
| 509 | * We may be called twice, as both the pre- and |
| 510 | * post-daemonized phases will call us, but running these |
| 511 | * commands more than once is pointless and wasteful. |
| 512 | */ |
| 513 | static int done = 0; |
| 514 | if (done++) |
| 515 | return; |
| 516 | |
Jeff King | d70a9eb | 2020-07-28 20:37:20 -0400 | [diff] [blame] | 517 | if (pack_refs && run_command_v_opt(pack_refs_cmd.v, RUN_GIT_CMD)) |
| 518 | die(FAILED_RUN, pack_refs_cmd.v[0]); |
Nguyễn Thái Ngọc Duy | 62aad18 | 2014-05-25 07:38:29 +0700 | [diff] [blame] | 519 | |
Jeff King | d70a9eb | 2020-07-28 20:37:20 -0400 | [diff] [blame] | 520 | if (prune_reflogs && run_command_v_opt(reflog.v, RUN_GIT_CMD)) |
| 521 | die(FAILED_RUN, reflog.v[0]); |
Nguyễn Thái Ngọc Duy | 62aad18 | 2014-05-25 07:38:29 +0700 | [diff] [blame] | 522 | } |
| 523 | |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 524 | int cmd_gc(int argc, const char **argv, const char *prefix) |
| 525 | { |
James Bowes | 44c637c | 2007-11-01 21:02:27 -0400 | [diff] [blame] | 526 | int aggressive = 0; |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 527 | int auto_gc = 0; |
Frank Lichtenheld | a0c14cb | 2008-02-29 22:53:39 +0100 | [diff] [blame] | 528 | int quiet = 0; |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 529 | int force = 0; |
| 530 | const char *name; |
| 531 | pid_t pid; |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 532 | int daemonized = 0; |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 533 | int keep_base_pack = -1; |
Junio C Hamano | 8ab5aa4 | 2018-04-21 12:13:13 +0900 | [diff] [blame] | 534 | timestamp_t dummy; |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 535 | |
James Bowes | 44c637c | 2007-11-01 21:02:27 -0400 | [diff] [blame] | 536 | struct option builtin_gc_options[] = { |
Nguyễn Thái Ngọc Duy | 6705c16 | 2012-08-20 19:32:14 +0700 | [diff] [blame] | 537 | OPT__QUIET(&quiet, N_("suppress progress reporting")), |
| 538 | { OPTION_STRING, 0, "prune", &prune_expire, N_("date"), |
| 539 | N_("prune unreferenced objects"), |
Johannes Schindelin | 58e9d9d | 2009-02-14 23:10:10 +0100 | [diff] [blame] | 540 | PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire }, |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 541 | OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")), |
Nguyễn Thái Ngọc Duy | 7e1eeaa | 2018-02-09 18:01:58 +0700 | [diff] [blame] | 542 | OPT_BOOL_F(0, "auto", &auto_gc, N_("enable auto-gc mode"), |
| 543 | PARSE_OPT_NOCOMPLETE), |
| 544 | OPT_BOOL_F(0, "force", &force, |
| 545 | N_("force running gc even if there may be another gc running"), |
| 546 | PARSE_OPT_NOCOMPLETE), |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 547 | OPT_BOOL(0, "keep-largest-pack", &keep_base_pack, |
| 548 | N_("repack all other packs except the largest pack")), |
James Bowes | 44c637c | 2007-11-01 21:02:27 -0400 | [diff] [blame] | 549 | OPT_END() |
| 550 | }; |
| 551 | |
Nguyễn Thái Ngọc Duy | 0c8151b | 2010-10-22 01:47:19 -0500 | [diff] [blame] | 552 | if (argc == 2 && !strcmp(argv[1], "-h")) |
| 553 | usage_with_options(builtin_gc_usage, builtin_gc_options); |
| 554 | |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 555 | strvec_pushl(&pack_refs_cmd, "pack-refs", "--all", "--prune", NULL); |
| 556 | strvec_pushl(&reflog, "reflog", "expire", "--all", NULL); |
| 557 | strvec_pushl(&repack, "repack", "-d", "-l", NULL); |
| 558 | strvec_pushl(&prune, "prune", "--expire", NULL); |
| 559 | strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL); |
| 560 | strvec_pushl(&rerere, "rerere", "gc", NULL); |
Jeff King | 234587f | 2012-04-18 14:10:19 -0700 | [diff] [blame] | 561 | |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 562 | /* default expiry time, overwritten in gc_config */ |
Tanay Abhra | 5801d3b | 2014-08-07 09:21:22 -0700 | [diff] [blame] | 563 | gc_config(); |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 564 | if (parse_expiry_date(gc_log_expire, &gc_log_expire_time)) |
Junio C Hamano | 96913c9 | 2018-04-23 22:36:14 +0900 | [diff] [blame] | 565 | die(_("failed to parse gc.logexpiry value %s"), gc_log_expire); |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 566 | |
| 567 | if (pack_refs < 0) |
| 568 | pack_refs = !is_bare_repository(); |
| 569 | |
Stephen Boyd | 3778292 | 2009-05-23 11:53:12 -0700 | [diff] [blame] | 570 | argc = parse_options(argc, argv, prefix, builtin_gc_options, |
| 571 | builtin_gc_usage, 0); |
James Bowes | 44c637c | 2007-11-01 21:02:27 -0400 | [diff] [blame] | 572 | if (argc > 0) |
| 573 | usage_with_options(builtin_gc_usage, builtin_gc_options); |
| 574 | |
Junio C Hamano | 8ab5aa4 | 2018-04-21 12:13:13 +0900 | [diff] [blame] | 575 | if (prune_expire && parse_expiry_date(prune_expire, &dummy)) |
| 576 | die(_("failed to parse prune expiry value %s"), prune_expire); |
| 577 | |
James Bowes | 44c637c | 2007-11-01 21:02:27 -0400 | [diff] [blame] | 578 | if (aggressive) { |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 579 | strvec_push(&repack, "-f"); |
Nguyễn Thái Ngọc Duy | 125f814 | 2014-03-16 20:35:03 +0700 | [diff] [blame] | 580 | if (aggressive_depth > 0) |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 581 | strvec_pushf(&repack, "--depth=%d", aggressive_depth); |
Jeff King | 234587f | 2012-04-18 14:10:19 -0700 | [diff] [blame] | 582 | if (aggressive_window > 0) |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 583 | strvec_pushf(&repack, "--window=%d", aggressive_window); |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 584 | } |
Frank Lichtenheld | a0c14cb | 2008-02-29 22:53:39 +0100 | [diff] [blame] | 585 | if (quiet) |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 586 | strvec_push(&repack, "-q"); |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 587 | |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 588 | if (auto_gc) { |
| 589 | /* |
| 590 | * Auto-gc should be least intrusive as possible. |
| 591 | */ |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 592 | if (!need_to_gc()) |
| 593 | return 0; |
Nguyễn Thái Ngọc Duy | 9f673f9 | 2014-02-08 14:08:52 +0700 | [diff] [blame] | 594 | if (!quiet) { |
| 595 | if (detach_auto) |
| 596 | fprintf(stderr, _("Auto packing the repository in background for optimum performance.\n")); |
| 597 | else |
| 598 | fprintf(stderr, _("Auto packing the repository for optimum performance.\n")); |
| 599 | fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n")); |
| 600 | } |
Nguyễn Thái Ngọc Duy | 62aad18 | 2014-05-25 07:38:29 +0700 | [diff] [blame] | 601 | if (detach_auto) { |
Jonathan Nieder | 3029970 | 2018-07-16 23:57:40 -0700 | [diff] [blame] | 602 | int ret = report_last_gc_error(); |
| 603 | if (ret < 0) |
Elijah Newren | 15beaaa | 2019-11-05 17:07:23 +0000 | [diff] [blame] | 604 | /* an I/O error occurred, already reported */ |
Jonathan Nieder | 3029970 | 2018-07-16 23:57:40 -0700 | [diff] [blame] | 605 | exit(128); |
| 606 | if (ret == 1) |
| 607 | /* Last gc --auto failed. Skip this one. */ |
| 608 | return 0; |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 609 | |
Jeff King | c45af94 | 2017-07-11 05:06:35 -0400 | [diff] [blame] | 610 | if (lock_repo_for_gc(force, &pid)) |
| 611 | return 0; |
Jonathan Nieder | fec2ed2 | 2018-07-16 23:54:16 -0700 | [diff] [blame] | 612 | gc_before_repack(); /* dies on failure */ |
Jeff King | c45af94 | 2017-07-11 05:06:35 -0400 | [diff] [blame] | 613 | delete_tempfile(&pidfile); |
| 614 | |
Nguyễn Thái Ngọc Duy | 9f673f9 | 2014-02-08 14:08:52 +0700 | [diff] [blame] | 615 | /* |
| 616 | * failure to daemonize is ok, we'll continue |
| 617 | * in foreground |
| 618 | */ |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 619 | daemonized = !daemonize(); |
Nguyễn Thái Ngọc Duy | 62aad18 | 2014-05-25 07:38:29 +0700 | [diff] [blame] | 620 | } |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 621 | } else { |
| 622 | struct string_list keep_pack = STRING_LIST_INIT_NODUP; |
| 623 | |
| 624 | if (keep_base_pack != -1) { |
| 625 | if (keep_base_pack) |
Nguyễn Thái Ngọc Duy | 55dfe13 | 2018-04-15 17:36:15 +0200 | [diff] [blame] | 626 | find_base_packs(&keep_pack, 0); |
| 627 | } else if (big_pack_threshold) { |
| 628 | find_base_packs(&keep_pack, big_pack_threshold); |
Nguyễn Thái Ngọc Duy | ae4e89e | 2018-04-15 17:36:14 +0200 | [diff] [blame] | 629 | } |
| 630 | |
| 631 | add_repack_all_option(&keep_pack); |
| 632 | string_list_clear(&keep_pack, 0); |
| 633 | } |
Junio C Hamano | 2c3c439 | 2007-09-05 13:01:37 -0700 | [diff] [blame] | 634 | |
Nguyễn Thái Ngọc Duy | 64a99eb | 2013-08-08 18:05:38 +0700 | [diff] [blame] | 635 | name = lock_repo_for_gc(force, &pid); |
| 636 | if (name) { |
| 637 | if (auto_gc) |
| 638 | return 0; /* be quiet on --auto */ |
| 639 | die(_("gc is already running on machine '%s' pid %"PRIuMAX" (use --force if not)"), |
| 640 | name, (uintmax_t)pid); |
| 641 | } |
| 642 | |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 643 | if (daemonized) { |
| 644 | hold_lock_file_for_update(&log_lock, |
| 645 | git_path("gc.log"), |
| 646 | LOCK_DIE_ON_ERROR); |
Junio C Hamano | 076c827 | 2015-10-15 15:43:32 -0700 | [diff] [blame] | 647 | dup2(get_lock_file_fd(&log_lock), 2); |
Nguyễn Thái Ngọc Duy | 329e6e8 | 2015-09-19 12:13:23 +0700 | [diff] [blame] | 648 | sigchain_push_common(process_log_file_on_signal); |
| 649 | atexit(process_log_file_at_exit); |
| 650 | } |
| 651 | |
Jonathan Nieder | fec2ed2 | 2018-07-16 23:54:16 -0700 | [diff] [blame] | 652 | gc_before_repack(); |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 653 | |
Jeff King | 067fbd4 | 2015-06-23 06:54:11 -0400 | [diff] [blame] | 654 | if (!repository_format_precious_objects) { |
Derrick Stolee | 2d511cf | 2019-05-17 11:41:49 -0700 | [diff] [blame] | 655 | close_object_store(the_repository->objects); |
Jeff King | d70a9eb | 2020-07-28 20:37:20 -0400 | [diff] [blame] | 656 | if (run_command_v_opt(repack.v, RUN_GIT_CMD)) |
| 657 | die(FAILED_RUN, repack.v[0]); |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 658 | |
Jeff King | 067fbd4 | 2015-06-23 06:54:11 -0400 | [diff] [blame] | 659 | if (prune_expire) { |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 660 | strvec_push(&prune, prune_expire); |
Jeff King | 067fbd4 | 2015-06-23 06:54:11 -0400 | [diff] [blame] | 661 | if (quiet) |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 662 | strvec_push(&prune, "--no-progress"); |
Christian Couder | b14ed5a | 2019-06-25 15:40:31 +0200 | [diff] [blame] | 663 | if (has_promisor_remote()) |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 664 | strvec_push(&prune, |
Jeff King | f6d8942 | 2020-07-28 16:26:31 -0400 | [diff] [blame] | 665 | "--exclude-promisor-objects"); |
Jeff King | d70a9eb | 2020-07-28 20:37:20 -0400 | [diff] [blame] | 666 | if (run_command_v_opt(prune.v, RUN_GIT_CMD)) |
| 667 | die(FAILED_RUN, prune.v[0]); |
Jeff King | 067fbd4 | 2015-06-23 06:54:11 -0400 | [diff] [blame] | 668 | } |
Johannes Schindelin | 58e9d9d | 2009-02-14 23:10:10 +0100 | [diff] [blame] | 669 | } |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 670 | |
Nguyễn Thái Ngọc Duy | e3df33b | 2014-11-30 15:24:53 +0700 | [diff] [blame] | 671 | if (prune_worktrees_expire) { |
Jeff King | 22f9b7f | 2020-07-28 16:24:27 -0400 | [diff] [blame] | 672 | strvec_push(&prune_worktrees, prune_worktrees_expire); |
Jeff King | d70a9eb | 2020-07-28 20:37:20 -0400 | [diff] [blame] | 673 | if (run_command_v_opt(prune_worktrees.v, RUN_GIT_CMD)) |
| 674 | die(FAILED_RUN, prune_worktrees.v[0]); |
Nguyễn Thái Ngọc Duy | e3df33b | 2014-11-30 15:24:53 +0700 | [diff] [blame] | 675 | } |
| 676 | |
Jeff King | d70a9eb | 2020-07-28 20:37:20 -0400 | [diff] [blame] | 677 | if (run_command_v_opt(rerere.v, RUN_GIT_CMD)) |
| 678 | die(FAILED_RUN, rerere.v[0]); |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 679 | |
Doug Kelly | 478f34d | 2015-11-03 21:05:08 -0600 | [diff] [blame] | 680 | report_garbage = report_pack_garbage; |
Stefan Beller | a49d283 | 2018-03-23 18:45:21 +0100 | [diff] [blame] | 681 | reprepare_packed_git(the_repository); |
Johannes Schindelin | 5bdece0 | 2018-12-15 14:04:01 -0800 | [diff] [blame] | 682 | if (pack_garbage.nr > 0) { |
Derrick Stolee | 2d511cf | 2019-05-17 11:41:49 -0700 | [diff] [blame] | 683 | close_object_store(the_repository->objects); |
Doug Kelly | 478f34d | 2015-11-03 21:05:08 -0600 | [diff] [blame] | 684 | clean_pack_garbage(); |
Johannes Schindelin | 5bdece0 | 2018-12-15 14:04:01 -0800 | [diff] [blame] | 685 | } |
Doug Kelly | 478f34d | 2015-11-03 21:05:08 -0600 | [diff] [blame] | 686 | |
Derrick Stolee | 7211b9e | 2019-08-13 11:37:43 -0700 | [diff] [blame] | 687 | prepare_repo_settings(the_repository); |
| 688 | if (the_repository->settings.gc_write_commit_graph == 1) |
Taylor Blau | 0bd52e2 | 2020-02-03 21:51:50 -0800 | [diff] [blame] | 689 | write_commit_graph_reachable(the_repository->objects->odb, |
Junio C Hamano | f4f8dfe | 2019-09-09 12:26:36 -0700 | [diff] [blame] | 690 | !quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0, |
Derrick Stolee | 7211b9e | 2019-08-13 11:37:43 -0700 | [diff] [blame] | 691 | NULL); |
Derrick Stolee | d5d5d7b | 2018-06-27 09:24:46 -0400 | [diff] [blame] | 692 | |
Junio C Hamano | a087cc9 | 2007-09-17 00:44:17 -0700 | [diff] [blame] | 693 | if (auto_gc && too_many_loose_objects()) |
Ævar Arnfjörð Bjarmason | fea6128 | 2011-02-22 23:42:24 +0000 | [diff] [blame] | 694 | warning(_("There are too many unreachable loose objects; " |
| 695 | "run 'git prune' to remove them.")); |
Junio C Hamano | a087cc9 | 2007-09-17 00:44:17 -0700 | [diff] [blame] | 696 | |
David Turner | a831c06 | 2017-02-10 16:28:22 -0500 | [diff] [blame] | 697 | if (!daemonized) |
| 698 | unlink(git_path("gc.log")); |
| 699 | |
James Bowes | 6757ada | 2007-03-13 21:58:22 -0400 | [diff] [blame] | 700 | return 0; |
| 701 | } |
Derrick Stolee | 2057d75 | 2020-09-17 18:11:42 +0000 | [diff] [blame^] | 702 | |
| 703 | static const char * const builtin_maintenance_run_usage[] = { |
| 704 | N_("git maintenance run [--auto]"), |
| 705 | NULL |
| 706 | }; |
| 707 | |
| 708 | struct maintenance_run_opts { |
| 709 | int auto_flag; |
| 710 | }; |
| 711 | |
| 712 | static int maintenance_task_gc(struct maintenance_run_opts *opts) |
| 713 | { |
| 714 | struct child_process child = CHILD_PROCESS_INIT; |
| 715 | |
| 716 | child.git_cmd = 1; |
| 717 | strvec_push(&child.args, "gc"); |
| 718 | |
| 719 | if (opts->auto_flag) |
| 720 | strvec_push(&child.args, "--auto"); |
| 721 | |
| 722 | close_object_store(the_repository->objects); |
| 723 | return run_command(&child); |
| 724 | } |
| 725 | |
| 726 | static int maintenance_run(int argc, const char **argv, const char *prefix) |
| 727 | { |
| 728 | struct maintenance_run_opts opts; |
| 729 | struct option builtin_maintenance_run_options[] = { |
| 730 | OPT_BOOL(0, "auto", &opts.auto_flag, |
| 731 | N_("run tasks based on the state of the repository")), |
| 732 | OPT_END() |
| 733 | }; |
| 734 | memset(&opts, 0, sizeof(opts)); |
| 735 | |
| 736 | argc = parse_options(argc, argv, prefix, |
| 737 | builtin_maintenance_run_options, |
| 738 | builtin_maintenance_run_usage, |
| 739 | PARSE_OPT_STOP_AT_NON_OPTION); |
| 740 | |
| 741 | if (argc != 0) |
| 742 | usage_with_options(builtin_maintenance_run_usage, |
| 743 | builtin_maintenance_run_options); |
| 744 | return maintenance_task_gc(&opts); |
| 745 | } |
| 746 | |
| 747 | static const char builtin_maintenance_usage[] = N_("git maintenance run [<options>]"); |
| 748 | |
| 749 | int cmd_maintenance(int argc, const char **argv, const char *prefix) |
| 750 | { |
| 751 | if (argc < 2 || |
| 752 | (argc == 2 && !strcmp(argv[1], "-h"))) |
| 753 | usage(builtin_maintenance_usage); |
| 754 | |
| 755 | if (!strcmp(argv[1], "run")) |
| 756 | return maintenance_run(argc - 1, argv + 1, prefix); |
| 757 | |
| 758 | die(_("invalid subcommand: %s"), argv[1]); |
| 759 | } |