Git fork
at reftables-rust 1734 lines 51 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2#define DISABLE_SIGN_COMPARE_WARNINGS 3 4#include "builtin.h" 5#include "config.h" 6#include "dir.h" 7#include "environment.h" 8#include "gettext.h" 9#include "hex.h" 10#include "parse-options.h" 11#include "path.h" 12#include "run-command.h" 13#include "server-info.h" 14#include "strbuf.h" 15#include "string-list.h" 16#include "strvec.h" 17#include "midx.h" 18#include "packfile.h" 19#include "prune-packed.h" 20#include "odb.h" 21#include "promisor-remote.h" 22#include "shallow.h" 23#include "pack.h" 24#include "pack-bitmap.h" 25#include "refs.h" 26#include "list-objects-filter-options.h" 27 28#define ALL_INTO_ONE 1 29#define LOOSEN_UNREACHABLE 2 30#define PACK_CRUFT 4 31 32#define DELETE_PACK 1 33#define RETAIN_PACK 2 34 35static int pack_everything; 36static int delta_base_offset = 1; 37static int pack_kept_objects = -1; 38static int write_bitmaps = -1; 39static int use_delta_islands; 40static int run_update_server_info = 1; 41static char *packdir, *packtmp_name, *packtmp; 42static int midx_must_contain_cruft = 1; 43 44static const char *const git_repack_usage[] = { 45 N_("git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" 46 "[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" 47 "[--write-midx] [--name-hash-version=<n>] [--path-walk]"), 48 NULL 49}; 50 51static const char incremental_bitmap_conflict_error[] = N_( 52"Incremental repacks are incompatible with bitmap indexes. Use\n" 53"--no-write-bitmap-index or disable the pack.writeBitmaps configuration." 54); 55 56struct pack_objects_args { 57 char *window; 58 char *window_memory; 59 char *depth; 60 char *threads; 61 unsigned long max_pack_size; 62 int no_reuse_delta; 63 int no_reuse_object; 64 int quiet; 65 int local; 66 int name_hash_version; 67 int path_walk; 68 struct list_objects_filter_options filter_options; 69}; 70 71static int repack_config(const char *var, const char *value, 72 const struct config_context *ctx, void *cb) 73{ 74 struct pack_objects_args *cruft_po_args = cb; 75 if (!strcmp(var, "repack.usedeltabaseoffset")) { 76 delta_base_offset = git_config_bool(var, value); 77 return 0; 78 } 79 if (!strcmp(var, "repack.packkeptobjects")) { 80 pack_kept_objects = git_config_bool(var, value); 81 return 0; 82 } 83 if (!strcmp(var, "repack.writebitmaps") || 84 !strcmp(var, "pack.writebitmaps")) { 85 write_bitmaps = git_config_bool(var, value); 86 return 0; 87 } 88 if (!strcmp(var, "repack.usedeltaislands")) { 89 use_delta_islands = git_config_bool(var, value); 90 return 0; 91 } 92 if (strcmp(var, "repack.updateserverinfo") == 0) { 93 run_update_server_info = git_config_bool(var, value); 94 return 0; 95 } 96 if (!strcmp(var, "repack.cruftwindow")) { 97 free(cruft_po_args->window); 98 return git_config_string(&cruft_po_args->window, var, value); 99 } 100 if (!strcmp(var, "repack.cruftwindowmemory")) { 101 free(cruft_po_args->window_memory); 102 return git_config_string(&cruft_po_args->window_memory, var, value); 103 } 104 if (!strcmp(var, "repack.cruftdepth")) { 105 free(cruft_po_args->depth); 106 return git_config_string(&cruft_po_args->depth, var, value); 107 } 108 if (!strcmp(var, "repack.cruftthreads")) { 109 free(cruft_po_args->threads); 110 return git_config_string(&cruft_po_args->threads, var, value); 111 } 112 if (!strcmp(var, "repack.midxmustcontaincruft")) { 113 midx_must_contain_cruft = git_config_bool(var, value); 114 return 0; 115 } 116 return git_default_config(var, value, ctx, cb); 117} 118 119static void pack_objects_args_release(struct pack_objects_args *args) 120{ 121 free(args->window); 122 free(args->window_memory); 123 free(args->depth); 124 free(args->threads); 125 list_objects_filter_release(&args->filter_options); 126} 127 128struct existing_packs { 129 struct string_list kept_packs; 130 struct string_list non_kept_packs; 131 struct string_list cruft_packs; 132}; 133 134#define EXISTING_PACKS_INIT { \ 135 .kept_packs = STRING_LIST_INIT_DUP, \ 136 .non_kept_packs = STRING_LIST_INIT_DUP, \ 137 .cruft_packs = STRING_LIST_INIT_DUP, \ 138} 139 140static int has_existing_non_kept_packs(const struct existing_packs *existing) 141{ 142 return existing->non_kept_packs.nr || existing->cruft_packs.nr; 143} 144 145static void pack_mark_for_deletion(struct string_list_item *item) 146{ 147 item->util = (void*)((uintptr_t)item->util | DELETE_PACK); 148} 149 150static void pack_unmark_for_deletion(struct string_list_item *item) 151{ 152 item->util = (void*)((uintptr_t)item->util & ~DELETE_PACK); 153} 154 155static int pack_is_marked_for_deletion(struct string_list_item *item) 156{ 157 return (uintptr_t)item->util & DELETE_PACK; 158} 159 160static void pack_mark_retained(struct string_list_item *item) 161{ 162 item->util = (void*)((uintptr_t)item->util | RETAIN_PACK); 163} 164 165static int pack_is_retained(struct string_list_item *item) 166{ 167 return (uintptr_t)item->util & RETAIN_PACK; 168} 169 170static void mark_packs_for_deletion_1(struct string_list *names, 171 struct string_list *list) 172{ 173 struct string_list_item *item; 174 const int hexsz = the_hash_algo->hexsz; 175 176 for_each_string_list_item(item, list) { 177 char *sha1; 178 size_t len = strlen(item->string); 179 if (len < hexsz) 180 continue; 181 sha1 = item->string + len - hexsz; 182 183 if (pack_is_retained(item)) { 184 pack_unmark_for_deletion(item); 185 } else if (!string_list_has_string(names, sha1)) { 186 /* 187 * Mark this pack for deletion, which ensures 188 * that this pack won't be included in a MIDX 189 * (if `--write-midx` was given) and that we 190 * will actually delete this pack (if `-d` was 191 * given). 192 */ 193 pack_mark_for_deletion(item); 194 } 195 } 196} 197 198static void retain_cruft_pack(struct existing_packs *existing, 199 struct packed_git *cruft) 200{ 201 struct strbuf buf = STRBUF_INIT; 202 struct string_list_item *item; 203 204 strbuf_addstr(&buf, pack_basename(cruft)); 205 strbuf_strip_suffix(&buf, ".pack"); 206 207 item = string_list_lookup(&existing->cruft_packs, buf.buf); 208 if (!item) 209 BUG("could not find cruft pack '%s'", pack_basename(cruft)); 210 211 pack_mark_retained(item); 212 strbuf_release(&buf); 213} 214 215static void mark_packs_for_deletion(struct existing_packs *existing, 216 struct string_list *names) 217 218{ 219 mark_packs_for_deletion_1(names, &existing->non_kept_packs); 220 mark_packs_for_deletion_1(names, &existing->cruft_packs); 221} 222 223static void remove_redundant_pack(const char *dir_name, const char *base_name) 224{ 225 struct strbuf buf = STRBUF_INIT; 226 struct odb_source *source = the_repository->objects->sources; 227 struct multi_pack_index *m = get_multi_pack_index(source); 228 strbuf_addf(&buf, "%s.pack", base_name); 229 if (m && source->local && midx_contains_pack(m, buf.buf)) 230 clear_midx_file(the_repository); 231 strbuf_insertf(&buf, 0, "%s/", dir_name); 232 unlink_pack_path(buf.buf, 1); 233 strbuf_release(&buf); 234} 235 236static void remove_redundant_packs_1(struct string_list *packs) 237{ 238 struct string_list_item *item; 239 for_each_string_list_item(item, packs) { 240 if (!pack_is_marked_for_deletion(item)) 241 continue; 242 remove_redundant_pack(packdir, item->string); 243 } 244} 245 246static void remove_redundant_existing_packs(struct existing_packs *existing) 247{ 248 remove_redundant_packs_1(&existing->non_kept_packs); 249 remove_redundant_packs_1(&existing->cruft_packs); 250} 251 252static void existing_packs_release(struct existing_packs *existing) 253{ 254 string_list_clear(&existing->kept_packs, 0); 255 string_list_clear(&existing->non_kept_packs, 0); 256 string_list_clear(&existing->cruft_packs, 0); 257} 258 259/* 260 * Adds all packs hex strings (pack-$HASH) to either packs->non_kept 261 * or packs->kept based on whether each pack has a corresponding 262 * .keep file or not. Packs without a .keep file are not to be kept 263 * if we are going to pack everything into one file. 264 */ 265static void collect_pack_filenames(struct existing_packs *existing, 266 const struct string_list *extra_keep) 267{ 268 struct packfile_store *packs = the_repository->objects->packfiles; 269 struct packed_git *p; 270 struct strbuf buf = STRBUF_INIT; 271 272 for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 273 int i; 274 const char *base; 275 276 if (!p->pack_local) 277 continue; 278 279 base = pack_basename(p); 280 281 for (i = 0; i < extra_keep->nr; i++) 282 if (!fspathcmp(base, extra_keep->items[i].string)) 283 break; 284 285 strbuf_reset(&buf); 286 strbuf_addstr(&buf, base); 287 strbuf_strip_suffix(&buf, ".pack"); 288 289 if ((extra_keep->nr > 0 && i < extra_keep->nr) || p->pack_keep) 290 string_list_append(&existing->kept_packs, buf.buf); 291 else if (p->is_cruft) 292 string_list_append(&existing->cruft_packs, buf.buf); 293 else 294 string_list_append(&existing->non_kept_packs, buf.buf); 295 } 296 297 string_list_sort(&existing->kept_packs); 298 string_list_sort(&existing->non_kept_packs); 299 string_list_sort(&existing->cruft_packs); 300 strbuf_release(&buf); 301} 302 303static void prepare_pack_objects(struct child_process *cmd, 304 const struct pack_objects_args *args, 305 const char *out) 306{ 307 strvec_push(&cmd->args, "pack-objects"); 308 if (args->window) 309 strvec_pushf(&cmd->args, "--window=%s", args->window); 310 if (args->window_memory) 311 strvec_pushf(&cmd->args, "--window-memory=%s", args->window_memory); 312 if (args->depth) 313 strvec_pushf(&cmd->args, "--depth=%s", args->depth); 314 if (args->threads) 315 strvec_pushf(&cmd->args, "--threads=%s", args->threads); 316 if (args->max_pack_size) 317 strvec_pushf(&cmd->args, "--max-pack-size=%lu", args->max_pack_size); 318 if (args->no_reuse_delta) 319 strvec_pushf(&cmd->args, "--no-reuse-delta"); 320 if (args->no_reuse_object) 321 strvec_pushf(&cmd->args, "--no-reuse-object"); 322 if (args->name_hash_version) 323 strvec_pushf(&cmd->args, "--name-hash-version=%d", args->name_hash_version); 324 if (args->path_walk) 325 strvec_pushf(&cmd->args, "--path-walk"); 326 if (args->local) 327 strvec_push(&cmd->args, "--local"); 328 if (args->quiet) 329 strvec_push(&cmd->args, "--quiet"); 330 if (delta_base_offset) 331 strvec_push(&cmd->args, "--delta-base-offset"); 332 strvec_push(&cmd->args, out); 333 cmd->git_cmd = 1; 334 cmd->out = -1; 335} 336 337/* 338 * Write oid to the given struct child_process's stdin, starting it first if 339 * necessary. 340 */ 341static int write_oid(const struct object_id *oid, 342 struct packed_git *pack UNUSED, 343 uint32_t pos UNUSED, void *data) 344{ 345 struct child_process *cmd = data; 346 347 if (cmd->in == -1) { 348 if (start_command(cmd)) 349 die(_("could not start pack-objects to repack promisor objects")); 350 } 351 352 if (write_in_full(cmd->in, oid_to_hex(oid), the_hash_algo->hexsz) < 0 || 353 write_in_full(cmd->in, "\n", 1) < 0) 354 die(_("failed to feed promisor objects to pack-objects")); 355 return 0; 356} 357 358static struct { 359 const char *name; 360 unsigned optional:1; 361} exts[] = { 362 {".pack"}, 363 {".rev", 1}, 364 {".mtimes", 1}, 365 {".bitmap", 1}, 366 {".promisor", 1}, 367 {".idx"}, 368}; 369 370struct generated_pack_data { 371 struct tempfile *tempfiles[ARRAY_SIZE(exts)]; 372}; 373 374static struct generated_pack_data *populate_pack_exts(const char *name) 375{ 376 struct stat statbuf; 377 struct strbuf path = STRBUF_INIT; 378 struct generated_pack_data *data = xcalloc(1, sizeof(*data)); 379 int i; 380 381 for (i = 0; i < ARRAY_SIZE(exts); i++) { 382 strbuf_reset(&path); 383 strbuf_addf(&path, "%s-%s%s", packtmp, name, exts[i].name); 384 385 if (stat(path.buf, &statbuf)) 386 continue; 387 388 data->tempfiles[i] = register_tempfile(path.buf); 389 } 390 391 strbuf_release(&path); 392 return data; 393} 394 395static int has_pack_ext(const struct generated_pack_data *data, 396 const char *ext) 397{ 398 int i; 399 for (i = 0; i < ARRAY_SIZE(exts); i++) { 400 if (strcmp(exts[i].name, ext)) 401 continue; 402 return !!data->tempfiles[i]; 403 } 404 BUG("unknown pack extension: '%s'", ext); 405} 406 407static void repack_promisor_objects(const struct pack_objects_args *args, 408 struct string_list *names) 409{ 410 struct child_process cmd = CHILD_PROCESS_INIT; 411 FILE *out; 412 struct strbuf line = STRBUF_INIT; 413 414 prepare_pack_objects(&cmd, args, packtmp); 415 cmd.in = -1; 416 417 /* 418 * NEEDSWORK: Giving pack-objects only the OIDs without any ordering 419 * hints may result in suboptimal deltas in the resulting pack. See if 420 * the OIDs can be sent with fake paths such that pack-objects can use a 421 * {type -> existing pack order} ordering when computing deltas instead 422 * of a {type -> size} ordering, which may produce better deltas. 423 */ 424 for_each_packed_object(the_repository, write_oid, &cmd, 425 FOR_EACH_OBJECT_PROMISOR_ONLY); 426 427 if (cmd.in == -1) { 428 /* No packed objects; cmd was never started */ 429 child_process_clear(&cmd); 430 return; 431 } 432 433 close(cmd.in); 434 435 out = xfdopen(cmd.out, "r"); 436 while (strbuf_getline_lf(&line, out) != EOF) { 437 struct string_list_item *item; 438 char *promisor_name; 439 440 if (line.len != the_hash_algo->hexsz) 441 die(_("repack: Expecting full hex object ID lines only from pack-objects.")); 442 item = string_list_append(names, line.buf); 443 444 /* 445 * pack-objects creates the .pack and .idx files, but not the 446 * .promisor file. Create the .promisor file, which is empty. 447 * 448 * NEEDSWORK: fetch-pack sometimes generates non-empty 449 * .promisor files containing the ref names and associated 450 * hashes at the point of generation of the corresponding 451 * packfile, but this would not preserve their contents. Maybe 452 * concatenate the contents of all .promisor files instead of 453 * just creating a new empty file. 454 */ 455 promisor_name = mkpathdup("%s-%s.promisor", packtmp, 456 line.buf); 457 write_promisor_file(promisor_name, NULL, 0); 458 459 item->util = populate_pack_exts(item->string); 460 461 free(promisor_name); 462 } 463 464 fclose(out); 465 if (finish_command(&cmd)) 466 die(_("could not finish pack-objects to repack promisor objects")); 467 strbuf_release(&line); 468} 469 470struct pack_geometry { 471 struct packed_git **pack; 472 uint32_t pack_nr, pack_alloc; 473 uint32_t split; 474 475 int split_factor; 476}; 477 478static uint32_t geometry_pack_weight(struct packed_git *p) 479{ 480 if (open_pack_index(p)) 481 die(_("cannot open index for %s"), p->pack_name); 482 return p->num_objects; 483} 484 485static int geometry_cmp(const void *va, const void *vb) 486{ 487 uint32_t aw = geometry_pack_weight(*(struct packed_git **)va), 488 bw = geometry_pack_weight(*(struct packed_git **)vb); 489 490 if (aw < bw) 491 return -1; 492 if (aw > bw) 493 return 1; 494 return 0; 495} 496 497static void init_pack_geometry(struct pack_geometry *geometry, 498 struct existing_packs *existing, 499 const struct pack_objects_args *args) 500{ 501 struct packfile_store *packs = the_repository->objects->packfiles; 502 struct packed_git *p; 503 struct strbuf buf = STRBUF_INIT; 504 505 for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 506 if (args->local && !p->pack_local) 507 /* 508 * When asked to only repack local packfiles we skip 509 * over any packfiles that are borrowed from alternate 510 * object directories. 511 */ 512 continue; 513 514 if (!pack_kept_objects) { 515 /* 516 * Any pack that has its pack_keep bit set will 517 * appear in existing->kept_packs below, but 518 * this saves us from doing a more expensive 519 * check. 520 */ 521 if (p->pack_keep) 522 continue; 523 524 /* 525 * The pack may be kept via the --keep-pack 526 * option; check 'existing->kept_packs' to 527 * determine whether to ignore it. 528 */ 529 strbuf_reset(&buf); 530 strbuf_addstr(&buf, pack_basename(p)); 531 strbuf_strip_suffix(&buf, ".pack"); 532 533 if (string_list_has_string(&existing->kept_packs, buf.buf)) 534 continue; 535 } 536 if (p->is_cruft) 537 continue; 538 539 ALLOC_GROW(geometry->pack, 540 geometry->pack_nr + 1, 541 geometry->pack_alloc); 542 543 geometry->pack[geometry->pack_nr] = p; 544 geometry->pack_nr++; 545 } 546 547 QSORT(geometry->pack, geometry->pack_nr, geometry_cmp); 548 strbuf_release(&buf); 549} 550 551static void split_pack_geometry(struct pack_geometry *geometry) 552{ 553 uint32_t i; 554 uint32_t split; 555 off_t total_size = 0; 556 557 if (!geometry->pack_nr) { 558 geometry->split = geometry->pack_nr; 559 return; 560 } 561 562 /* 563 * First, count the number of packs (in descending order of size) which 564 * already form a geometric progression. 565 */ 566 for (i = geometry->pack_nr - 1; i > 0; i--) { 567 struct packed_git *ours = geometry->pack[i]; 568 struct packed_git *prev = geometry->pack[i - 1]; 569 570 if (unsigned_mult_overflows(geometry->split_factor, 571 geometry_pack_weight(prev))) 572 die(_("pack %s too large to consider in geometric " 573 "progression"), 574 prev->pack_name); 575 576 if (geometry_pack_weight(ours) < 577 geometry->split_factor * geometry_pack_weight(prev)) 578 break; 579 } 580 581 split = i; 582 583 if (split) { 584 /* 585 * Move the split one to the right, since the top element in the 586 * last-compared pair can't be in the progression. Only do this 587 * when we split in the middle of the array (otherwise if we got 588 * to the end, then the split is in the right place). 589 */ 590 split++; 591 } 592 593 /* 594 * Then, anything to the left of 'split' must be in a new pack. But, 595 * creating that new pack may cause packs in the heavy half to no longer 596 * form a geometric progression. 597 * 598 * Compute an expected size of the new pack, and then determine how many 599 * packs in the heavy half need to be joined into it (if any) to restore 600 * the geometric progression. 601 */ 602 for (i = 0; i < split; i++) { 603 struct packed_git *p = geometry->pack[i]; 604 605 if (unsigned_add_overflows(total_size, geometry_pack_weight(p))) 606 die(_("pack %s too large to roll up"), p->pack_name); 607 total_size += geometry_pack_weight(p); 608 } 609 for (i = split; i < geometry->pack_nr; i++) { 610 struct packed_git *ours = geometry->pack[i]; 611 612 if (unsigned_mult_overflows(geometry->split_factor, 613 total_size)) 614 die(_("pack %s too large to roll up"), ours->pack_name); 615 616 if (geometry_pack_weight(ours) < 617 geometry->split_factor * total_size) { 618 if (unsigned_add_overflows(total_size, 619 geometry_pack_weight(ours))) 620 die(_("pack %s too large to roll up"), 621 ours->pack_name); 622 623 split++; 624 total_size += geometry_pack_weight(ours); 625 } else 626 break; 627 } 628 629 geometry->split = split; 630} 631 632static struct packed_git *get_preferred_pack(struct pack_geometry *geometry) 633{ 634 uint32_t i; 635 636 if (!geometry) { 637 /* 638 * No geometry means either an all-into-one repack (in which 639 * case there is only one pack left and it is the largest) or an 640 * incremental one. 641 * 642 * If repacking incrementally, then we could check the size of 643 * all packs to determine which should be preferred, but leave 644 * this for later. 645 */ 646 return NULL; 647 } 648 if (geometry->split == geometry->pack_nr) 649 return NULL; 650 651 /* 652 * The preferred pack is the largest pack above the split line. In 653 * other words, it is the largest pack that does not get rolled up in 654 * the geometric repack. 655 */ 656 for (i = geometry->pack_nr; i > geometry->split; i--) 657 /* 658 * A pack that is not local would never be included in a 659 * multi-pack index. We thus skip over any non-local packs. 660 */ 661 if (geometry->pack[i - 1]->pack_local) 662 return geometry->pack[i - 1]; 663 664 return NULL; 665} 666 667static void geometry_remove_redundant_packs(struct pack_geometry *geometry, 668 struct string_list *names, 669 struct existing_packs *existing) 670{ 671 struct strbuf buf = STRBUF_INIT; 672 uint32_t i; 673 674 for (i = 0; i < geometry->split; i++) { 675 struct packed_git *p = geometry->pack[i]; 676 if (string_list_has_string(names, hash_to_hex(p->hash))) 677 continue; 678 679 strbuf_reset(&buf); 680 strbuf_addstr(&buf, pack_basename(p)); 681 strbuf_strip_suffix(&buf, ".pack"); 682 683 if ((p->pack_keep) || 684 (string_list_has_string(&existing->kept_packs, buf.buf))) 685 continue; 686 687 remove_redundant_pack(packdir, buf.buf); 688 } 689 690 strbuf_release(&buf); 691} 692 693static void free_pack_geometry(struct pack_geometry *geometry) 694{ 695 if (!geometry) 696 return; 697 698 free(geometry->pack); 699} 700 701static int midx_has_unknown_packs(char **midx_pack_names, 702 size_t midx_pack_names_nr, 703 struct string_list *include, 704 struct pack_geometry *geometry, 705 struct existing_packs *existing) 706{ 707 size_t i; 708 709 string_list_sort(include); 710 711 for (i = 0; i < midx_pack_names_nr; i++) { 712 const char *pack_name = midx_pack_names[i]; 713 714 /* 715 * Determine whether or not each MIDX'd pack from the existing 716 * MIDX (if any) is represented in the new MIDX. For each pack 717 * in the MIDX, it must either be: 718 * 719 * - In the "include" list of packs to be included in the new 720 * MIDX. Note this function is called before the include 721 * list is populated with any cruft pack(s). 722 * 723 * - Below the geometric split line (if using pack geometry), 724 * indicating that the pack won't be included in the new 725 * MIDX, but its contents were rolled up as part of the 726 * geometric repack. 727 * 728 * - In the existing non-kept packs list (if not using pack 729 * geometry), and marked as non-deleted. 730 */ 731 if (string_list_has_string(include, pack_name)) { 732 continue; 733 } else if (geometry) { 734 struct strbuf buf = STRBUF_INIT; 735 uint32_t j; 736 737 for (j = 0; j < geometry->split; j++) { 738 strbuf_reset(&buf); 739 strbuf_addstr(&buf, pack_basename(geometry->pack[j])); 740 strbuf_strip_suffix(&buf, ".pack"); 741 strbuf_addstr(&buf, ".idx"); 742 743 if (!strcmp(pack_name, buf.buf)) { 744 strbuf_release(&buf); 745 break; 746 } 747 } 748 749 strbuf_release(&buf); 750 751 if (j < geometry->split) 752 continue; 753 } else { 754 struct string_list_item *item; 755 756 item = string_list_lookup(&existing->non_kept_packs, 757 pack_name); 758 if (item && !pack_is_marked_for_deletion(item)) 759 continue; 760 } 761 762 /* 763 * If we got to this point, the MIDX includes some pack that we 764 * don't know about. 765 */ 766 return 1; 767 } 768 769 return 0; 770} 771 772struct midx_snapshot_ref_data { 773 struct tempfile *f; 774 struct oidset seen; 775 int preferred; 776}; 777 778static int midx_snapshot_ref_one(const char *refname UNUSED, 779 const char *referent UNUSED, 780 const struct object_id *oid, 781 int flag UNUSED, void *_data) 782{ 783 struct midx_snapshot_ref_data *data = _data; 784 struct object_id peeled; 785 786 if (!peel_iterated_oid(the_repository, oid, &peeled)) 787 oid = &peeled; 788 789 if (oidset_insert(&data->seen, oid)) 790 return 0; /* already seen */ 791 792 if (odb_read_object_info(the_repository->objects, oid, NULL) != OBJ_COMMIT) 793 return 0; 794 795 fprintf(data->f->fp, "%s%s\n", data->preferred ? "+" : "", 796 oid_to_hex(oid)); 797 798 return 0; 799} 800 801static void midx_snapshot_refs(struct tempfile *f) 802{ 803 struct midx_snapshot_ref_data data; 804 const struct string_list *preferred = bitmap_preferred_tips(the_repository); 805 806 data.f = f; 807 data.preferred = 0; 808 oidset_init(&data.seen, 0); 809 810 if (!fdopen_tempfile(f, "w")) 811 die(_("could not open tempfile %s for writing"), 812 get_tempfile_path(f)); 813 814 if (preferred) { 815 struct string_list_item *item; 816 817 data.preferred = 1; 818 for_each_string_list_item(item, preferred) 819 refs_for_each_ref_in(get_main_ref_store(the_repository), 820 item->string, 821 midx_snapshot_ref_one, &data); 822 data.preferred = 0; 823 } 824 825 refs_for_each_ref(get_main_ref_store(the_repository), 826 midx_snapshot_ref_one, &data); 827 828 if (close_tempfile_gently(f)) { 829 int save_errno = errno; 830 delete_tempfile(&f); 831 errno = save_errno; 832 die_errno(_("could not close refs snapshot tempfile")); 833 } 834 835 oidset_clear(&data.seen); 836} 837 838static void midx_included_packs(struct string_list *include, 839 struct existing_packs *existing, 840 char **midx_pack_names, 841 size_t midx_pack_names_nr, 842 struct string_list *names, 843 struct pack_geometry *geometry) 844{ 845 struct string_list_item *item; 846 struct strbuf buf = STRBUF_INIT; 847 848 for_each_string_list_item(item, &existing->kept_packs) { 849 strbuf_reset(&buf); 850 strbuf_addf(&buf, "%s.idx", item->string); 851 string_list_insert(include, buf.buf); 852 } 853 854 for_each_string_list_item(item, names) { 855 strbuf_reset(&buf); 856 strbuf_addf(&buf, "pack-%s.idx", item->string); 857 string_list_insert(include, buf.buf); 858 } 859 860 if (geometry->split_factor) { 861 uint32_t i; 862 863 for (i = geometry->split; i < geometry->pack_nr; i++) { 864 struct packed_git *p = geometry->pack[i]; 865 866 /* 867 * The multi-pack index never refers to packfiles part 868 * of an alternate object database, so we skip these. 869 * While git-multi-pack-index(1) would silently ignore 870 * them anyway, this allows us to skip executing the 871 * command completely when we have only non-local 872 * packfiles. 873 */ 874 if (!p->pack_local) 875 continue; 876 877 strbuf_reset(&buf); 878 strbuf_addstr(&buf, pack_basename(p)); 879 strbuf_strip_suffix(&buf, ".pack"); 880 strbuf_addstr(&buf, ".idx"); 881 882 string_list_insert(include, buf.buf); 883 } 884 } else { 885 for_each_string_list_item(item, &existing->non_kept_packs) { 886 if (pack_is_marked_for_deletion(item)) 887 continue; 888 889 strbuf_reset(&buf); 890 strbuf_addf(&buf, "%s.idx", item->string); 891 string_list_insert(include, buf.buf); 892 } 893 } 894 895 if (midx_must_contain_cruft || 896 midx_has_unknown_packs(midx_pack_names, midx_pack_names_nr, 897 include, geometry, existing)) { 898 /* 899 * If there are one or more unknown pack(s) present (see 900 * midx_has_unknown_packs() for what makes a pack 901 * "unknown") in the MIDX before the repack, keep them 902 * as they may be required to form a reachability 903 * closure if the MIDX is bitmapped. 904 * 905 * For example, a cruft pack can be required to form a 906 * reachability closure if the MIDX is bitmapped and one 907 * or more of the bitmap's selected commits reaches a 908 * once-cruft object that was later made reachable. 909 */ 910 for_each_string_list_item(item, &existing->cruft_packs) { 911 /* 912 * When doing a --geometric repack, there is no 913 * need to check for deleted packs, since we're 914 * by definition not doing an ALL_INTO_ONE 915 * repack (hence no packs will be deleted). 916 * Otherwise we must check for and exclude any 917 * packs which are enqueued for deletion. 918 * 919 * So we could omit the conditional below in the 920 * --geometric case, but doing so is unnecessary 921 * since no packs are marked as pending 922 * deletion (since we only call 923 * `mark_packs_for_deletion()` when doing an 924 * all-into-one repack). 925 */ 926 if (pack_is_marked_for_deletion(item)) 927 continue; 928 929 strbuf_reset(&buf); 930 strbuf_addf(&buf, "%s.idx", item->string); 931 string_list_insert(include, buf.buf); 932 } 933 } else { 934 /* 935 * Modern versions of Git (with the appropriate 936 * configuration setting) will write new copies of 937 * once-cruft objects when doing a --geometric repack. 938 * 939 * If the MIDX has no cruft pack, new packs written 940 * during a --geometric repack will not rely on the 941 * cruft pack to form a reachability closure, so we can 942 * avoid including them in the MIDX in that case. 943 */ 944 ; 945 } 946 947 strbuf_release(&buf); 948} 949 950static int write_midx_included_packs(struct string_list *include, 951 struct pack_geometry *geometry, 952 struct string_list *names, 953 const char *refs_snapshot, 954 int show_progress, int write_bitmaps) 955{ 956 struct child_process cmd = CHILD_PROCESS_INIT; 957 struct string_list_item *item; 958 struct packed_git *preferred = get_preferred_pack(geometry); 959 FILE *in; 960 int ret; 961 962 if (!include->nr) 963 return 0; 964 965 cmd.in = -1; 966 cmd.git_cmd = 1; 967 968 strvec_push(&cmd.args, "multi-pack-index"); 969 strvec_pushl(&cmd.args, "write", "--stdin-packs", NULL); 970 971 if (show_progress) 972 strvec_push(&cmd.args, "--progress"); 973 else 974 strvec_push(&cmd.args, "--no-progress"); 975 976 if (write_bitmaps) 977 strvec_push(&cmd.args, "--bitmap"); 978 979 if (preferred) 980 strvec_pushf(&cmd.args, "--preferred-pack=%s", 981 pack_basename(preferred)); 982 else if (names->nr) { 983 /* The largest pack was repacked, meaning that either 984 * one or two packs exist depending on whether the 985 * repository has a cruft pack or not. 986 * 987 * Select the non-cruft one as preferred to encourage 988 * pack-reuse among packs containing reachable objects 989 * over unreachable ones. 990 * 991 * (Note we could write multiple packs here if 992 * `--max-pack-size` was given, but any one of them 993 * will suffice, so pick the first one.) 994 */ 995 for_each_string_list_item(item, names) { 996 struct generated_pack_data *data = item->util; 997 if (has_pack_ext(data, ".mtimes")) 998 continue; 999 1000 strvec_pushf(&cmd.args, "--preferred-pack=pack-%s.pack", 1001 item->string); 1002 break; 1003 } 1004 } else { 1005 /* 1006 * No packs were kept, and no packs were written. The 1007 * only thing remaining are .keep packs (unless 1008 * --pack-kept-objects was given). 1009 * 1010 * Set the `--preferred-pack` arbitrarily here. 1011 */ 1012 ; 1013 } 1014 1015 if (refs_snapshot) 1016 strvec_pushf(&cmd.args, "--refs-snapshot=%s", refs_snapshot); 1017 1018 ret = start_command(&cmd); 1019 if (ret) 1020 return ret; 1021 1022 in = xfdopen(cmd.in, "w"); 1023 for_each_string_list_item(item, include) 1024 fprintf(in, "%s\n", item->string); 1025 fclose(in); 1026 1027 return finish_command(&cmd); 1028} 1029 1030static void remove_redundant_bitmaps(struct string_list *include, 1031 const char *packdir) 1032{ 1033 struct strbuf path = STRBUF_INIT; 1034 struct string_list_item *item; 1035 size_t packdir_len; 1036 1037 strbuf_addstr(&path, packdir); 1038 strbuf_addch(&path, '/'); 1039 packdir_len = path.len; 1040 1041 /* 1042 * Remove any pack bitmaps corresponding to packs which are now 1043 * included in the MIDX. 1044 */ 1045 for_each_string_list_item(item, include) { 1046 strbuf_addstr(&path, item->string); 1047 strbuf_strip_suffix(&path, ".idx"); 1048 strbuf_addstr(&path, ".bitmap"); 1049 1050 if (unlink(path.buf) && errno != ENOENT) 1051 warning_errno(_("could not remove stale bitmap: %s"), 1052 path.buf); 1053 1054 strbuf_setlen(&path, packdir_len); 1055 } 1056 strbuf_release(&path); 1057} 1058 1059static int finish_pack_objects_cmd(struct child_process *cmd, 1060 struct string_list *names, 1061 int local) 1062{ 1063 FILE *out; 1064 struct strbuf line = STRBUF_INIT; 1065 1066 out = xfdopen(cmd->out, "r"); 1067 while (strbuf_getline_lf(&line, out) != EOF) { 1068 struct string_list_item *item; 1069 1070 if (line.len != the_hash_algo->hexsz) 1071 die(_("repack: Expecting full hex object ID lines only " 1072 "from pack-objects.")); 1073 /* 1074 * Avoid putting packs written outside of the repository in the 1075 * list of names. 1076 */ 1077 if (local) { 1078 item = string_list_append(names, line.buf); 1079 item->util = populate_pack_exts(line.buf); 1080 } 1081 } 1082 fclose(out); 1083 1084 strbuf_release(&line); 1085 1086 return finish_command(cmd); 1087} 1088 1089static int write_filtered_pack(const struct pack_objects_args *args, 1090 const char *destination, 1091 const char *pack_prefix, 1092 struct existing_packs *existing, 1093 struct string_list *names) 1094{ 1095 struct child_process cmd = CHILD_PROCESS_INIT; 1096 struct string_list_item *item; 1097 FILE *in; 1098 int ret; 1099 const char *caret; 1100 const char *scratch; 1101 int local = skip_prefix(destination, packdir, &scratch); 1102 1103 prepare_pack_objects(&cmd, args, destination); 1104 1105 strvec_push(&cmd.args, "--stdin-packs"); 1106 1107 if (!pack_kept_objects) 1108 strvec_push(&cmd.args, "--honor-pack-keep"); 1109 for_each_string_list_item(item, &existing->kept_packs) 1110 strvec_pushf(&cmd.args, "--keep-pack=%s", item->string); 1111 1112 cmd.in = -1; 1113 1114 ret = start_command(&cmd); 1115 if (ret) 1116 return ret; 1117 1118 /* 1119 * Here 'names' contains only the pack(s) that were just 1120 * written, which is exactly the packs we want to keep. Also 1121 * 'existing_kept_packs' already contains the packs in 1122 * 'keep_pack_list'. 1123 */ 1124 in = xfdopen(cmd.in, "w"); 1125 for_each_string_list_item(item, names) 1126 fprintf(in, "^%s-%s.pack\n", pack_prefix, item->string); 1127 for_each_string_list_item(item, &existing->non_kept_packs) 1128 fprintf(in, "%s.pack\n", item->string); 1129 for_each_string_list_item(item, &existing->cruft_packs) 1130 fprintf(in, "%s.pack\n", item->string); 1131 caret = pack_kept_objects ? "" : "^"; 1132 for_each_string_list_item(item, &existing->kept_packs) 1133 fprintf(in, "%s%s.pack\n", caret, item->string); 1134 fclose(in); 1135 1136 return finish_pack_objects_cmd(&cmd, names, local); 1137} 1138 1139static void combine_small_cruft_packs(FILE *in, size_t combine_cruft_below_size, 1140 struct existing_packs *existing) 1141{ 1142 struct packfile_store *packs = the_repository->objects->packfiles; 1143 struct packed_git *p; 1144 struct strbuf buf = STRBUF_INIT; 1145 size_t i; 1146 1147 for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 1148 if (!(p->is_cruft && p->pack_local)) 1149 continue; 1150 1151 strbuf_reset(&buf); 1152 strbuf_addstr(&buf, pack_basename(p)); 1153 strbuf_strip_suffix(&buf, ".pack"); 1154 1155 if (!string_list_has_string(&existing->cruft_packs, buf.buf)) 1156 continue; 1157 1158 if (p->pack_size < combine_cruft_below_size) { 1159 fprintf(in, "-%s\n", pack_basename(p)); 1160 } else { 1161 retain_cruft_pack(existing, p); 1162 fprintf(in, "%s\n", pack_basename(p)); 1163 } 1164 } 1165 1166 for (i = 0; i < existing->non_kept_packs.nr; i++) 1167 fprintf(in, "-%s.pack\n", 1168 existing->non_kept_packs.items[i].string); 1169 1170 strbuf_release(&buf); 1171} 1172 1173static int write_cruft_pack(const struct pack_objects_args *args, 1174 const char *destination, 1175 const char *pack_prefix, 1176 const char *cruft_expiration, 1177 unsigned long combine_cruft_below_size, 1178 struct string_list *names, 1179 struct existing_packs *existing) 1180{ 1181 struct child_process cmd = CHILD_PROCESS_INIT; 1182 struct string_list_item *item; 1183 FILE *in; 1184 int ret; 1185 const char *scratch; 1186 int local = skip_prefix(destination, packdir, &scratch); 1187 1188 prepare_pack_objects(&cmd, args, destination); 1189 1190 strvec_push(&cmd.args, "--cruft"); 1191 if (cruft_expiration) 1192 strvec_pushf(&cmd.args, "--cruft-expiration=%s", 1193 cruft_expiration); 1194 1195 strvec_push(&cmd.args, "--honor-pack-keep"); 1196 strvec_push(&cmd.args, "--non-empty"); 1197 1198 cmd.in = -1; 1199 1200 ret = start_command(&cmd); 1201 if (ret) 1202 return ret; 1203 1204 /* 1205 * names has a confusing double use: it both provides the list 1206 * of just-written new packs, and accepts the name of the cruft 1207 * pack we are writing. 1208 * 1209 * By the time it is read here, it contains only the pack(s) 1210 * that were just written, which is exactly the set of packs we 1211 * want to consider kept. 1212 * 1213 * If `--expire-to` is given, the double-use served by `names` 1214 * ensures that the pack written to `--expire-to` excludes any 1215 * objects contained in the cruft pack. 1216 */ 1217 in = xfdopen(cmd.in, "w"); 1218 for_each_string_list_item(item, names) 1219 fprintf(in, "%s-%s.pack\n", pack_prefix, item->string); 1220 if (combine_cruft_below_size && !cruft_expiration) { 1221 combine_small_cruft_packs(in, combine_cruft_below_size, 1222 existing); 1223 } else { 1224 for_each_string_list_item(item, &existing->non_kept_packs) 1225 fprintf(in, "-%s.pack\n", item->string); 1226 for_each_string_list_item(item, &existing->cruft_packs) 1227 fprintf(in, "-%s.pack\n", item->string); 1228 } 1229 for_each_string_list_item(item, &existing->kept_packs) 1230 fprintf(in, "%s.pack\n", item->string); 1231 fclose(in); 1232 1233 return finish_pack_objects_cmd(&cmd, names, local); 1234} 1235 1236static const char *find_pack_prefix(const char *packdir, const char *packtmp) 1237{ 1238 const char *pack_prefix; 1239 if (!skip_prefix(packtmp, packdir, &pack_prefix)) 1240 die(_("pack prefix %s does not begin with objdir %s"), 1241 packtmp, packdir); 1242 if (*pack_prefix == '/') 1243 pack_prefix++; 1244 return pack_prefix; 1245} 1246 1247int cmd_repack(int argc, 1248 const char **argv, 1249 const char *prefix, 1250 struct repository *repo UNUSED) 1251{ 1252 struct child_process cmd = CHILD_PROCESS_INIT; 1253 struct string_list_item *item; 1254 struct string_list names = STRING_LIST_INIT_DUP; 1255 struct existing_packs existing = EXISTING_PACKS_INIT; 1256 struct pack_geometry geometry = { 0 }; 1257 struct tempfile *refs_snapshot = NULL; 1258 int i, ext, ret; 1259 int show_progress; 1260 char **midx_pack_names = NULL; 1261 size_t midx_pack_names_nr = 0; 1262 1263 /* variables to be filled by option parsing */ 1264 int delete_redundant = 0; 1265 const char *unpack_unreachable = NULL; 1266 int keep_unreachable = 0; 1267 struct string_list keep_pack_list = STRING_LIST_INIT_NODUP; 1268 struct pack_objects_args po_args = { 0 }; 1269 struct pack_objects_args cruft_po_args = { 0 }; 1270 int write_midx = 0; 1271 const char *cruft_expiration = NULL; 1272 const char *expire_to = NULL; 1273 const char *filter_to = NULL; 1274 const char *opt_window = NULL; 1275 const char *opt_window_memory = NULL; 1276 const char *opt_depth = NULL; 1277 const char *opt_threads = NULL; 1278 unsigned long combine_cruft_below_size = 0ul; 1279 1280 struct option builtin_repack_options[] = { 1281 OPT_BIT('a', NULL, &pack_everything, 1282 N_("pack everything in a single pack"), ALL_INTO_ONE), 1283 OPT_BIT('A', NULL, &pack_everything, 1284 N_("same as -a, and turn unreachable objects loose"), 1285 LOOSEN_UNREACHABLE | ALL_INTO_ONE), 1286 OPT_BIT(0, "cruft", &pack_everything, 1287 N_("same as -a, pack unreachable cruft objects separately"), 1288 PACK_CRUFT), 1289 OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"), 1290 N_("with --cruft, expire objects older than this")), 1291 OPT_UNSIGNED(0, "combine-cruft-below-size", 1292 &combine_cruft_below_size, 1293 N_("with --cruft, only repack cruft packs smaller than this")), 1294 OPT_UNSIGNED(0, "max-cruft-size", &cruft_po_args.max_pack_size, 1295 N_("with --cruft, limit the size of new cruft packs")), 1296 OPT_BOOL('d', NULL, &delete_redundant, 1297 N_("remove redundant packs, and run git-prune-packed")), 1298 OPT_BOOL('f', NULL, &po_args.no_reuse_delta, 1299 N_("pass --no-reuse-delta to git-pack-objects")), 1300 OPT_BOOL('F', NULL, &po_args.no_reuse_object, 1301 N_("pass --no-reuse-object to git-pack-objects")), 1302 OPT_INTEGER(0, "name-hash-version", &po_args.name_hash_version, 1303 N_("specify the name hash version to use for grouping similar objects by path")), 1304 OPT_BOOL(0, "path-walk", &po_args.path_walk, 1305 N_("pass --path-walk to git-pack-objects")), 1306 OPT_NEGBIT('n', NULL, &run_update_server_info, 1307 N_("do not run git-update-server-info"), 1), 1308 OPT__QUIET(&po_args.quiet, N_("be quiet")), 1309 OPT_BOOL('l', "local", &po_args.local, 1310 N_("pass --local to git-pack-objects")), 1311 OPT_BOOL('b', "write-bitmap-index", &write_bitmaps, 1312 N_("write bitmap index")), 1313 OPT_BOOL('i', "delta-islands", &use_delta_islands, 1314 N_("pass --delta-islands to git-pack-objects")), 1315 OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"), 1316 N_("with -A, do not loosen objects older than this")), 1317 OPT_BOOL('k', "keep-unreachable", &keep_unreachable, 1318 N_("with -a, repack unreachable objects")), 1319 OPT_STRING(0, "window", &opt_window, N_("n"), 1320 N_("size of the window used for delta compression")), 1321 OPT_STRING(0, "window-memory", &opt_window_memory, N_("bytes"), 1322 N_("same as the above, but limit memory size instead of entries count")), 1323 OPT_STRING(0, "depth", &opt_depth, N_("n"), 1324 N_("limits the maximum delta depth")), 1325 OPT_STRING(0, "threads", &opt_threads, N_("n"), 1326 N_("limits the maximum number of threads")), 1327 OPT_UNSIGNED(0, "max-pack-size", &po_args.max_pack_size, 1328 N_("maximum size of each packfile")), 1329 OPT_PARSE_LIST_OBJECTS_FILTER(&po_args.filter_options), 1330 OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects, 1331 N_("repack objects in packs marked with .keep")), 1332 OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"), 1333 N_("do not repack this pack")), 1334 OPT_INTEGER('g', "geometric", &geometry.split_factor, 1335 N_("find a geometric progression with factor <N>")), 1336 OPT_BOOL('m', "write-midx", &write_midx, 1337 N_("write a multi-pack index of the resulting packs")), 1338 OPT_STRING(0, "expire-to", &expire_to, N_("dir"), 1339 N_("pack prefix to store a pack containing pruned objects")), 1340 OPT_STRING(0, "filter-to", &filter_to, N_("dir"), 1341 N_("pack prefix to store a pack containing filtered out objects")), 1342 OPT_END() 1343 }; 1344 1345 list_objects_filter_init(&po_args.filter_options); 1346 1347 repo_config(the_repository, repack_config, &cruft_po_args); 1348 1349 argc = parse_options(argc, argv, prefix, builtin_repack_options, 1350 git_repack_usage, 0); 1351 1352 po_args.window = xstrdup_or_null(opt_window); 1353 po_args.window_memory = xstrdup_or_null(opt_window_memory); 1354 po_args.depth = xstrdup_or_null(opt_depth); 1355 po_args.threads = xstrdup_or_null(opt_threads); 1356 1357 if (delete_redundant && the_repository->repository_format_precious_objects) 1358 die(_("cannot delete packs in a precious-objects repo")); 1359 1360 die_for_incompatible_opt3(unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE), "-A", 1361 keep_unreachable, "-k/--keep-unreachable", 1362 pack_everything & PACK_CRUFT, "--cruft"); 1363 1364 if (pack_everything & PACK_CRUFT) 1365 pack_everything |= ALL_INTO_ONE; 1366 1367 if (write_bitmaps < 0) { 1368 if (!write_midx && 1369 (!(pack_everything & ALL_INTO_ONE) || !is_bare_repository())) 1370 write_bitmaps = 0; 1371 } 1372 if (pack_kept_objects < 0) 1373 pack_kept_objects = write_bitmaps > 0 && !write_midx; 1374 1375 if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) && !write_midx) 1376 die(_(incremental_bitmap_conflict_error)); 1377 1378 if (write_bitmaps && po_args.local && 1379 odb_has_alternates(the_repository->objects)) { 1380 /* 1381 * When asked to do a local repack, but we have 1382 * packfiles that are inherited from an alternate, then 1383 * we cannot guarantee that the multi-pack-index would 1384 * have full coverage of all objects. We thus disable 1385 * writing bitmaps in that case. 1386 */ 1387 warning(_("disabling bitmap writing, as some objects are not being packed")); 1388 write_bitmaps = 0; 1389 } 1390 1391 if (write_midx && write_bitmaps) { 1392 struct strbuf path = STRBUF_INIT; 1393 1394 strbuf_addf(&path, "%s/%s_XXXXXX", repo_get_object_directory(the_repository), 1395 "bitmap-ref-tips"); 1396 1397 refs_snapshot = xmks_tempfile(path.buf); 1398 midx_snapshot_refs(refs_snapshot); 1399 1400 strbuf_release(&path); 1401 } 1402 1403 packdir = mkpathdup("%s/pack", repo_get_object_directory(the_repository)); 1404 packtmp_name = xstrfmt(".tmp-%d-pack", (int)getpid()); 1405 packtmp = mkpathdup("%s/%s", packdir, packtmp_name); 1406 1407 collect_pack_filenames(&existing, &keep_pack_list); 1408 1409 if (geometry.split_factor) { 1410 if (pack_everything) 1411 die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a"); 1412 init_pack_geometry(&geometry, &existing, &po_args); 1413 split_pack_geometry(&geometry); 1414 } 1415 1416 prepare_pack_objects(&cmd, &po_args, packtmp); 1417 1418 show_progress = !po_args.quiet && isatty(2); 1419 1420 strvec_push(&cmd.args, "--keep-true-parents"); 1421 if (!pack_kept_objects) 1422 strvec_push(&cmd.args, "--honor-pack-keep"); 1423 for (i = 0; i < keep_pack_list.nr; i++) 1424 strvec_pushf(&cmd.args, "--keep-pack=%s", 1425 keep_pack_list.items[i].string); 1426 strvec_push(&cmd.args, "--non-empty"); 1427 if (!geometry.split_factor) { 1428 /* 1429 * We need to grab all reachable objects, including those that 1430 * are reachable from reflogs and the index. 1431 * 1432 * When repacking into a geometric progression of packs, 1433 * however, we ask 'git pack-objects --stdin-packs', and it is 1434 * not about packing objects based on reachability but about 1435 * repacking all the objects in specified packs and loose ones 1436 * (indeed, --stdin-packs is incompatible with these options). 1437 */ 1438 strvec_push(&cmd.args, "--all"); 1439 strvec_push(&cmd.args, "--reflog"); 1440 strvec_push(&cmd.args, "--indexed-objects"); 1441 } 1442 if (repo_has_promisor_remote(the_repository)) 1443 strvec_push(&cmd.args, "--exclude-promisor-objects"); 1444 if (!write_midx) { 1445 if (write_bitmaps > 0) 1446 strvec_push(&cmd.args, "--write-bitmap-index"); 1447 else if (write_bitmaps < 0) 1448 strvec_push(&cmd.args, "--write-bitmap-index-quiet"); 1449 } 1450 if (use_delta_islands) 1451 strvec_push(&cmd.args, "--delta-islands"); 1452 1453 if (pack_everything & ALL_INTO_ONE) { 1454 repack_promisor_objects(&po_args, &names); 1455 1456 if (has_existing_non_kept_packs(&existing) && 1457 delete_redundant && 1458 !(pack_everything & PACK_CRUFT)) { 1459 for_each_string_list_item(item, &names) { 1460 strvec_pushf(&cmd.args, "--keep-pack=%s-%s.pack", 1461 packtmp_name, item->string); 1462 } 1463 if (unpack_unreachable) { 1464 strvec_pushf(&cmd.args, 1465 "--unpack-unreachable=%s", 1466 unpack_unreachable); 1467 } else if (pack_everything & LOOSEN_UNREACHABLE) { 1468 strvec_push(&cmd.args, 1469 "--unpack-unreachable"); 1470 } else if (keep_unreachable) { 1471 strvec_push(&cmd.args, "--keep-unreachable"); 1472 } 1473 } 1474 1475 if (keep_unreachable && delete_redundant && 1476 !(pack_everything & PACK_CRUFT)) 1477 strvec_push(&cmd.args, "--pack-loose-unreachable"); 1478 } else if (geometry.split_factor) { 1479 if (midx_must_contain_cruft) 1480 strvec_push(&cmd.args, "--stdin-packs"); 1481 else 1482 strvec_push(&cmd.args, "--stdin-packs=follow"); 1483 strvec_push(&cmd.args, "--unpacked"); 1484 } else { 1485 strvec_push(&cmd.args, "--unpacked"); 1486 strvec_push(&cmd.args, "--incremental"); 1487 } 1488 1489 if (po_args.filter_options.choice) 1490 strvec_pushf(&cmd.args, "--filter=%s", 1491 expand_list_objects_filter_spec(&po_args.filter_options)); 1492 else if (filter_to) 1493 die(_("option '%s' can only be used along with '%s'"), "--filter-to", "--filter"); 1494 1495 if (geometry.split_factor) 1496 cmd.in = -1; 1497 else 1498 cmd.no_stdin = 1; 1499 1500 ret = start_command(&cmd); 1501 if (ret) 1502 goto cleanup; 1503 1504 if (geometry.split_factor) { 1505 FILE *in = xfdopen(cmd.in, "w"); 1506 /* 1507 * The resulting pack should contain all objects in packs that 1508 * are going to be rolled up, but exclude objects in packs which 1509 * are being left alone. 1510 */ 1511 for (i = 0; i < geometry.split; i++) 1512 fprintf(in, "%s\n", pack_basename(geometry.pack[i])); 1513 for (i = geometry.split; i < geometry.pack_nr; i++) 1514 fprintf(in, "^%s\n", pack_basename(geometry.pack[i])); 1515 fclose(in); 1516 } 1517 1518 ret = finish_pack_objects_cmd(&cmd, &names, 1); 1519 if (ret) 1520 goto cleanup; 1521 1522 if (!names.nr) { 1523 if (!po_args.quiet) 1524 printf_ln(_("Nothing new to pack.")); 1525 /* 1526 * If we didn't write any new packs, the non-cruft packs 1527 * may refer to once-unreachable objects in the cruft 1528 * pack(s). 1529 * 1530 * If there isn't already a MIDX, the one we write 1531 * must include the cruft pack(s), in case the 1532 * non-cruft pack(s) refer to once-cruft objects. 1533 * 1534 * If there is already a MIDX, we can punt here, since 1535 * midx_has_unknown_packs() will make the decision for 1536 * us. 1537 */ 1538 if (!get_multi_pack_index(the_repository->objects->sources)) 1539 midx_must_contain_cruft = 1; 1540 } 1541 1542 if (pack_everything & PACK_CRUFT) { 1543 const char *pack_prefix = find_pack_prefix(packdir, packtmp); 1544 1545 if (!cruft_po_args.window) 1546 cruft_po_args.window = xstrdup_or_null(po_args.window); 1547 if (!cruft_po_args.window_memory) 1548 cruft_po_args.window_memory = xstrdup_or_null(po_args.window_memory); 1549 if (!cruft_po_args.depth) 1550 cruft_po_args.depth = xstrdup_or_null(po_args.depth); 1551 if (!cruft_po_args.threads) 1552 cruft_po_args.threads = xstrdup_or_null(po_args.threads); 1553 if (!cruft_po_args.max_pack_size) 1554 cruft_po_args.max_pack_size = po_args.max_pack_size; 1555 1556 cruft_po_args.local = po_args.local; 1557 cruft_po_args.quiet = po_args.quiet; 1558 1559 ret = write_cruft_pack(&cruft_po_args, packtmp, pack_prefix, 1560 cruft_expiration, 1561 combine_cruft_below_size, &names, 1562 &existing); 1563 if (ret) 1564 goto cleanup; 1565 1566 if (delete_redundant && expire_to) { 1567 /* 1568 * If `--expire-to` is given with `-d`, it's possible 1569 * that we're about to prune some objects. With cruft 1570 * packs, pruning is implicit: any objects from existing 1571 * packs that weren't picked up by new packs are removed 1572 * when their packs are deleted. 1573 * 1574 * Generate an additional cruft pack, with one twist: 1575 * `names` now includes the name of the cruft pack 1576 * written in the previous step. So the contents of 1577 * _this_ cruft pack exclude everything contained in the 1578 * existing cruft pack (that is, all of the unreachable 1579 * objects which are no older than 1580 * `--cruft-expiration`). 1581 * 1582 * To make this work, cruft_expiration must become NULL 1583 * so that this cruft pack doesn't actually prune any 1584 * objects. If it were non-NULL, this call would always 1585 * generate an empty pack (since every object not in the 1586 * cruft pack generated above will have an mtime older 1587 * than the expiration). 1588 * 1589 * Pretend we don't have a `--combine-cruft-below-size` 1590 * argument, since we're not selectively combining 1591 * anything based on size to generate the limbo cruft 1592 * pack, but rather removing all cruft packs from the 1593 * main repository regardless of size. 1594 */ 1595 ret = write_cruft_pack(&cruft_po_args, expire_to, 1596 pack_prefix, 1597 NULL, 1598 0ul, 1599 &names, 1600 &existing); 1601 if (ret) 1602 goto cleanup; 1603 } 1604 } 1605 1606 if (po_args.filter_options.choice) { 1607 if (!filter_to) 1608 filter_to = packtmp; 1609 1610 ret = write_filtered_pack(&po_args, 1611 filter_to, 1612 find_pack_prefix(packdir, packtmp), 1613 &existing, 1614 &names); 1615 if (ret) 1616 goto cleanup; 1617 } 1618 1619 string_list_sort(&names); 1620 1621 if (get_multi_pack_index(the_repository->objects->sources)) { 1622 struct multi_pack_index *m = 1623 get_multi_pack_index(the_repository->objects->sources); 1624 1625 ALLOC_ARRAY(midx_pack_names, 1626 m->num_packs + m->num_packs_in_base); 1627 1628 for (; m; m = m->base_midx) 1629 for (uint32_t i = 0; i < m->num_packs; i++) 1630 midx_pack_names[midx_pack_names_nr++] = 1631 xstrdup(m->pack_names[i]); 1632 } 1633 1634 close_object_store(the_repository->objects); 1635 1636 /* 1637 * Ok we have prepared all new packfiles. 1638 */ 1639 for_each_string_list_item(item, &names) { 1640 struct generated_pack_data *data = item->util; 1641 1642 for (ext = 0; ext < ARRAY_SIZE(exts); ext++) { 1643 char *fname; 1644 1645 fname = mkpathdup("%s/pack-%s%s", 1646 packdir, item->string, exts[ext].name); 1647 1648 if (data->tempfiles[ext]) { 1649 const char *fname_old = get_tempfile_path(data->tempfiles[ext]); 1650 struct stat statbuffer; 1651 1652 if (!stat(fname_old, &statbuffer)) { 1653 statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); 1654 chmod(fname_old, statbuffer.st_mode); 1655 } 1656 1657 if (rename_tempfile(&data->tempfiles[ext], fname)) 1658 die_errno(_("renaming pack to '%s' failed"), fname); 1659 } else if (!exts[ext].optional) 1660 die(_("pack-objects did not write a '%s' file for pack %s-%s"), 1661 exts[ext].name, packtmp, item->string); 1662 else if (unlink(fname) < 0 && errno != ENOENT) 1663 die_errno(_("could not unlink: %s"), fname); 1664 1665 free(fname); 1666 } 1667 } 1668 /* End of pack replacement. */ 1669 1670 if (delete_redundant && pack_everything & ALL_INTO_ONE) 1671 mark_packs_for_deletion(&existing, &names); 1672 1673 if (write_midx) { 1674 struct string_list include = STRING_LIST_INIT_DUP; 1675 midx_included_packs(&include, &existing, midx_pack_names, 1676 midx_pack_names_nr, &names, &geometry); 1677 1678 ret = write_midx_included_packs(&include, &geometry, &names, 1679 refs_snapshot ? get_tempfile_path(refs_snapshot) : NULL, 1680 show_progress, write_bitmaps > 0); 1681 1682 if (!ret && write_bitmaps) 1683 remove_redundant_bitmaps(&include, packdir); 1684 1685 string_list_clear(&include, 0); 1686 1687 if (ret) 1688 goto cleanup; 1689 } 1690 1691 odb_reprepare(the_repository->objects); 1692 1693 if (delete_redundant) { 1694 int opts = 0; 1695 remove_redundant_existing_packs(&existing); 1696 1697 if (geometry.split_factor) 1698 geometry_remove_redundant_packs(&geometry, &names, 1699 &existing); 1700 if (show_progress) 1701 opts |= PRUNE_PACKED_VERBOSE; 1702 prune_packed_objects(opts); 1703 1704 if (!keep_unreachable && 1705 (!(pack_everything & LOOSEN_UNREACHABLE) || 1706 unpack_unreachable) && 1707 is_repository_shallow(the_repository)) 1708 prune_shallow(PRUNE_QUICK); 1709 } 1710 1711 if (run_update_server_info) 1712 update_server_info(the_repository, 0); 1713 1714 if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0)) { 1715 unsigned flags = 0; 1716 if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0)) 1717 flags |= MIDX_WRITE_INCREMENTAL; 1718 write_midx_file(the_repository->objects->sources, 1719 NULL, NULL, flags); 1720 } 1721 1722cleanup: 1723 string_list_clear(&keep_pack_list, 0); 1724 string_list_clear(&names, 1); 1725 existing_packs_release(&existing); 1726 free_pack_geometry(&geometry); 1727 for (size_t i = 0; i < midx_pack_names_nr; i++) 1728 free(midx_pack_names[i]); 1729 free(midx_pack_names); 1730 pack_objects_args_release(&po_args); 1731 pack_objects_args_release(&cruft_po_args); 1732 1733 return ret; 1734}