Git fork
at reftables-rust 863 lines 24 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2 3#include "git-compat-util.h" 4#include "hex.h" 5#include "repository.h" 6#include "tempfile.h" 7#include "lockfile.h" 8#include "odb.h" 9#include "commit.h" 10#include "tag.h" 11#include "pkt-line.h" 12#include "refs.h" 13#include "oid-array.h" 14#include "path.h" 15#include "diff.h" 16#include "revision.h" 17#include "commit-slab.h" 18#include "list-objects.h" 19#include "commit-reach.h" 20#include "shallow.h" 21#include "statinfo.h" 22#include "trace.h" 23 24void set_alternate_shallow_file(struct repository *r, const char *path, int override) 25{ 26 if (r->parsed_objects->is_shallow != -1) 27 BUG("is_repository_shallow must not be called before set_alternate_shallow_file"); 28 if (r->parsed_objects->alternate_shallow_file && !override) 29 return; 30 free(r->parsed_objects->alternate_shallow_file); 31 r->parsed_objects->alternate_shallow_file = xstrdup_or_null(path); 32} 33 34int register_shallow(struct repository *r, const struct object_id *oid) 35{ 36 struct commit_graft *graft = 37 xmalloc(sizeof(struct commit_graft)); 38 struct commit *commit = lookup_commit(r, oid); 39 40 oidcpy(&graft->oid, oid); 41 graft->nr_parent = -1; 42 if (commit && commit->object.parsed) { 43 free_commit_list(commit->parents); 44 commit->parents = NULL; 45 } 46 return register_commit_graft(r, graft, 0); 47} 48 49int unregister_shallow(const struct object_id *oid) 50{ 51 int pos = commit_graft_pos(the_repository, oid); 52 if (pos < 0) 53 return -1; 54 free(the_repository->parsed_objects->grafts[pos]); 55 if (pos + 1 < the_repository->parsed_objects->grafts_nr) 56 MOVE_ARRAY(the_repository->parsed_objects->grafts + pos, 57 the_repository->parsed_objects->grafts + pos + 1, 58 the_repository->parsed_objects->grafts_nr - pos - 1); 59 the_repository->parsed_objects->grafts_nr--; 60 return 0; 61} 62 63int is_repository_shallow(struct repository *r) 64{ 65 FILE *fp; 66 char buf[1024]; 67 const char *path = r->parsed_objects->alternate_shallow_file; 68 69 if (r->parsed_objects->is_shallow >= 0) 70 return r->parsed_objects->is_shallow; 71 72 if (!path) 73 path = git_path_shallow(r); 74 /* 75 * fetch-pack sets '--shallow-file ""' as an indicator that no 76 * shallow file should be used. We could just open it and it 77 * will likely fail. But let's do an explicit check instead. 78 */ 79 if (!*path || (fp = fopen(path, "r")) == NULL) { 80 stat_validity_clear(r->parsed_objects->shallow_stat); 81 r->parsed_objects->is_shallow = 0; 82 return r->parsed_objects->is_shallow; 83 } 84 stat_validity_update(r->parsed_objects->shallow_stat, fileno(fp)); 85 r->parsed_objects->is_shallow = 1; 86 87 while (fgets(buf, sizeof(buf), fp)) { 88 struct object_id oid; 89 if (get_oid_hex(buf, &oid)) 90 die("bad shallow line: %s", buf); 91 register_shallow(r, &oid); 92 } 93 fclose(fp); 94 return r->parsed_objects->is_shallow; 95} 96 97static void reset_repository_shallow(struct repository *r) 98{ 99 r->parsed_objects->is_shallow = -1; 100 stat_validity_clear(r->parsed_objects->shallow_stat); 101 parsed_object_pool_reset_commit_grafts(r->parsed_objects); 102} 103 104int commit_shallow_file(struct repository *r, struct shallow_lock *lk) 105{ 106 int res = commit_lock_file(&lk->lock); 107 reset_repository_shallow(r); 108 109 /* 110 * Update in-memory data structures with the new shallow information, 111 * including unparsing all commits that now have grafts. 112 */ 113 is_repository_shallow(r); 114 115 return res; 116} 117 118void rollback_shallow_file(struct repository *r, struct shallow_lock *lk) 119{ 120 rollback_lock_file(&lk->lock); 121 reset_repository_shallow(r); 122} 123 124/* 125 * TODO: use "int" elemtype instead of "int *" when/if commit-slab 126 * supports a "valid" flag. 127 */ 128define_commit_slab(commit_depth, int *); 129static void free_depth_in_slab(int **ptr) 130{ 131 FREE_AND_NULL(*ptr); 132} 133struct commit_list *get_shallow_commits(struct object_array *heads, int depth, 134 int shallow_flag, int not_shallow_flag) 135{ 136 size_t i = 0; 137 int cur_depth = 0; 138 struct commit_list *result = NULL; 139 struct object_array stack = OBJECT_ARRAY_INIT; 140 struct commit *commit = NULL; 141 struct commit_graft *graft; 142 struct commit_depth depths; 143 144 init_commit_depth(&depths); 145 while (commit || i < heads->nr || stack.nr) { 146 struct commit_list *p; 147 if (!commit) { 148 if (i < heads->nr) { 149 int **depth_slot; 150 commit = (struct commit *) 151 deref_tag(the_repository, 152 heads->objects[i++].item, 153 NULL, 0); 154 if (!commit || commit->object.type != OBJ_COMMIT) { 155 commit = NULL; 156 continue; 157 } 158 depth_slot = commit_depth_at(&depths, commit); 159 if (!*depth_slot) 160 *depth_slot = xmalloc(sizeof(int)); 161 **depth_slot = 0; 162 cur_depth = 0; 163 } else { 164 commit = (struct commit *) 165 object_array_pop(&stack); 166 cur_depth = **commit_depth_at(&depths, commit); 167 } 168 } 169 parse_commit_or_die(commit); 170 cur_depth++; 171 if ((depth != INFINITE_DEPTH && cur_depth >= depth) || 172 (is_repository_shallow(the_repository) && !commit->parents && 173 (graft = lookup_commit_graft(the_repository, &commit->object.oid)) != NULL && 174 graft->nr_parent < 0)) { 175 commit_list_insert(commit, &result); 176 commit->object.flags |= shallow_flag; 177 commit = NULL; 178 continue; 179 } 180 commit->object.flags |= not_shallow_flag; 181 for (p = commit->parents, commit = NULL; p; p = p->next) { 182 int **depth_slot = commit_depth_at(&depths, p->item); 183 if (!*depth_slot) { 184 *depth_slot = xmalloc(sizeof(int)); 185 **depth_slot = cur_depth; 186 } else { 187 if (cur_depth >= **depth_slot) 188 continue; 189 **depth_slot = cur_depth; 190 } 191 if (p->next) 192 add_object_array(&p->item->object, 193 NULL, &stack); 194 else { 195 commit = p->item; 196 cur_depth = **commit_depth_at(&depths, commit); 197 } 198 } 199 } 200 deep_clear_commit_depth(&depths, free_depth_in_slab); 201 202 return result; 203} 204 205static void show_commit(struct commit *commit, void *data) 206{ 207 commit_list_insert(commit, data); 208} 209 210/* 211 * Given rev-list arguments, run rev-list. All reachable commits 212 * except border ones are marked with not_shallow_flag. Border commits 213 * are marked with shallow_flag. The list of border/shallow commits 214 * are also returned. 215 */ 216struct commit_list *get_shallow_commits_by_rev_list(struct strvec *argv, 217 int shallow_flag, 218 int not_shallow_flag) 219{ 220 struct commit_list *result = NULL, *p; 221 struct commit_list *not_shallow_list = NULL; 222 struct rev_info revs; 223 int both_flags = shallow_flag | not_shallow_flag; 224 225 /* 226 * SHALLOW (excluded) and NOT_SHALLOW (included) should not be 227 * set at this point. But better be safe than sorry. 228 */ 229 clear_object_flags(the_repository, both_flags); 230 231 is_repository_shallow(the_repository); /* make sure shallows are read */ 232 233 repo_init_revisions(the_repository, &revs, NULL); 234 save_commit_buffer = 0; 235 setup_revisions_from_strvec(argv, &revs, NULL); 236 237 if (prepare_revision_walk(&revs)) 238 die("revision walk setup failed"); 239 traverse_commit_list(&revs, show_commit, NULL, &not_shallow_list); 240 241 if (!not_shallow_list) 242 die("no commits selected for shallow requests"); 243 244 /* Mark all reachable commits as NOT_SHALLOW */ 245 for (p = not_shallow_list; p; p = p->next) 246 p->item->object.flags |= not_shallow_flag; 247 248 /* 249 * mark border commits SHALLOW + NOT_SHALLOW. 250 * We cannot clear NOT_SHALLOW right now. Imagine border 251 * commit A is processed first, then commit B, whose parent is 252 * A, later. If NOT_SHALLOW on A is cleared at step 1, B 253 * itself is considered border at step 2, which is incorrect. 254 */ 255 for (p = not_shallow_list; p; p = p->next) { 256 struct commit *c = p->item; 257 struct commit_list *parent; 258 259 if (repo_parse_commit(the_repository, c)) 260 die("unable to parse commit %s", 261 oid_to_hex(&c->object.oid)); 262 263 for (parent = c->parents; parent; parent = parent->next) 264 if (!(parent->item->object.flags & not_shallow_flag)) { 265 c->object.flags |= shallow_flag; 266 commit_list_insert(c, &result); 267 break; 268 } 269 } 270 free_commit_list(not_shallow_list); 271 272 /* 273 * Now we can clean up NOT_SHALLOW on border commits. Having 274 * both flags set can confuse the caller. 275 */ 276 for (p = result; p; p = p->next) { 277 struct object *o = &p->item->object; 278 if ((o->flags & both_flags) == both_flags) 279 o->flags &= ~not_shallow_flag; 280 } 281 release_revisions(&revs); 282 return result; 283} 284 285static void check_shallow_file_for_update(struct repository *r) 286{ 287 if (r->parsed_objects->is_shallow == -1) 288 BUG("shallow must be initialized by now"); 289 290 if (!stat_validity_check(r->parsed_objects->shallow_stat, 291 git_path_shallow(r))) 292 die("shallow file has changed since we read it"); 293} 294 295#define SEEN_ONLY 1 296#define VERBOSE 2 297#define QUICK 4 298 299struct write_shallow_data { 300 struct strbuf *out; 301 int use_pack_protocol; 302 int count; 303 unsigned flags; 304}; 305 306static int write_one_shallow(const struct commit_graft *graft, void *cb_data) 307{ 308 struct write_shallow_data *data = cb_data; 309 const char *hex = oid_to_hex(&graft->oid); 310 if (graft->nr_parent != -1) 311 return 0; 312 if (data->flags & QUICK) { 313 if (!odb_has_object(the_repository->objects, &graft->oid, 314 HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) 315 return 0; 316 } else if (data->flags & SEEN_ONLY) { 317 struct commit *c = lookup_commit(the_repository, &graft->oid); 318 if (!c || !(c->object.flags & SEEN)) { 319 if (data->flags & VERBOSE) 320 printf("Removing %s from .git/shallow\n", 321 oid_to_hex(&c->object.oid)); 322 return 0; 323 } 324 } 325 data->count++; 326 if (data->use_pack_protocol) 327 packet_buf_write(data->out, "shallow %s", hex); 328 else { 329 strbuf_addstr(data->out, hex); 330 strbuf_addch(data->out, '\n'); 331 } 332 return 0; 333} 334 335static int write_shallow_commits_1(struct strbuf *out, int use_pack_protocol, 336 const struct oid_array *extra, 337 unsigned flags) 338{ 339 struct write_shallow_data data = { 340 .out = out, 341 .use_pack_protocol = use_pack_protocol, 342 .flags = flags, 343 }; 344 345 for_each_commit_graft(write_one_shallow, &data); 346 if (!extra) 347 return data.count; 348 for (size_t i = 0; i < extra->nr; i++) { 349 strbuf_addstr(out, oid_to_hex(extra->oid + i)); 350 strbuf_addch(out, '\n'); 351 data.count++; 352 } 353 return data.count; 354} 355 356int write_shallow_commits(struct strbuf *out, int use_pack_protocol, 357 const struct oid_array *extra) 358{ 359 return write_shallow_commits_1(out, use_pack_protocol, extra, 0); 360} 361 362const char *setup_temporary_shallow(const struct oid_array *extra) 363{ 364 struct tempfile *temp; 365 struct strbuf sb = STRBUF_INIT; 366 367 if (write_shallow_commits(&sb, 0, extra)) { 368 char *path = repo_git_path(the_repository, "shallow_XXXXXX"); 369 temp = xmks_tempfile(path); 370 free(path); 371 372 if (write_in_full(temp->fd, sb.buf, sb.len) < 0 || 373 close_tempfile_gently(temp) < 0) 374 die_errno("failed to write to %s", 375 get_tempfile_path(temp)); 376 strbuf_release(&sb); 377 return get_tempfile_path(temp); 378 } 379 /* 380 * is_repository_shallow() sees empty string as "no shallow 381 * file". 382 */ 383 return ""; 384} 385 386void setup_alternate_shallow(struct shallow_lock *shallow_lock, 387 const char **alternate_shallow_file, 388 const struct oid_array *extra) 389{ 390 struct strbuf sb = STRBUF_INIT; 391 int fd; 392 393 fd = hold_lock_file_for_update(&shallow_lock->lock, 394 git_path_shallow(the_repository), 395 LOCK_DIE_ON_ERROR); 396 check_shallow_file_for_update(the_repository); 397 if (write_shallow_commits(&sb, 0, extra)) { 398 if (write_in_full(fd, sb.buf, sb.len) < 0) 399 die_errno("failed to write to %s", 400 get_lock_file_path(&shallow_lock->lock)); 401 *alternate_shallow_file = get_lock_file_path(&shallow_lock->lock); 402 } else 403 /* 404 * is_repository_shallow() sees empty string as "no 405 * shallow file". 406 */ 407 *alternate_shallow_file = ""; 408 strbuf_release(&sb); 409} 410 411static int advertise_shallow_grafts_cb(const struct commit_graft *graft, void *cb) 412{ 413 int fd = *(int *)cb; 414 if (graft->nr_parent == -1) 415 packet_write_fmt(fd, "shallow %s\n", oid_to_hex(&graft->oid)); 416 return 0; 417} 418 419void advertise_shallow_grafts(int fd) 420{ 421 if (!is_repository_shallow(the_repository)) 422 return; 423 for_each_commit_graft(advertise_shallow_grafts_cb, &fd); 424} 425 426/* 427 * mark_reachable_objects() should have been run prior to this and all 428 * reachable commits marked as "SEEN", except when quick_prune is non-zero, 429 * in which case lines are excised from the shallow file if they refer to 430 * commits that do not exist (any longer). 431 */ 432void prune_shallow(unsigned options) 433{ 434 struct shallow_lock shallow_lock = SHALLOW_LOCK_INIT; 435 struct strbuf sb = STRBUF_INIT; 436 unsigned flags = SEEN_ONLY; 437 int fd; 438 439 if (options & PRUNE_QUICK) 440 flags |= QUICK; 441 442 if (options & PRUNE_SHOW_ONLY) { 443 flags |= VERBOSE; 444 write_shallow_commits_1(&sb, 0, NULL, flags); 445 strbuf_release(&sb); 446 return; 447 } 448 fd = hold_lock_file_for_update(&shallow_lock.lock, 449 git_path_shallow(the_repository), 450 LOCK_DIE_ON_ERROR); 451 check_shallow_file_for_update(the_repository); 452 if (write_shallow_commits_1(&sb, 0, NULL, flags)) { 453 if (write_in_full(fd, sb.buf, sb.len) < 0) 454 die_errno("failed to write to %s", 455 get_lock_file_path(&shallow_lock.lock)); 456 commit_shallow_file(the_repository, &shallow_lock); 457 } else { 458 unlink(git_path_shallow(the_repository)); 459 rollback_shallow_file(the_repository, &shallow_lock); 460 } 461 strbuf_release(&sb); 462} 463 464struct trace_key trace_shallow = TRACE_KEY_INIT(SHALLOW); 465 466/* 467 * Step 1, split sender shallow commits into "ours" and "theirs" 468 * Step 2, clean "ours" based on .git/shallow 469 */ 470void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa) 471{ 472 trace_printf_key(&trace_shallow, "shallow: prepare_shallow_info\n"); 473 memset(info, 0, sizeof(*info)); 474 info->shallow = sa; 475 if (!sa) 476 return; 477 ALLOC_ARRAY(info->ours, sa->nr); 478 ALLOC_ARRAY(info->theirs, sa->nr); 479 for (size_t i = 0; i < sa->nr; i++) { 480 if (odb_has_object(the_repository->objects, sa->oid + i, 481 HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { 482 struct commit_graft *graft; 483 graft = lookup_commit_graft(the_repository, 484 &sa->oid[i]); 485 if (graft && graft->nr_parent < 0) 486 continue; 487 info->ours[info->nr_ours++] = i; 488 } else 489 info->theirs[info->nr_theirs++] = i; 490 } 491} 492 493void clear_shallow_info(struct shallow_info *info) 494{ 495 if (info->used_shallow) { 496 for (size_t i = 0; i < info->shallow->nr; i++) 497 free(info->used_shallow[i]); 498 free(info->used_shallow); 499 } 500 501 free(info->need_reachability_test); 502 free(info->reachable); 503 free(info->shallow_ref); 504 free(info->ours); 505 free(info->theirs); 506} 507 508/* Step 4, remove non-existent ones in "theirs" after getting the pack */ 509 510void remove_nonexistent_theirs_shallow(struct shallow_info *info) 511{ 512 struct object_id *oid = info->shallow->oid; 513 size_t i, dst; 514 trace_printf_key(&trace_shallow, "shallow: remove_nonexistent_theirs_shallow\n"); 515 for (i = dst = 0; i < info->nr_theirs; i++) { 516 if (i != dst) 517 info->theirs[dst] = info->theirs[i]; 518 if (odb_has_object(the_repository->objects, oid + info->theirs[i], 519 HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) 520 dst++; 521 } 522 info->nr_theirs = dst; 523} 524 525define_commit_slab(ref_bitmap, uint32_t *); 526 527#define POOL_SIZE (512 * 1024) 528 529struct paint_info { 530 struct ref_bitmap ref_bitmap; 531 unsigned nr_bits; 532 char **pools; 533 char *free, *end; 534 unsigned pool_count; 535}; 536 537static uint32_t *paint_alloc(struct paint_info *info) 538{ 539 unsigned nr = DIV_ROUND_UP(info->nr_bits, 32); 540 unsigned size = nr * sizeof(uint32_t); 541 void *p; 542 if (!info->pool_count || info->end < info->free + size) { 543 if (size > POOL_SIZE) 544 BUG("pool size too small for %d in paint_alloc()", 545 size); 546 info->pool_count++; 547 REALLOC_ARRAY(info->pools, info->pool_count); 548 info->free = xmalloc(POOL_SIZE); 549 info->pools[info->pool_count - 1] = info->free; 550 info->end = info->free + POOL_SIZE; 551 } 552 p = info->free; 553 info->free += size; 554 return p; 555} 556 557/* 558 * Given a commit SHA-1, walk down to parents until either SEEN, 559 * UNINTERESTING or BOTTOM is hit. Set the id-th bit in ref_bitmap for 560 * all walked commits. 561 */ 562static void paint_down(struct paint_info *info, const struct object_id *oid, 563 unsigned int id) 564{ 565 unsigned int i, nr; 566 struct commit_list *head = NULL; 567 size_t bitmap_nr = DIV_ROUND_UP(info->nr_bits, 32); 568 size_t bitmap_size = st_mult(sizeof(uint32_t), bitmap_nr); 569 struct commit *c = lookup_commit_reference_gently(the_repository, oid, 570 1); 571 uint32_t *tmp; /* to be freed before return */ 572 uint32_t *bitmap; 573 574 if (!c) 575 return; 576 577 tmp = xmalloc(bitmap_size); 578 bitmap = paint_alloc(info); 579 memset(bitmap, 0, bitmap_size); 580 bitmap[id / 32] |= (1U << (id % 32)); 581 commit_list_insert(c, &head); 582 while (head) { 583 struct commit_list *p; 584 struct commit *c = pop_commit(&head); 585 uint32_t **refs = ref_bitmap_at(&info->ref_bitmap, c); 586 587 /* XXX check "UNINTERESTING" from pack bitmaps if available */ 588 if (c->object.flags & (SEEN | UNINTERESTING)) 589 continue; 590 else 591 c->object.flags |= SEEN; 592 593 if (!*refs) 594 *refs = bitmap; 595 else { 596 memcpy(tmp, *refs, bitmap_size); 597 for (i = 0; i < bitmap_nr; i++) 598 tmp[i] |= bitmap[i]; 599 if (memcmp(tmp, *refs, bitmap_size)) { 600 *refs = paint_alloc(info); 601 memcpy(*refs, tmp, bitmap_size); 602 } 603 } 604 605 if (c->object.flags & BOTTOM) 606 continue; 607 608 if (repo_parse_commit(the_repository, c)) 609 die("unable to parse commit %s", 610 oid_to_hex(&c->object.oid)); 611 612 for (p = c->parents; p; p = p->next) { 613 if (p->item->object.flags & SEEN) 614 continue; 615 commit_list_insert(p->item, &head); 616 } 617 } 618 619 nr = get_max_object_index(the_repository); 620 for (i = 0; i < nr; i++) { 621 struct object *o = get_indexed_object(the_repository, i); 622 if (o && o->type == OBJ_COMMIT) 623 o->flags &= ~SEEN; 624 } 625 626 free(tmp); 627} 628 629static int mark_uninteresting(const char *refname UNUSED, 630 const char *referent UNUSED, 631 const struct object_id *oid, 632 int flags UNUSED, 633 void *cb_data UNUSED) 634{ 635 struct commit *commit = lookup_commit_reference_gently(the_repository, 636 oid, 1); 637 if (!commit) 638 return 0; 639 commit->object.flags |= UNINTERESTING; 640 mark_parents_uninteresting(NULL, commit); 641 return 0; 642} 643 644static void post_assign_shallow(struct shallow_info *info, 645 struct ref_bitmap *ref_bitmap, 646 int *ref_status); 647/* 648 * Step 6(+7), associate shallow commits with new refs 649 * 650 * info->ref must be initialized before calling this function. 651 * 652 * If used is not NULL, it's an array of info->shallow->nr 653 * bitmaps. The n-th bit set in the m-th bitmap if ref[n] needs the 654 * m-th shallow commit from info->shallow. 655 * 656 * If used is NULL, "ours" and "theirs" are updated. And if ref_status 657 * is not NULL it's an array of ref->nr ints. ref_status[i] is true if 658 * the ref needs some shallow commits from either info->ours or 659 * info->theirs. 660 */ 661void assign_shallow_commits_to_refs(struct shallow_info *info, 662 uint32_t **used, int *ref_status) 663{ 664 struct object_id *oid = info->shallow->oid; 665 struct oid_array *ref = info->ref; 666 unsigned int i, nr; 667 size_t *shallow, nr_shallow = 0; 668 struct paint_info pi; 669 670 trace_printf_key(&trace_shallow, "shallow: assign_shallow_commits_to_refs\n"); 671 ALLOC_ARRAY(shallow, info->nr_ours + info->nr_theirs); 672 for (i = 0; i < info->nr_ours; i++) 673 shallow[nr_shallow++] = info->ours[i]; 674 for (i = 0; i < info->nr_theirs; i++) 675 shallow[nr_shallow++] = info->theirs[i]; 676 677 /* 678 * Prepare the commit graph to track what refs can reach what 679 * (new) shallow commits. 680 */ 681 nr = get_max_object_index(the_repository); 682 for (i = 0; i < nr; i++) { 683 struct object *o = get_indexed_object(the_repository, i); 684 if (!o || o->type != OBJ_COMMIT) 685 continue; 686 687 o->flags &= ~(UNINTERESTING | BOTTOM | SEEN); 688 } 689 690 memset(&pi, 0, sizeof(pi)); 691 init_ref_bitmap(&pi.ref_bitmap); 692 pi.nr_bits = ref->nr; 693 694 /* 695 * "--not --all" to cut short the traversal if new refs 696 * connect to old refs. If not (e.g. force ref updates) it'll 697 * have to go down to the current shallow commits. 698 */ 699 refs_head_ref(get_main_ref_store(the_repository), mark_uninteresting, 700 NULL); 701 refs_for_each_ref(get_main_ref_store(the_repository), 702 mark_uninteresting, NULL); 703 704 /* Mark potential bottoms so we won't go out of bound */ 705 for (i = 0; i < nr_shallow; i++) { 706 struct commit *c = lookup_commit(the_repository, 707 &oid[shallow[i]]); 708 c->object.flags |= BOTTOM; 709 } 710 711 for (i = 0; i < ref->nr; i++) 712 paint_down(&pi, ref->oid + i, i); 713 714 if (used) { 715 int bitmap_size = DIV_ROUND_UP(pi.nr_bits, 32) * sizeof(uint32_t); 716 memset(used, 0, sizeof(*used) * info->shallow->nr); 717 for (i = 0; i < nr_shallow; i++) { 718 const struct commit *c = lookup_commit(the_repository, 719 &oid[shallow[i]]); 720 uint32_t **map = ref_bitmap_at(&pi.ref_bitmap, c); 721 if (*map) 722 used[shallow[i]] = xmemdupz(*map, bitmap_size); 723 } 724 /* 725 * unreachable shallow commits are not removed from 726 * "ours" and "theirs". The user is supposed to run 727 * step 7 on every ref separately and not trust "ours" 728 * and "theirs" any more. 729 */ 730 } else 731 post_assign_shallow(info, &pi.ref_bitmap, ref_status); 732 733 clear_ref_bitmap(&pi.ref_bitmap); 734 for (i = 0; i < pi.pool_count; i++) 735 free(pi.pools[i]); 736 free(pi.pools); 737 free(shallow); 738} 739 740struct commit_array { 741 struct commit **commits; 742 size_t nr, alloc; 743}; 744 745static int add_ref(const char *refname UNUSED, 746 const char *referent UNUSED, 747 const struct object_id *oid, 748 int flags UNUSED, 749 void *cb_data) 750{ 751 struct commit_array *ca = cb_data; 752 ALLOC_GROW(ca->commits, ca->nr + 1, ca->alloc); 753 ca->commits[ca->nr] = lookup_commit_reference_gently(the_repository, 754 oid, 1); 755 if (ca->commits[ca->nr]) 756 ca->nr++; 757 return 0; 758} 759 760static void update_refstatus(int *ref_status, size_t nr, uint32_t *bitmap) 761{ 762 if (!ref_status) 763 return; 764 for (size_t i = 0; i < nr; i++) 765 if (bitmap[i / 32] & (1U << (i % 32))) 766 ref_status[i]++; 767} 768 769/* 770 * Step 7, reachability test on "ours" at commit level 771 */ 772static void post_assign_shallow(struct shallow_info *info, 773 struct ref_bitmap *ref_bitmap, 774 int *ref_status) 775{ 776 struct object_id *oid = info->shallow->oid; 777 struct commit *c; 778 uint32_t **bitmap; 779 size_t dst, i, j; 780 size_t bitmap_nr = DIV_ROUND_UP(info->ref->nr, 32); 781 struct commit_array ca; 782 783 trace_printf_key(&trace_shallow, "shallow: post_assign_shallow\n"); 784 if (ref_status) 785 memset(ref_status, 0, sizeof(*ref_status) * info->ref->nr); 786 787 /* Remove unreachable shallow commits from "theirs" */ 788 for (i = dst = 0; i < info->nr_theirs; i++) { 789 if (i != dst) 790 info->theirs[dst] = info->theirs[i]; 791 c = lookup_commit(the_repository, &oid[info->theirs[i]]); 792 bitmap = ref_bitmap_at(ref_bitmap, c); 793 if (!*bitmap) 794 continue; 795 for (j = 0; j < bitmap_nr; j++) 796 if (bitmap[0][j]) { 797 update_refstatus(ref_status, info->ref->nr, *bitmap); 798 dst++; 799 break; 800 } 801 } 802 info->nr_theirs = dst; 803 804 memset(&ca, 0, sizeof(ca)); 805 refs_head_ref(get_main_ref_store(the_repository), add_ref, &ca); 806 refs_for_each_ref(get_main_ref_store(the_repository), add_ref, &ca); 807 808 /* Remove unreachable shallow commits from "ours" */ 809 for (i = dst = 0; i < info->nr_ours; i++) { 810 if (i != dst) 811 info->ours[dst] = info->ours[i]; 812 c = lookup_commit(the_repository, &oid[info->ours[i]]); 813 bitmap = ref_bitmap_at(ref_bitmap, c); 814 if (!*bitmap) 815 continue; 816 for (j = 0; j < bitmap_nr; j++) 817 if (bitmap[0][j]) { 818 /* Step 7, reachability test at commit level */ 819 int ret = repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1); 820 if (ret < 0) 821 exit(128); 822 if (!ret) { 823 update_refstatus(ref_status, info->ref->nr, *bitmap); 824 dst++; 825 break; 826 } 827 } 828 } 829 info->nr_ours = dst; 830 831 free(ca.commits); 832} 833 834/* (Delayed) step 7, reachability test at commit level */ 835int delayed_reachability_test(struct shallow_info *si, int c) 836{ 837 if (si->need_reachability_test[c]) { 838 struct commit *commit = lookup_commit(the_repository, 839 &si->shallow->oid[c]); 840 841 if (!si->commits) { 842 struct commit_array ca; 843 844 memset(&ca, 0, sizeof(ca)); 845 refs_head_ref(get_main_ref_store(the_repository), 846 add_ref, &ca); 847 refs_for_each_ref(get_main_ref_store(the_repository), 848 add_ref, &ca); 849 si->commits = ca.commits; 850 si->nr_commits = ca.nr; 851 } 852 853 si->reachable[c] = repo_in_merge_bases_many(the_repository, 854 commit, 855 si->nr_commits, 856 si->commits, 857 1); 858 if (si->reachable[c] < 0) 859 exit(128); 860 si->need_reachability_test[c] = 0; 861 } 862 return si->reachable[c]; 863}