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