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