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