Line | Count | Source |
1 | | #define USE_THE_REPOSITORY_VARIABLE |
2 | | |
3 | | #include "git-compat-util.h" |
4 | | #include "commit.h" |
5 | | #include "commit-graph.h" |
6 | | #include "decorate.h" |
7 | | #include "hex.h" |
8 | | #include "prio-queue.h" |
9 | | #include "ref-filter.h" |
10 | | #include "revision.h" |
11 | | #include "tag.h" |
12 | | #include "commit-reach.h" |
13 | | #include "ewah/ewok.h" |
14 | | #include "trace2.h" |
15 | | |
16 | | /* Remember to update object flag allocation in object.h */ |
17 | 0 | #define PARENT1 (1u<<16) |
18 | 0 | #define PARENT2 (1u<<17) |
19 | 0 | #define STALE (1u<<18) |
20 | 0 | #define RESULT (1u<<19) |
21 | 0 | #define ENQUEUED (1u<<20) |
22 | | |
23 | | static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT | ENQUEUED); |
24 | | |
25 | | static int compare_commits_by_gen(const void *_a, const void *_b) |
26 | 0 | { |
27 | 0 | const struct commit *a = *(const struct commit * const *)_a; |
28 | 0 | const struct commit *b = *(const struct commit * const *)_b; |
29 | |
|
30 | 0 | timestamp_t generation_a = commit_graph_generation(a); |
31 | 0 | timestamp_t generation_b = commit_graph_generation(b); |
32 | |
|
33 | 0 | if (generation_a < generation_b) |
34 | 0 | return -1; |
35 | 0 | if (generation_a > generation_b) |
36 | 0 | return 1; |
37 | 0 | if (a->date < b->date) |
38 | 0 | return -1; |
39 | 0 | if (a->date > b->date) |
40 | 0 | return 1; |
41 | 0 | return 0; |
42 | 0 | } |
43 | | |
44 | | /* |
45 | | * A prio_queue with O(1) termination check. 'max_nonstale' tracks |
46 | | * the lowest-priority non-stale commit enqueued so far; once it is |
47 | | * popped, every remaining entry is known to be STALE. |
48 | | */ |
49 | | struct nonstale_queue { |
50 | | struct prio_queue pq; |
51 | | struct commit *max_nonstale; |
52 | | }; |
53 | | |
54 | | static void nonstale_queue_put(struct nonstale_queue *queue, |
55 | | struct commit *c) |
56 | 0 | { |
57 | 0 | struct commit *old = queue->max_nonstale; |
58 | |
|
59 | 0 | prio_queue_put(&queue->pq, c); |
60 | 0 | if (c->object.flags & STALE) |
61 | 0 | return; |
62 | 0 | if (!old || queue->pq.compare(old, c, queue->pq.cb_data) <= 0) |
63 | 0 | queue->max_nonstale = c; |
64 | 0 | } |
65 | | |
66 | | static struct commit *nonstale_queue_get(struct nonstale_queue *queue) |
67 | 0 | { |
68 | 0 | struct commit *commit = prio_queue_get(&queue->pq); |
69 | |
|
70 | 0 | if (commit == queue->max_nonstale) |
71 | 0 | queue->max_nonstale = NULL; |
72 | |
|
73 | 0 | return commit; |
74 | 0 | } |
75 | | |
76 | | static void clear_nonstale_queue(struct nonstale_queue *queue) |
77 | 0 | { |
78 | 0 | clear_prio_queue(&queue->pq); |
79 | 0 | queue->max_nonstale = NULL; |
80 | 0 | } |
81 | | |
82 | | /* |
83 | | * Priority queue with per-side commit counters for paint_down_to_common(). |
84 | | * Each non-stale queued commit occupies exactly one bucket: PARENT1-only, |
85 | | * PARENT2-only, or both (a pending merge-base candidate). |
86 | | */ |
87 | | struct paint_state { |
88 | | struct prio_queue queue; |
89 | | size_t parent1_count; |
90 | | size_t parent2_count; |
91 | | size_t mb_candidate_count; |
92 | | timestamp_t min_generation; |
93 | | timestamp_t last_gen; |
94 | | timestamp_t topo_ceiling; |
95 | | }; |
96 | | |
97 | | static void paint_count_update(struct paint_state *state, |
98 | | unsigned flags, int delta) |
99 | 0 | { |
100 | 0 | switch (flags & (PARENT1 | PARENT2 | STALE)) { |
101 | 0 | case PARENT1: |
102 | 0 | state->parent1_count += delta; |
103 | 0 | break; |
104 | | |
105 | 0 | case PARENT2: |
106 | 0 | state->parent2_count += delta; |
107 | 0 | break; |
108 | | |
109 | 0 | case PARENT1 | PARENT2: |
110 | 0 | state->mb_candidate_count += delta; |
111 | 0 | break; |
112 | | |
113 | 0 | case PARENT1 | PARENT2 | STALE: |
114 | 0 | break; |
115 | | |
116 | 0 | default: |
117 | 0 | BUG("unexpected paint state"); |
118 | 0 | } |
119 | 0 | } |
120 | | |
121 | | static void paint_queue_put(struct paint_state *state, |
122 | | struct commit *c, unsigned add_flags) |
123 | 0 | { |
124 | 0 | unsigned old_flags = c->object.flags; |
125 | 0 | c->object.flags |= add_flags; |
126 | |
|
127 | 0 | if (old_flags & ENQUEUED) { |
128 | 0 | paint_count_update(state, old_flags, -1); |
129 | 0 | paint_count_update(state, c->object.flags, 1); |
130 | 0 | } else { |
131 | 0 | c->object.flags |= ENQUEUED; |
132 | 0 | prio_queue_put(&state->queue, c); |
133 | 0 | paint_count_update(state, c->object.flags, 1); |
134 | 0 | } |
135 | 0 | } |
136 | | |
137 | | /* |
138 | | * Dequeue the next commit for the paint walk, or return NULL when |
139 | | * no more merge bases can be discovered. |
140 | | */ |
141 | | static struct commit *paint_queue_get(struct paint_state *state) |
142 | 0 | { |
143 | 0 | struct commit *commit = prio_queue_get(&state->queue); |
144 | 0 | timestamp_t generation; |
145 | |
|
146 | 0 | if (!commit) |
147 | 0 | return NULL; |
148 | | |
149 | 0 | commit->object.flags &= ~ENQUEUED; |
150 | 0 | generation = commit_graph_generation(commit); |
151 | |
|
152 | 0 | if (state->min_generation && generation > state->last_gen) |
153 | 0 | BUG("bad generation skip %"PRItime" > %"PRItime" at %s", |
154 | 0 | generation, state->last_gen, |
155 | 0 | oid_to_hex(&commit->object.oid)); |
156 | 0 | state->last_gen = generation; |
157 | | |
158 | | /* generation cutoff */ |
159 | 0 | if (generation < state->min_generation) |
160 | 0 | return NULL; |
161 | | |
162 | | /* |
163 | | * Check exit condition before decrementing: the counters |
164 | | * still include this commit, so the last non-stale commit |
165 | | * sees a non-zero count and is returned for processing. |
166 | | */ |
167 | 0 | if (!state->mb_candidate_count) { |
168 | | /* only stale entries remain */ |
169 | 0 | if (!state->parent1_count && !state->parent2_count) |
170 | 0 | return NULL; |
171 | | |
172 | | /* one side is exhausted */ |
173 | 0 | if ((!state->parent1_count || !state->parent2_count) && |
174 | 0 | generation < state->topo_ceiling) |
175 | 0 | return NULL; |
176 | 0 | } |
177 | | |
178 | 0 | paint_count_update(state, commit->object.flags, -1); |
179 | 0 | return commit; |
180 | 0 | } |
181 | | |
182 | | /* |
183 | | * See Documentation/technical/paint-down-to-common.adoc |
184 | | * |
185 | | * All input commits in one and twos[] must have been parsed! |
186 | | */ |
187 | | static int paint_down_to_common(struct repository *r, |
188 | | struct commit *one, int n, |
189 | | struct commit **twos, |
190 | | timestamp_t min_generation, |
191 | | enum merge_base_flags mb_flags, |
192 | | struct commit_list **result) |
193 | 0 | { |
194 | | /* |
195 | | * Generation ordering is required for the side-exhaustion and |
196 | | * single-result early exits, which rely on topological traversal |
197 | | * order (children visited before parents) in the ordered region. |
198 | | */ |
199 | 0 | struct paint_state state = { |
200 | 0 | .queue = { compare_commits_by_gen_then_commit_date } |
201 | 0 | }; |
202 | 0 | struct commit *commit; |
203 | 0 | int i; |
204 | 0 | int steps = 0; |
205 | 0 | struct commit_list **tail = result; |
206 | |
|
207 | 0 | state.min_generation = min_generation; |
208 | 0 | state.last_gen = GENERATION_NUMBER_INFINITY; |
209 | 0 | state.topo_ceiling = corrected_commit_dates_enabled(r) |
210 | 0 | ? GENERATION_NUMBER_INFINITY |
211 | 0 | : GENERATION_NUMBER_V1_MAX; |
212 | | |
213 | |
|
214 | 0 | one->object.flags |= PARENT1; |
215 | 0 | if (!n) { |
216 | 0 | commit_list_append(one, result); |
217 | 0 | return 0; |
218 | 0 | } |
219 | 0 | paint_queue_put(&state, one, 0); |
220 | |
|
221 | 0 | for (i = 0; i < n; i++) |
222 | 0 | paint_queue_put(&state, twos[i], PARENT2); |
223 | |
|
224 | 0 | while ((commit = paint_queue_get(&state))) { |
225 | 0 | struct commit_list *parents; |
226 | 0 | int flags; |
227 | 0 | steps++; |
228 | |
|
229 | 0 | flags = commit->object.flags & (PARENT1 | PARENT2 | STALE); |
230 | 0 | if (flags == (PARENT1 | PARENT2)) { |
231 | 0 | if (!(commit->object.flags & RESULT)) { |
232 | 0 | commit->object.flags |= RESULT; |
233 | 0 | tail = commit_list_append(commit, tail); |
234 | | /* |
235 | | * When the queue is generation-ordered, |
236 | | * no remaining common ancestor can be a |
237 | | * descendant of this one. |
238 | | */ |
239 | 0 | if (!(mb_flags & MERGE_BASE_FIND_ALL) && |
240 | 0 | state.last_gen < state.topo_ceiling) |
241 | 0 | break; |
242 | 0 | } |
243 | | /* Mark parents of a found merge stale */ |
244 | 0 | flags |= STALE; |
245 | 0 | } |
246 | 0 | parents = commit->parents; |
247 | 0 | while (parents) { |
248 | 0 | struct commit *p = parents->item; |
249 | 0 | parents = parents->next; |
250 | 0 | if ((p->object.flags & flags) == flags) |
251 | 0 | continue; |
252 | 0 | if (repo_parse_commit(r, p)) { |
253 | 0 | clear_prio_queue(&state.queue); |
254 | 0 | commit_list_free(*result); |
255 | 0 | *result = NULL; |
256 | | /* |
257 | | * At this stage, we know that the commit is |
258 | | * missing: `repo_parse_commit()` uses |
259 | | * `OBJECT_INFO_DIE_IF_CORRUPT` and therefore |
260 | | * corrupt commits would already have been |
261 | | * dispatched with a `die()`. |
262 | | */ |
263 | 0 | if (mb_flags & MERGE_BASE_IGNORE_MISSING_COMMITS) |
264 | 0 | return 0; |
265 | 0 | return error(_("could not parse commit %s"), |
266 | 0 | oid_to_hex(&p->object.oid)); |
267 | 0 | } |
268 | 0 | paint_queue_put(&state, p, flags); |
269 | 0 | } |
270 | 0 | } |
271 | | |
272 | 0 | clear_prio_queue(&state.queue); |
273 | 0 | trace2_data_intmax("paint_down_to_common", r, |
274 | 0 | "steps", steps); |
275 | 0 | commit_list_sort_by_date(result); |
276 | 0 | return 0; |
277 | 0 | } |
278 | | |
279 | | static int merge_bases_many(struct repository *r, |
280 | | struct commit *one, int n, |
281 | | struct commit **twos, |
282 | | enum merge_base_flags mb_flags, |
283 | | struct commit_list **result) |
284 | 0 | { |
285 | 0 | struct commit_list *list = NULL, **tail = result; |
286 | 0 | int i; |
287 | |
|
288 | 0 | for (i = 0; i < n; i++) { |
289 | 0 | if (one == twos[i]) { |
290 | | /* |
291 | | * We do not mark this even with RESULT so we do not |
292 | | * have to clean it up. |
293 | | */ |
294 | 0 | *result = commit_list_insert(one, result); |
295 | 0 | return 0; |
296 | 0 | } |
297 | 0 | } |
298 | | |
299 | 0 | if (!one) |
300 | 0 | return 0; |
301 | 0 | if (repo_parse_commit(r, one)) |
302 | 0 | return error(_("could not parse commit %s"), |
303 | 0 | oid_to_hex(&one->object.oid)); |
304 | 0 | for (i = 0; i < n; i++) { |
305 | 0 | if (!twos[i]) |
306 | 0 | return 0; |
307 | 0 | if (repo_parse_commit(r, twos[i])) |
308 | 0 | return error(_("could not parse commit %s"), |
309 | 0 | oid_to_hex(&twos[i]->object.oid)); |
310 | 0 | } |
311 | | |
312 | 0 | if (paint_down_to_common(r, one, n, twos, 0, mb_flags, &list)) { |
313 | 0 | commit_list_free(list); |
314 | 0 | return -1; |
315 | 0 | } |
316 | | |
317 | 0 | while (list) { |
318 | 0 | struct commit *commit = pop_commit(&list); |
319 | 0 | if (!(commit->object.flags & STALE)) |
320 | 0 | tail = commit_list_append(commit, tail); |
321 | 0 | } |
322 | 0 | commit_list_sort_by_date(result); |
323 | 0 | return 0; |
324 | 0 | } |
325 | | |
326 | | int get_octopus_merge_bases(struct commit_list *in, struct commit_list **result) |
327 | 0 | { |
328 | 0 | struct commit_list *i, *j, *k; |
329 | |
|
330 | 0 | if (!in) |
331 | 0 | return 0; |
332 | | |
333 | 0 | commit_list_insert(in->item, result); |
334 | |
|
335 | 0 | for (i = in->next; i; i = i->next) { |
336 | 0 | struct commit_list *new_commits = NULL, *end = NULL; |
337 | |
|
338 | 0 | for (j = *result; j; j = j->next) { |
339 | 0 | struct commit_list *bases = NULL; |
340 | 0 | if (repo_get_merge_bases(the_repository, i->item, |
341 | 0 | j->item, &bases) < 0) { |
342 | 0 | commit_list_free(bases); |
343 | 0 | commit_list_free(*result); |
344 | 0 | *result = NULL; |
345 | 0 | return -1; |
346 | 0 | } |
347 | 0 | if (!new_commits) |
348 | 0 | new_commits = bases; |
349 | 0 | else |
350 | 0 | end->next = bases; |
351 | 0 | for (k = bases; k; k = k->next) |
352 | 0 | end = k; |
353 | 0 | } |
354 | 0 | commit_list_free(*result); |
355 | 0 | *result = new_commits; |
356 | 0 | } |
357 | 0 | return 0; |
358 | 0 | } |
359 | | |
360 | | static int remove_redundant_no_gen(struct repository *r, |
361 | | struct commit **array, |
362 | | size_t cnt, size_t *dedup_cnt) |
363 | 0 | { |
364 | 0 | struct commit **work; |
365 | 0 | unsigned char *redundant; |
366 | 0 | size_t *filled_index; |
367 | 0 | size_t i, j, filled; |
368 | |
|
369 | 0 | CALLOC_ARRAY(work, cnt); |
370 | 0 | redundant = xcalloc(cnt, 1); |
371 | 0 | ALLOC_ARRAY(filled_index, cnt - 1); |
372 | |
|
373 | 0 | for (i = 0; i < cnt; i++) |
374 | 0 | repo_parse_commit(r, array[i]); |
375 | 0 | for (i = 0; i < cnt; i++) { |
376 | 0 | struct commit_list *common = NULL; |
377 | 0 | timestamp_t min_generation = commit_graph_generation(array[i]); |
378 | |
|
379 | 0 | if (redundant[i]) |
380 | 0 | continue; |
381 | 0 | for (j = filled = 0; j < cnt; j++) { |
382 | 0 | timestamp_t curr_generation; |
383 | 0 | if (i == j || redundant[j]) |
384 | 0 | continue; |
385 | 0 | filled_index[filled] = j; |
386 | 0 | work[filled++] = array[j]; |
387 | |
|
388 | 0 | curr_generation = commit_graph_generation(array[j]); |
389 | 0 | if (curr_generation < min_generation) |
390 | 0 | min_generation = curr_generation; |
391 | 0 | } |
392 | 0 | if (paint_down_to_common(r, array[i], filled, |
393 | 0 | work, min_generation, |
394 | 0 | MERGE_BASE_FIND_ALL, &common)) { |
395 | 0 | clear_commit_marks(array[i], all_flags); |
396 | 0 | clear_commit_marks_many(filled, work, all_flags); |
397 | 0 | commit_list_free(common); |
398 | 0 | free(work); |
399 | 0 | free(redundant); |
400 | 0 | free(filled_index); |
401 | 0 | return -1; |
402 | 0 | } |
403 | 0 | if (array[i]->object.flags & PARENT2) |
404 | 0 | redundant[i] = 1; |
405 | 0 | for (j = 0; j < filled; j++) |
406 | 0 | if (work[j]->object.flags & PARENT1) |
407 | 0 | redundant[filled_index[j]] = 1; |
408 | 0 | clear_commit_marks(array[i], all_flags); |
409 | 0 | clear_commit_marks_many(filled, work, all_flags); |
410 | 0 | commit_list_free(common); |
411 | 0 | } |
412 | | |
413 | | /* Now collect the result */ |
414 | 0 | COPY_ARRAY(work, array, cnt); |
415 | 0 | for (i = filled = 0; i < cnt; i++) |
416 | 0 | if (!redundant[i]) |
417 | 0 | array[filled++] = work[i]; |
418 | 0 | *dedup_cnt = filled; |
419 | 0 | free(work); |
420 | 0 | free(redundant); |
421 | 0 | free(filled_index); |
422 | 0 | return 0; |
423 | 0 | } |
424 | | |
425 | | static int remove_redundant_with_gen(struct repository *r, |
426 | | struct commit **array, size_t cnt, |
427 | | size_t *dedup_cnt) |
428 | 0 | { |
429 | 0 | size_t i, count_non_stale = 0, count_still_independent = cnt; |
430 | 0 | timestamp_t min_generation = GENERATION_NUMBER_INFINITY; |
431 | 0 | struct commit **sorted; |
432 | 0 | struct commit_stack walk_start = COMMIT_STACK_INIT; |
433 | 0 | size_t min_gen_pos = 0; |
434 | | |
435 | | /* |
436 | | * Sort the input by generation number, ascending. This allows |
437 | | * us to increase the "min_generation" limit when we discover |
438 | | * the commit with lowest generation is STALE. The index |
439 | | * min_gen_pos points to the current position within 'array' |
440 | | * that is not yet known to be STALE. |
441 | | */ |
442 | 0 | DUP_ARRAY(sorted, array, cnt); |
443 | 0 | QSORT(sorted, cnt, compare_commits_by_gen); |
444 | 0 | min_generation = commit_graph_generation(sorted[0]); |
445 | |
|
446 | 0 | commit_stack_grow(&walk_start, cnt); |
447 | | |
448 | | /* Mark all parents of the input as STALE */ |
449 | 0 | for (i = 0; i < cnt; i++) { |
450 | 0 | struct commit_list *parents; |
451 | |
|
452 | 0 | repo_parse_commit(r, array[i]); |
453 | 0 | array[i]->object.flags |= RESULT; |
454 | 0 | parents = array[i]->parents; |
455 | |
|
456 | 0 | while (parents) { |
457 | 0 | repo_parse_commit(r, parents->item); |
458 | 0 | if (!(parents->item->object.flags & STALE)) { |
459 | 0 | parents->item->object.flags |= STALE; |
460 | 0 | commit_stack_push(&walk_start, parents->item); |
461 | 0 | } |
462 | 0 | parents = parents->next; |
463 | 0 | } |
464 | 0 | } |
465 | |
|
466 | 0 | QSORT(walk_start.items, walk_start.nr, compare_commits_by_gen); |
467 | | |
468 | | /* remove STALE bit for now to allow walking through parents */ |
469 | 0 | for (i = 0; i < walk_start.nr; i++) |
470 | 0 | walk_start.items[i]->object.flags &= ~STALE; |
471 | | |
472 | | /* |
473 | | * Start walking from the highest generation. Hopefully, it will |
474 | | * find all other items during the first-parent walk, and we can |
475 | | * terminate early. Otherwise, we will do the same amount of work |
476 | | * as before. |
477 | | */ |
478 | 0 | for (i = walk_start.nr; i && count_still_independent > 1; i--) { |
479 | | /* push the STALE bits up to min generation */ |
480 | 0 | struct commit_list *stack = NULL; |
481 | |
|
482 | 0 | commit_list_insert(walk_start.items[i - 1], &stack); |
483 | 0 | walk_start.items[i - 1]->object.flags |= STALE; |
484 | |
|
485 | 0 | while (stack) { |
486 | 0 | struct commit_list *parents; |
487 | 0 | struct commit *c = stack->item; |
488 | |
|
489 | 0 | repo_parse_commit(r, c); |
490 | |
|
491 | 0 | if (c->object.flags & RESULT) { |
492 | 0 | c->object.flags &= ~RESULT; |
493 | 0 | if (--count_still_independent <= 1) |
494 | 0 | break; |
495 | 0 | if (oideq(&c->object.oid, &sorted[min_gen_pos]->object.oid)) { |
496 | 0 | while (min_gen_pos < cnt - 1 && |
497 | 0 | (sorted[min_gen_pos]->object.flags & STALE)) |
498 | 0 | min_gen_pos++; |
499 | 0 | min_generation = commit_graph_generation(sorted[min_gen_pos]); |
500 | 0 | } |
501 | 0 | } |
502 | | |
503 | 0 | if (commit_graph_generation(c) < min_generation) { |
504 | 0 | pop_commit(&stack); |
505 | 0 | continue; |
506 | 0 | } |
507 | | |
508 | 0 | parents = c->parents; |
509 | 0 | while (parents) { |
510 | 0 | if (!(parents->item->object.flags & STALE)) { |
511 | 0 | parents->item->object.flags |= STALE; |
512 | 0 | commit_list_insert(parents->item, &stack); |
513 | 0 | break; |
514 | 0 | } |
515 | 0 | parents = parents->next; |
516 | 0 | } |
517 | | |
518 | | /* pop if all parents have been visited already */ |
519 | 0 | if (!parents) |
520 | 0 | pop_commit(&stack); |
521 | 0 | } |
522 | 0 | commit_list_free(stack); |
523 | 0 | } |
524 | 0 | free(sorted); |
525 | | |
526 | | /* clear result */ |
527 | 0 | for (i = 0; i < cnt; i++) |
528 | 0 | array[i]->object.flags &= ~RESULT; |
529 | | |
530 | | /* rearrange array */ |
531 | 0 | for (i = count_non_stale = 0; i < cnt; i++) { |
532 | 0 | if (!(array[i]->object.flags & STALE)) |
533 | 0 | array[count_non_stale++] = array[i]; |
534 | 0 | } |
535 | | |
536 | | /* clear marks */ |
537 | 0 | clear_commit_marks_many(walk_start.nr, walk_start.items, STALE); |
538 | 0 | commit_stack_clear(&walk_start); |
539 | |
|
540 | 0 | *dedup_cnt = count_non_stale; |
541 | 0 | return 0; |
542 | 0 | } |
543 | | |
544 | | static int remove_redundant(struct repository *r, struct commit **array, |
545 | | size_t cnt, size_t *dedup_cnt) |
546 | 0 | { |
547 | | /* |
548 | | * Some commit in the array may be an ancestor of |
549 | | * another commit. Move the independent commits to the |
550 | | * beginning of 'array' and return their number. Callers |
551 | | * should not rely upon the contents of 'array' after |
552 | | * that number. |
553 | | */ |
554 | 0 | if (generation_numbers_enabled(r)) { |
555 | | /* |
556 | | * If we have a single commit with finite generation |
557 | | * number, then the _with_gen algorithm is preferred. |
558 | | */ |
559 | 0 | for (size_t i = 0; i < cnt; i++) { |
560 | 0 | if (commit_graph_generation(array[i]) < GENERATION_NUMBER_INFINITY) |
561 | 0 | return remove_redundant_with_gen(r, array, cnt, dedup_cnt); |
562 | 0 | } |
563 | 0 | } |
564 | | |
565 | 0 | return remove_redundant_no_gen(r, array, cnt, dedup_cnt); |
566 | 0 | } |
567 | | |
568 | | static int get_merge_bases_many_0(struct repository *r, |
569 | | struct commit *one, |
570 | | size_t n, |
571 | | struct commit **twos, |
572 | | int cleanup, |
573 | | enum merge_base_flags mb_flags, |
574 | | struct commit_list **result) |
575 | 0 | { |
576 | 0 | struct commit_list *list, **tail = result; |
577 | 0 | struct commit **rslt; |
578 | 0 | size_t cnt, i; |
579 | 0 | int ret; |
580 | |
|
581 | 0 | if (merge_bases_many(r, one, n, twos, mb_flags, result) < 0) |
582 | 0 | return -1; |
583 | 0 | for (i = 0; i < n; i++) { |
584 | 0 | if (one == twos[i]) |
585 | 0 | return 0; |
586 | 0 | } |
587 | 0 | if (!*result || !(*result)->next) { |
588 | 0 | if (cleanup) { |
589 | 0 | clear_commit_marks(one, all_flags); |
590 | 0 | clear_commit_marks_many(n, twos, all_flags); |
591 | 0 | } |
592 | 0 | return 0; |
593 | 0 | } |
594 | | |
595 | | /* There are more than one */ |
596 | 0 | cnt = commit_list_count(*result); |
597 | 0 | CALLOC_ARRAY(rslt, cnt); |
598 | 0 | for (list = *result, i = 0; list; list = list->next) |
599 | 0 | rslt[i++] = list->item; |
600 | 0 | commit_list_free(*result); |
601 | 0 | *result = NULL; |
602 | |
|
603 | 0 | clear_commit_marks(one, all_flags); |
604 | 0 | clear_commit_marks_many(n, twos, all_flags); |
605 | |
|
606 | 0 | ret = remove_redundant(r, rslt, cnt, &cnt); |
607 | 0 | if (ret < 0) { |
608 | 0 | free(rslt); |
609 | 0 | return -1; |
610 | 0 | } |
611 | 0 | for (i = 0; i < cnt; i++) |
612 | 0 | tail = commit_list_append(rslt[i], tail); |
613 | 0 | commit_list_sort_by_date(result); |
614 | 0 | free(rslt); |
615 | 0 | return 0; |
616 | 0 | } |
617 | | |
618 | | int repo_get_merge_bases_many(struct repository *r, |
619 | | struct commit *one, |
620 | | size_t n, |
621 | | struct commit **twos, |
622 | | struct commit_list **result) |
623 | 0 | { |
624 | 0 | return get_merge_bases_many_0(r, one, n, twos, 1, |
625 | 0 | MERGE_BASE_FIND_ALL, result); |
626 | 0 | } |
627 | | |
628 | | int repo_get_merge_bases_many_dirty(struct repository *r, |
629 | | struct commit *one, |
630 | | size_t n, |
631 | | struct commit **twos, |
632 | | enum merge_base_flags mb_flags, |
633 | | struct commit_list **result) |
634 | 0 | { |
635 | 0 | return get_merge_bases_many_0(r, one, n, twos, 0, mb_flags, result); |
636 | 0 | } |
637 | | |
638 | | int repo_get_merge_bases(struct repository *r, |
639 | | struct commit *one, |
640 | | struct commit *two, |
641 | | struct commit_list **result) |
642 | 0 | { |
643 | 0 | return get_merge_bases_many_0(r, one, 1, &two, 1, |
644 | 0 | MERGE_BASE_FIND_ALL, result); |
645 | 0 | } |
646 | | |
647 | | /* |
648 | | * Is "commit" a descendant of one of the elements on the "with_commit" list? |
649 | | */ |
650 | | int repo_is_descendant_of(struct repository *r, |
651 | | struct commit *commit, |
652 | | struct commit_list *with_commit) |
653 | 0 | { |
654 | 0 | if (!with_commit) |
655 | 0 | return 1; |
656 | | |
657 | 0 | if (generation_numbers_enabled(r)) { |
658 | 0 | struct commit_list *from_list = NULL; |
659 | 0 | int result; |
660 | 0 | commit_list_insert(commit, &from_list); |
661 | 0 | result = can_all_from_reach(r, from_list, with_commit, 0); |
662 | 0 | commit_list_free(from_list); |
663 | 0 | return result; |
664 | 0 | } else { |
665 | 0 | while (with_commit) { |
666 | 0 | struct commit *other; |
667 | 0 | int ret; |
668 | |
|
669 | 0 | other = with_commit->item; |
670 | 0 | with_commit = with_commit->next; |
671 | 0 | ret = repo_in_merge_bases_many(r, other, 1, &commit, 0); |
672 | 0 | if (ret) |
673 | 0 | return ret; |
674 | 0 | } |
675 | 0 | return 0; |
676 | 0 | } |
677 | 0 | } |
678 | | |
679 | | /* |
680 | | * Is "commit" an ancestor of one of the "references"? |
681 | | */ |
682 | | int repo_in_merge_bases_many(struct repository *r, struct commit *commit, |
683 | | int nr_reference, struct commit **reference, |
684 | | int ignore_missing_commits) |
685 | 0 | { |
686 | 0 | struct commit_list *bases = NULL; |
687 | 0 | int ret = 0, i; |
688 | 0 | timestamp_t generation, max_generation = GENERATION_NUMBER_ZERO; |
689 | 0 | enum merge_base_flags mb_flags = MERGE_BASE_FIND_ALL; |
690 | |
|
691 | 0 | if (ignore_missing_commits) |
692 | 0 | mb_flags |= MERGE_BASE_IGNORE_MISSING_COMMITS; |
693 | |
|
694 | 0 | if (repo_parse_commit(r, commit)) |
695 | 0 | return ignore_missing_commits ? 0 : -1; |
696 | 0 | for (i = 0; i < nr_reference; i++) { |
697 | 0 | if (repo_parse_commit(r, reference[i])) |
698 | 0 | return ignore_missing_commits ? 0 : -1; |
699 | | |
700 | 0 | generation = commit_graph_generation(reference[i]); |
701 | 0 | if (generation > max_generation) |
702 | 0 | max_generation = generation; |
703 | 0 | } |
704 | | |
705 | 0 | generation = commit_graph_generation(commit); |
706 | 0 | if (generation > max_generation) |
707 | 0 | return ret; |
708 | | |
709 | 0 | if (paint_down_to_common(r, commit, |
710 | 0 | nr_reference, reference, |
711 | 0 | generation, mb_flags, &bases)) |
712 | 0 | ret = -1; |
713 | 0 | else if (commit->object.flags & PARENT2) |
714 | 0 | ret = 1; |
715 | 0 | clear_commit_marks(commit, all_flags); |
716 | 0 | clear_commit_marks_many(nr_reference, reference, all_flags); |
717 | 0 | commit_list_free(bases); |
718 | 0 | return ret; |
719 | 0 | } |
720 | | |
721 | | /* |
722 | | * Is "commit" an ancestor of (i.e. reachable from) the "reference"? |
723 | | */ |
724 | | int repo_in_merge_bases(struct repository *r, |
725 | | struct commit *commit, |
726 | | struct commit *reference) |
727 | 0 | { |
728 | 0 | int res; |
729 | 0 | struct commit_list *list = NULL; |
730 | 0 | struct commit_list **next = &list; |
731 | |
|
732 | 0 | next = commit_list_append(commit, next); |
733 | 0 | res = repo_is_descendant_of(r, reference, list); |
734 | 0 | commit_list_free(list); |
735 | |
|
736 | 0 | return res; |
737 | 0 | } |
738 | | |
739 | | struct commit_list *reduce_heads(struct commit_list *heads) |
740 | 0 | { |
741 | 0 | struct commit_list *p; |
742 | 0 | struct commit_list *result = NULL, **tail = &result; |
743 | 0 | struct commit **array; |
744 | 0 | size_t num_head, i; |
745 | 0 | int ret; |
746 | |
|
747 | 0 | if (!heads) |
748 | 0 | return NULL; |
749 | | |
750 | | /* Uniquify */ |
751 | 0 | for (p = heads; p; p = p->next) |
752 | 0 | p->item->object.flags &= ~STALE; |
753 | 0 | for (p = heads, num_head = 0; p; p = p->next) { |
754 | 0 | if (p->item->object.flags & STALE) |
755 | 0 | continue; |
756 | 0 | p->item->object.flags |= STALE; |
757 | 0 | num_head++; |
758 | 0 | } |
759 | 0 | CALLOC_ARRAY(array, num_head); |
760 | 0 | for (p = heads, i = 0; p; p = p->next) { |
761 | 0 | if (p->item->object.flags & STALE) { |
762 | 0 | array[i++] = p->item; |
763 | 0 | p->item->object.flags &= ~STALE; |
764 | 0 | } |
765 | 0 | } |
766 | |
|
767 | 0 | ret = remove_redundant(the_repository, array, num_head, &num_head); |
768 | 0 | if (ret < 0) { |
769 | 0 | free(array); |
770 | 0 | return NULL; |
771 | 0 | } |
772 | | |
773 | 0 | for (i = 0; i < num_head; i++) |
774 | 0 | tail = &commit_list_insert(array[i], tail)->next; |
775 | 0 | free(array); |
776 | 0 | return result; |
777 | 0 | } |
778 | | |
779 | | void reduce_heads_replace(struct commit_list **heads) |
780 | 0 | { |
781 | 0 | struct commit_list *result = reduce_heads(*heads); |
782 | 0 | commit_list_free(*heads); |
783 | 0 | *heads = result; |
784 | 0 | } |
785 | | |
786 | | int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid) |
787 | 0 | { |
788 | 0 | struct object *o; |
789 | 0 | struct commit *old_commit, *new_commit; |
790 | 0 | struct commit_list *old_commit_list = NULL; |
791 | 0 | int ret; |
792 | | |
793 | | /* |
794 | | * Both new_commit and old_commit must be commit-ish and new_commit is descendant of |
795 | | * old_commit. Otherwise we require --force. |
796 | | */ |
797 | 0 | o = deref_tag(the_repository, parse_object(the_repository, old_oid), |
798 | 0 | NULL, 0); |
799 | 0 | if (!o || o->type != OBJ_COMMIT) |
800 | 0 | return 0; |
801 | 0 | old_commit = (struct commit *) o; |
802 | |
|
803 | 0 | o = deref_tag(the_repository, parse_object(the_repository, new_oid), |
804 | 0 | NULL, 0); |
805 | 0 | if (!o || o->type != OBJ_COMMIT) |
806 | 0 | return 0; |
807 | 0 | new_commit = (struct commit *) o; |
808 | |
|
809 | 0 | if (repo_parse_commit(the_repository, new_commit) < 0) |
810 | 0 | return 0; |
811 | | |
812 | 0 | commit_list_insert(old_commit, &old_commit_list); |
813 | 0 | ret = repo_is_descendant_of(the_repository, |
814 | 0 | new_commit, old_commit_list); |
815 | 0 | if (ret < 0) |
816 | 0 | exit(128); |
817 | 0 | commit_list_free(old_commit_list); |
818 | 0 | return ret; |
819 | 0 | } |
820 | | |
821 | | /* |
822 | | * Mimicking the real stack, this stack lives on the heap, avoiding stack |
823 | | * overflows. |
824 | | * |
825 | | * At each recursion step, the stack items points to the commits whose |
826 | | * ancestors are to be inspected. |
827 | | */ |
828 | | struct contains_stack { |
829 | | int nr, alloc; |
830 | | struct contains_stack_entry { |
831 | | struct commit *commit; |
832 | | struct commit_list *parents; |
833 | | } *contains_stack; |
834 | | }; |
835 | | |
836 | | static int in_commit_list(const struct commit_list *want, struct commit *c) |
837 | 0 | { |
838 | 0 | for (; want; want = want->next) |
839 | 0 | if (oideq(&want->item->object.oid, &c->object.oid)) |
840 | 0 | return 1; |
841 | 0 | return 0; |
842 | 0 | } |
843 | | |
844 | | /* |
845 | | * Test whether the candidate is contained in the list. |
846 | | * Do not recurse to find out, though, but return CONTAINS_UNKNOWN if |
847 | | * inconclusive. |
848 | | */ |
849 | | static enum contains_result contains_test(struct commit *candidate, |
850 | | const struct commit_list *want, |
851 | | struct contains_cache *cache, |
852 | | timestamp_t cutoff) |
853 | 0 | { |
854 | 0 | enum contains_result *cached = contains_cache_at(cache, candidate); |
855 | | |
856 | | /* If we already have the answer cached, return that. */ |
857 | 0 | if (*cached) |
858 | 0 | return *cached; |
859 | | |
860 | | /* or are we it? */ |
861 | 0 | if (in_commit_list(want, candidate)) { |
862 | 0 | *cached = CONTAINS_YES; |
863 | 0 | return CONTAINS_YES; |
864 | 0 | } |
865 | | |
866 | | /* Otherwise, we don't know; prepare to recurse */ |
867 | 0 | parse_commit_or_die(candidate); |
868 | |
|
869 | 0 | if (commit_graph_generation(candidate) < cutoff) |
870 | 0 | return CONTAINS_NO; |
871 | | |
872 | 0 | return CONTAINS_UNKNOWN; |
873 | 0 | } |
874 | | |
875 | | static void push_to_contains_stack(struct commit *candidate, struct contains_stack *contains_stack) |
876 | 0 | { |
877 | 0 | ALLOC_GROW(contains_stack->contains_stack, contains_stack->nr + 1, contains_stack->alloc); |
878 | 0 | contains_stack->contains_stack[contains_stack->nr].commit = candidate; |
879 | 0 | contains_stack->contains_stack[contains_stack->nr++].parents = candidate->parents; |
880 | 0 | } |
881 | | |
882 | | static enum contains_result contains_tag_algo(struct commit *candidate, |
883 | | const struct commit_list *want, |
884 | | struct contains_cache *cache) |
885 | 0 | { |
886 | 0 | struct contains_stack contains_stack = { 0, 0, NULL }; |
887 | 0 | enum contains_result result; |
888 | 0 | timestamp_t cutoff = GENERATION_NUMBER_INFINITY; |
889 | 0 | const struct commit_list *p; |
890 | |
|
891 | 0 | for (p = want; p; p = p->next) { |
892 | 0 | timestamp_t generation; |
893 | 0 | struct commit *c = p->item; |
894 | 0 | load_commit_graph_info(the_repository, c); |
895 | 0 | generation = commit_graph_generation(c); |
896 | 0 | if (generation < cutoff) |
897 | 0 | cutoff = generation; |
898 | 0 | } |
899 | |
|
900 | 0 | result = contains_test(candidate, want, cache, cutoff); |
901 | 0 | if (result != CONTAINS_UNKNOWN) |
902 | 0 | return result; |
903 | | |
904 | 0 | *contains_cache_at(cache, candidate) = CONTAINS_IN_PROGRESS; |
905 | 0 | push_to_contains_stack(candidate, &contains_stack); |
906 | 0 | while (contains_stack.nr) { |
907 | 0 | struct contains_stack_entry *entry = &contains_stack.contains_stack[contains_stack.nr - 1]; |
908 | 0 | struct commit *commit = entry->commit; |
909 | 0 | struct commit_list *parents = entry->parents; |
910 | |
|
911 | 0 | if (!parents) { |
912 | 0 | *contains_cache_at(cache, commit) = CONTAINS_NO; |
913 | 0 | contains_stack.nr--; |
914 | 0 | } |
915 | | /* |
916 | | * A parent may have just been popped and marked, or may still |
917 | | * be active when replacement refs create a cycle. |
918 | | */ |
919 | 0 | else switch (contains_test(parents->item, want, cache, cutoff)) { |
920 | 0 | case CONTAINS_YES: |
921 | 0 | *contains_cache_at(cache, commit) = CONTAINS_YES; |
922 | 0 | contains_stack.nr--; |
923 | 0 | break; |
924 | 0 | case CONTAINS_NO: |
925 | 0 | entry->parents = parents->next; |
926 | 0 | break; |
927 | 0 | case CONTAINS_IN_PROGRESS: |
928 | 0 | die(_("commit ancestry contains a cycle")); |
929 | 0 | case CONTAINS_UNKNOWN: |
930 | 0 | *contains_cache_at(cache, parents->item) = |
931 | 0 | CONTAINS_IN_PROGRESS; |
932 | 0 | push_to_contains_stack(parents->item, &contains_stack); |
933 | 0 | break; |
934 | 0 | } |
935 | 0 | } |
936 | 0 | free(contains_stack.contains_stack); |
937 | 0 | return contains_test(candidate, want, cache, cutoff); |
938 | 0 | } |
939 | | |
940 | | int commit_contains(struct ref_filter *filter, struct commit *commit, |
941 | | struct commit_list *list, struct contains_cache *cache) |
942 | 0 | { |
943 | 0 | int result; |
944 | |
|
945 | 0 | if (filter->with_commit_tag_algo || |
946 | 0 | generation_numbers_enabled(the_repository)) |
947 | 0 | return contains_tag_algo(commit, list, cache) == CONTAINS_YES; |
948 | | |
949 | 0 | result = repo_is_descendant_of(the_repository, commit, list); |
950 | 0 | if (result < 0) |
951 | 0 | die(_("failed to check reachability")); |
952 | 0 | return result; |
953 | 0 | } |
954 | | |
955 | | int can_all_from_reach_with_flag(struct repository *r, |
956 | | struct object_array *from, |
957 | | unsigned int with_flag, |
958 | | unsigned int assign_flag, |
959 | | timestamp_t min_commit_date, |
960 | | timestamp_t min_generation) |
961 | 0 | { |
962 | 0 | struct commit **list = NULL; |
963 | 0 | size_t i; |
964 | 0 | size_t nr_commits; |
965 | 0 | int result = 1; |
966 | |
|
967 | 0 | ALLOC_ARRAY(list, from->nr); |
968 | 0 | nr_commits = 0; |
969 | 0 | for (i = 0; i < from->nr; i++) { |
970 | 0 | struct object *from_one = from->objects[i].item; |
971 | |
|
972 | 0 | if (!from_one || from_one->flags & assign_flag) |
973 | 0 | continue; |
974 | | |
975 | 0 | from_one = deref_tag(r, from_one, "a from object", 0); |
976 | 0 | if (!from_one || from_one->type != OBJ_COMMIT) { |
977 | | /* |
978 | | * no way to tell if this is reachable by |
979 | | * looking at the ancestry chain alone, so |
980 | | * leave a note to ourselves not to worry about |
981 | | * this object anymore. |
982 | | */ |
983 | 0 | from->objects[i].item->flags |= assign_flag; |
984 | 0 | continue; |
985 | 0 | } |
986 | | |
987 | 0 | list[nr_commits] = (struct commit *)from_one; |
988 | 0 | if (repo_parse_commit(r, list[nr_commits]) || |
989 | 0 | commit_graph_generation(list[nr_commits]) < min_generation) { |
990 | 0 | result = 0; |
991 | 0 | goto cleanup; |
992 | 0 | } |
993 | | |
994 | 0 | nr_commits++; |
995 | 0 | } |
996 | | |
997 | 0 | QSORT(list, nr_commits, compare_commits_by_gen); |
998 | |
|
999 | 0 | for (i = 0; i < nr_commits; i++) { |
1000 | | /* DFS from list[i] */ |
1001 | 0 | struct commit_list *stack = NULL; |
1002 | |
|
1003 | 0 | list[i]->object.flags |= assign_flag; |
1004 | 0 | commit_list_insert(list[i], &stack); |
1005 | |
|
1006 | 0 | while (stack) { |
1007 | 0 | struct commit_list *parent; |
1008 | |
|
1009 | 0 | if (stack->item->object.flags & (with_flag | RESULT)) { |
1010 | 0 | pop_commit(&stack); |
1011 | 0 | if (stack) |
1012 | 0 | stack->item->object.flags |= RESULT; |
1013 | 0 | continue; |
1014 | 0 | } |
1015 | | |
1016 | 0 | for (parent = stack->item->parents; parent; parent = parent->next) { |
1017 | 0 | if (parent->item->object.flags & (with_flag | RESULT)) |
1018 | 0 | stack->item->object.flags |= RESULT; |
1019 | |
|
1020 | 0 | if (!(parent->item->object.flags & assign_flag)) { |
1021 | 0 | parent->item->object.flags |= assign_flag; |
1022 | |
|
1023 | 0 | if (repo_parse_commit(r, parent->item) || |
1024 | 0 | parent->item->date < min_commit_date || |
1025 | 0 | commit_graph_generation(parent->item) < min_generation) |
1026 | 0 | continue; |
1027 | | |
1028 | 0 | commit_list_insert(parent->item, &stack); |
1029 | 0 | break; |
1030 | 0 | } |
1031 | 0 | } |
1032 | |
|
1033 | 0 | if (!parent) |
1034 | 0 | pop_commit(&stack); |
1035 | 0 | } |
1036 | |
|
1037 | 0 | if (!(list[i]->object.flags & (with_flag | RESULT))) { |
1038 | 0 | result = 0; |
1039 | 0 | goto cleanup; |
1040 | 0 | } |
1041 | 0 | } |
1042 | | |
1043 | 0 | cleanup: |
1044 | 0 | clear_commit_marks_many(nr_commits, list, RESULT | assign_flag); |
1045 | 0 | free(list); |
1046 | |
|
1047 | 0 | for (i = 0; i < from->nr; i++) { |
1048 | 0 | struct object *from_one = from->objects[i].item; |
1049 | |
|
1050 | 0 | if (from_one) |
1051 | 0 | from_one->flags &= ~assign_flag; |
1052 | 0 | } |
1053 | |
|
1054 | 0 | return result; |
1055 | 0 | } |
1056 | | |
1057 | | int can_all_from_reach(struct repository *r, struct commit_list *from, |
1058 | | struct commit_list *to, int cutoff_by_min_date) |
1059 | 0 | { |
1060 | 0 | struct object_array from_objs = OBJECT_ARRAY_INIT; |
1061 | 0 | struct commit_list *from_iter = from, *to_iter = to; |
1062 | 0 | int result; |
1063 | 0 | timestamp_t min_commit_date = cutoff_by_min_date ? from->item->date : 0; |
1064 | 0 | timestamp_t min_generation = GENERATION_NUMBER_INFINITY; |
1065 | |
|
1066 | 0 | while (from_iter) { |
1067 | 0 | add_object_array(&from_iter->item->object, NULL, &from_objs); |
1068 | |
|
1069 | 0 | if (!repo_parse_commit(r, from_iter->item)) { |
1070 | 0 | timestamp_t generation; |
1071 | 0 | if (from_iter->item->date < min_commit_date) |
1072 | 0 | min_commit_date = from_iter->item->date; |
1073 | |
|
1074 | 0 | generation = commit_graph_generation(from_iter->item); |
1075 | 0 | if (generation < min_generation) |
1076 | 0 | min_generation = generation; |
1077 | 0 | } |
1078 | |
|
1079 | 0 | from_iter = from_iter->next; |
1080 | 0 | } |
1081 | |
|
1082 | 0 | while (to_iter) { |
1083 | 0 | if (!repo_parse_commit(r, to_iter->item)) { |
1084 | 0 | timestamp_t generation; |
1085 | 0 | if (to_iter->item->date < min_commit_date) |
1086 | 0 | min_commit_date = to_iter->item->date; |
1087 | |
|
1088 | 0 | generation = commit_graph_generation(to_iter->item); |
1089 | 0 | if (generation < min_generation) |
1090 | 0 | min_generation = generation; |
1091 | 0 | } |
1092 | |
|
1093 | 0 | to_iter->item->object.flags |= PARENT2; |
1094 | |
|
1095 | 0 | to_iter = to_iter->next; |
1096 | 0 | } |
1097 | |
|
1098 | 0 | result = can_all_from_reach_with_flag(r, &from_objs, PARENT2, PARENT1, |
1099 | 0 | min_commit_date, min_generation); |
1100 | |
|
1101 | 0 | while (from) { |
1102 | 0 | clear_commit_marks(from->item, PARENT1); |
1103 | 0 | from = from->next; |
1104 | 0 | } |
1105 | |
|
1106 | 0 | while (to) { |
1107 | 0 | clear_commit_marks(to->item, PARENT2); |
1108 | 0 | to = to->next; |
1109 | 0 | } |
1110 | |
|
1111 | 0 | object_array_clear(&from_objs); |
1112 | 0 | return result; |
1113 | 0 | } |
1114 | | |
1115 | | struct commit_list *get_reachable_subset(struct commit **from, size_t nr_from, |
1116 | | struct commit **to, size_t nr_to, |
1117 | | unsigned int reachable_flag) |
1118 | 0 | { |
1119 | 0 | struct commit **item; |
1120 | 0 | struct commit *current; |
1121 | 0 | struct commit_list *found_commits = NULL; |
1122 | 0 | struct commit **to_last = to + nr_to; |
1123 | 0 | struct commit **from_last = from + nr_from; |
1124 | 0 | timestamp_t min_generation = GENERATION_NUMBER_INFINITY; |
1125 | 0 | int num_to_find = 0; |
1126 | |
|
1127 | 0 | struct prio_queue queue = { compare_commits_by_gen_then_commit_date }; |
1128 | |
|
1129 | 0 | for (item = to; item < to_last; item++) { |
1130 | 0 | timestamp_t generation; |
1131 | 0 | struct commit *c = *item; |
1132 | |
|
1133 | 0 | repo_parse_commit(the_repository, c); |
1134 | 0 | generation = commit_graph_generation(c); |
1135 | 0 | if (generation < min_generation) |
1136 | 0 | min_generation = generation; |
1137 | |
|
1138 | 0 | if (!(c->object.flags & PARENT1)) { |
1139 | 0 | c->object.flags |= PARENT1; |
1140 | 0 | num_to_find++; |
1141 | 0 | } |
1142 | 0 | } |
1143 | |
|
1144 | 0 | for (item = from; item < from_last; item++) { |
1145 | 0 | struct commit *c = *item; |
1146 | 0 | if (!(c->object.flags & PARENT2)) { |
1147 | 0 | c->object.flags |= PARENT2; |
1148 | 0 | repo_parse_commit(the_repository, c); |
1149 | |
|
1150 | 0 | prio_queue_put(&queue, *item); |
1151 | 0 | } |
1152 | 0 | } |
1153 | |
|
1154 | 0 | while (num_to_find && (current = prio_queue_get(&queue)) != NULL) { |
1155 | 0 | struct commit_list *parents; |
1156 | |
|
1157 | 0 | if (current->object.flags & PARENT1) { |
1158 | 0 | current->object.flags &= ~PARENT1; |
1159 | 0 | current->object.flags |= reachable_flag; |
1160 | 0 | commit_list_insert(current, &found_commits); |
1161 | 0 | num_to_find--; |
1162 | 0 | } |
1163 | |
|
1164 | 0 | for (parents = current->parents; parents; parents = parents->next) { |
1165 | 0 | struct commit *p = parents->item; |
1166 | |
|
1167 | 0 | repo_parse_commit(the_repository, p); |
1168 | |
|
1169 | 0 | if (commit_graph_generation(p) < min_generation) |
1170 | 0 | continue; |
1171 | | |
1172 | 0 | if (p->object.flags & PARENT2) |
1173 | 0 | continue; |
1174 | | |
1175 | 0 | p->object.flags |= PARENT2; |
1176 | 0 | prio_queue_put(&queue, p); |
1177 | 0 | } |
1178 | 0 | } |
1179 | |
|
1180 | 0 | clear_prio_queue(&queue); |
1181 | |
|
1182 | 0 | clear_commit_marks_many(nr_to, to, PARENT1); |
1183 | 0 | clear_commit_marks_many(nr_from, from, PARENT2); |
1184 | |
|
1185 | 0 | return found_commits; |
1186 | 0 | } |
1187 | | |
1188 | 0 | define_commit_slab(bit_arrays, struct bitmap *); Unexecuted instantiation: commit-reach.c:init_bit_arrays_with_stride Unexecuted instantiation: commit-reach.c:bit_arrays_at_peek Unexecuted instantiation: commit-reach.c:clear_bit_arrays |
1189 | 0 | static struct bit_arrays bit_arrays; |
1190 | 0 |
|
1191 | 0 | static void insert_no_dup(struct nonstale_queue *queue, struct commit *c) |
1192 | 0 | { |
1193 | 0 | if (c->object.flags & PARENT2) |
1194 | 0 | return; |
1195 | 0 | nonstale_queue_put(queue, c); |
1196 | 0 | c->object.flags |= PARENT2; |
1197 | 0 | } |
1198 | | |
1199 | | static struct bitmap *get_bit_array(struct commit *c, int width) |
1200 | 0 | { |
1201 | 0 | struct bitmap **bitmap = bit_arrays_at(&bit_arrays, c); |
1202 | 0 | if (!*bitmap) |
1203 | 0 | *bitmap = bitmap_word_alloc(width); |
1204 | 0 | return *bitmap; |
1205 | 0 | } |
1206 | | |
1207 | | static void free_bit_array(struct commit *c) |
1208 | 0 | { |
1209 | 0 | struct bitmap **bitmap = bit_arrays_at(&bit_arrays, c); |
1210 | 0 | if (!*bitmap) |
1211 | 0 | return; |
1212 | 0 | bitmap_free(*bitmap); |
1213 | 0 | *bitmap = NULL; |
1214 | 0 | } |
1215 | | |
1216 | | void ahead_behind(struct repository *r, |
1217 | | struct commit **commits, size_t commits_nr, |
1218 | | struct ahead_behind_count *counts, size_t counts_nr) |
1219 | 0 | { |
1220 | 0 | struct nonstale_queue queue = { |
1221 | 0 | { .compare = compare_commits_by_gen_then_commit_date } |
1222 | 0 | }; |
1223 | 0 | void *entry; |
1224 | 0 | size_t width = DIV_ROUND_UP(commits_nr, BITS_IN_EWORD); |
1225 | |
|
1226 | 0 | if (!commits_nr || !counts_nr) |
1227 | 0 | return; |
1228 | | |
1229 | 0 | for (size_t i = 0; i < counts_nr; i++) { |
1230 | 0 | counts[i].ahead = 0; |
1231 | 0 | counts[i].behind = 0; |
1232 | 0 | } |
1233 | |
|
1234 | 0 | ensure_generations_valid(r, commits, commits_nr); |
1235 | |
|
1236 | 0 | init_bit_arrays(&bit_arrays); |
1237 | |
|
1238 | 0 | for (size_t i = 0; i < commits_nr; i++) { |
1239 | 0 | struct commit *c = commits[i]; |
1240 | 0 | struct bitmap *bitmap = get_bit_array(c, width); |
1241 | |
|
1242 | 0 | bitmap_set(bitmap, i); |
1243 | 0 | insert_no_dup(&queue, c); |
1244 | 0 | } |
1245 | |
|
1246 | 0 | while (queue.max_nonstale) { |
1247 | 0 | struct commit *c = nonstale_queue_get(&queue); |
1248 | 0 | struct commit_list *p; |
1249 | 0 | struct bitmap *bitmap_c = get_bit_array(c, width); |
1250 | |
|
1251 | 0 | for (size_t i = 0; i < counts_nr; i++) { |
1252 | 0 | int reach_from_tip = !!bitmap_get(bitmap_c, counts[i].tip_index); |
1253 | 0 | int reach_from_base = !!bitmap_get(bitmap_c, counts[i].base_index); |
1254 | |
|
1255 | 0 | if (reach_from_tip ^ reach_from_base) { |
1256 | 0 | if (reach_from_base) |
1257 | 0 | counts[i].behind++; |
1258 | 0 | else |
1259 | 0 | counts[i].ahead++; |
1260 | 0 | } |
1261 | 0 | } |
1262 | |
|
1263 | 0 | for (p = c->parents; p; p = p->next) { |
1264 | 0 | struct bitmap *bitmap_p; |
1265 | |
|
1266 | 0 | repo_parse_commit(r, p->item); |
1267 | |
|
1268 | 0 | bitmap_p = get_bit_array(p->item, width); |
1269 | 0 | bitmap_or(bitmap_p, bitmap_c); |
1270 | | |
1271 | | /* |
1272 | | * If this parent is reachable from every starting |
1273 | | * commit, then none of its ancestors can contribute |
1274 | | * to the ahead/behind count. Mark it as STALE, so |
1275 | | * we can stop the walk when every commit in the |
1276 | | * queue is STALE. |
1277 | | */ |
1278 | 0 | if (bitmap_popcount(bitmap_p) == commits_nr) |
1279 | 0 | p->item->object.flags |= STALE; |
1280 | |
|
1281 | 0 | insert_no_dup(&queue, p->item); |
1282 | 0 | } |
1283 | |
|
1284 | 0 | free_bit_array(c); |
1285 | 0 | } |
1286 | | |
1287 | | /* STALE is used here, PARENT2 is used by insert_no_dup(). */ |
1288 | 0 | repo_clear_commit_marks(r, PARENT2 | STALE); |
1289 | 0 | prio_queue_for_each(&queue.pq, entry) |
1290 | 0 | free_bit_array(entry); |
1291 | 0 | clear_bit_arrays(&bit_arrays); |
1292 | 0 | clear_nonstale_queue(&queue); |
1293 | 0 | } |
1294 | | |
1295 | | struct commit_and_index { |
1296 | | struct commit *commit; |
1297 | | timestamp_t generation; |
1298 | | }; |
1299 | | |
1300 | | static int compare_commit_and_index_by_generation(const void *va, const void *vb) |
1301 | 0 | { |
1302 | 0 | const struct commit_and_index *a = (const struct commit_and_index *)va; |
1303 | 0 | const struct commit_and_index *b = (const struct commit_and_index *)vb; |
1304 | |
|
1305 | 0 | if (a->generation > b->generation) |
1306 | 0 | return 1; |
1307 | 0 | if (a->generation < b->generation) |
1308 | 0 | return -1; |
1309 | 0 | return 0; |
1310 | 0 | } |
1311 | | |
1312 | | void tips_reachable_from_bases(struct repository *r, |
1313 | | struct commit_list *bases, |
1314 | | struct commit **tips, size_t tips_nr, |
1315 | | int mark) |
1316 | 0 | { |
1317 | 0 | struct commit_and_index *commits; |
1318 | 0 | size_t min_generation_index = 0; |
1319 | 0 | timestamp_t min_generation; |
1320 | 0 | struct commit_list *stack = NULL; |
1321 | |
|
1322 | 0 | if (!bases || !tips || !tips_nr) |
1323 | 0 | return; |
1324 | | |
1325 | | /* |
1326 | | * Do a depth-first search starting at 'bases' to search for the |
1327 | | * tips. Stop at the lowest (un-found) generation number. When |
1328 | | * finding the lowest commit, increase the minimum generation |
1329 | | * number to the next lowest (un-found) generation number. |
1330 | | */ |
1331 | | |
1332 | 0 | CALLOC_ARRAY(commits, tips_nr); |
1333 | |
|
1334 | 0 | for (size_t i = 0; i < tips_nr; i++) { |
1335 | 0 | commits[i].commit = tips[i]; |
1336 | 0 | commits[i].generation = commit_graph_generation(tips[i]); |
1337 | 0 | } |
1338 | | |
1339 | | /* Sort with generation number ascending. */ |
1340 | 0 | QSORT(commits, tips_nr, compare_commit_and_index_by_generation); |
1341 | 0 | min_generation = commits[0].generation; |
1342 | |
|
1343 | 0 | for (size_t i = 0; i < tips_nr; i++) |
1344 | 0 | commits[i].commit->object.flags |= RESULT; |
1345 | |
|
1346 | 0 | while (bases) { |
1347 | 0 | repo_parse_commit(r, bases->item); |
1348 | 0 | commit_list_insert(bases->item, &stack); |
1349 | 0 | bases = bases->next; |
1350 | 0 | } |
1351 | |
|
1352 | 0 | while (stack) { |
1353 | 0 | int explored_all_parents = 1; |
1354 | 0 | struct commit_list *p; |
1355 | 0 | struct commit *c = stack->item; |
1356 | | |
1357 | | /* Does it match any of our tips? */ |
1358 | 0 | { |
1359 | 0 | if (c->object.flags & RESULT) { |
1360 | 0 | c->object.flags |= mark; |
1361 | |
|
1362 | 0 | if (commits[min_generation_index].commit->object.flags & mark) { |
1363 | 0 | unsigned int k = min_generation_index + 1; |
1364 | 0 | while (k < tips_nr && |
1365 | 0 | (commits[k].commit->object.flags & mark)) |
1366 | 0 | k++; |
1367 | | |
1368 | | /* Terminate early if all found. */ |
1369 | 0 | if (k >= tips_nr) |
1370 | 0 | goto done; |
1371 | | |
1372 | 0 | min_generation_index = k; |
1373 | 0 | min_generation = commits[k].generation; |
1374 | 0 | } |
1375 | 0 | } |
1376 | 0 | } |
1377 | | |
1378 | 0 | for (p = c->parents; p; p = p->next) { |
1379 | 0 | repo_parse_commit(r, p->item); |
1380 | | |
1381 | | /* Have we already explored this parent? */ |
1382 | 0 | if (p->item->object.flags & SEEN) |
1383 | 0 | continue; |
1384 | | |
1385 | | /* Is it below the current minimum generation? */ |
1386 | 0 | if (commit_graph_generation(p->item) < min_generation) |
1387 | 0 | continue; |
1388 | | |
1389 | | /* Ok, we will explore from here on. */ |
1390 | 0 | p->item->object.flags |= SEEN; |
1391 | 0 | explored_all_parents = 0; |
1392 | 0 | commit_list_insert(p->item, &stack); |
1393 | 0 | break; |
1394 | 0 | } |
1395 | |
|
1396 | 0 | if (explored_all_parents) |
1397 | 0 | pop_commit(&stack); |
1398 | 0 | } |
1399 | | |
1400 | 0 | done: |
1401 | 0 | for (size_t i = 0; i < tips_nr; i++) |
1402 | 0 | commits[i].commit->object.flags &= ~RESULT; |
1403 | 0 | free(commits); |
1404 | 0 | repo_clear_commit_marks(r, SEEN); |
1405 | 0 | commit_list_free(stack); |
1406 | 0 | } |
1407 | | |
1408 | | /* |
1409 | | * This slab initializes integers to zero, so use "-1" for "tip is best" and |
1410 | | * "i + 1" for "bases[i] is best". |
1411 | | */ |
1412 | 0 | define_commit_slab(best_branch_base, int); Unexecuted instantiation: commit-reach.c:init_best_branch_base_with_stride Unexecuted instantiation: commit-reach.c:best_branch_base_at_peek Unexecuted instantiation: commit-reach.c:clear_best_branch_base |
1413 | 0 | static struct best_branch_base best_branch_base; |
1414 | 0 | #define get_best(c) (*best_branch_base_at(&best_branch_base, (c))) |
1415 | 0 | #define set_best(c,v) (*best_branch_base_at(&best_branch_base, (c)) = (v)) |
1416 | | |
1417 | | int get_branch_base_for_tip(struct repository *r, |
1418 | | struct commit *tip, |
1419 | | struct commit **bases, |
1420 | | size_t bases_nr) |
1421 | 0 | { |
1422 | 0 | int best_index = -1; |
1423 | 0 | struct commit *c, *branch_point = NULL; |
1424 | 0 | struct prio_queue queue = { compare_commits_by_gen_then_commit_date }; |
1425 | 0 | int found_missing_gen = 0; |
1426 | |
|
1427 | 0 | if (!bases_nr) |
1428 | 0 | return -1; |
1429 | | |
1430 | 0 | repo_parse_commit(r, tip); |
1431 | 0 | if (commit_graph_generation(tip) == GENERATION_NUMBER_INFINITY) |
1432 | 0 | found_missing_gen = 1; |
1433 | | |
1434 | | /* Check for missing generation numbers. */ |
1435 | 0 | for (size_t i = 0; i < bases_nr; i++) { |
1436 | 0 | struct commit *c = bases[i]; |
1437 | 0 | repo_parse_commit(r, c); |
1438 | 0 | if (commit_graph_generation(c) == GENERATION_NUMBER_INFINITY) |
1439 | 0 | found_missing_gen = 1; |
1440 | 0 | } |
1441 | |
|
1442 | 0 | if (found_missing_gen) { |
1443 | 0 | struct commit **commits; |
1444 | 0 | size_t commits_nr = bases_nr + 1; |
1445 | |
|
1446 | 0 | CALLOC_ARRAY(commits, commits_nr); |
1447 | 0 | COPY_ARRAY(commits, bases, bases_nr); |
1448 | 0 | commits[bases_nr] = tip; |
1449 | 0 | ensure_generations_valid(r, commits, commits_nr); |
1450 | 0 | free(commits); |
1451 | 0 | } |
1452 | | |
1453 | | /* Initialize queue and slab now that generations are guaranteed. */ |
1454 | 0 | init_best_branch_base(&best_branch_base); |
1455 | 0 | set_best(tip, -1); |
1456 | 0 | prio_queue_put(&queue, tip); |
1457 | |
|
1458 | 0 | for (size_t i = 0; i < bases_nr; i++) { |
1459 | 0 | struct commit *c = bases[i]; |
1460 | 0 | int best = get_best(c); |
1461 | | |
1462 | | /* Has this already been marked as best by another commit? */ |
1463 | 0 | if (best) { |
1464 | 0 | if (best == -1) { |
1465 | | /* We agree at this position. Stop now. */ |
1466 | 0 | best_index = i + 1; |
1467 | 0 | goto cleanup; |
1468 | 0 | } |
1469 | 0 | continue; |
1470 | 0 | } |
1471 | | |
1472 | 0 | set_best(c, i + 1); |
1473 | 0 | prio_queue_put(&queue, c); |
1474 | 0 | } |
1475 | | |
1476 | 0 | while ((c = prio_queue_get(&queue))) { |
1477 | 0 | int best_for_c = get_best(c); |
1478 | 0 | int best_for_p, positive; |
1479 | 0 | struct commit *parent; |
1480 | | |
1481 | | /* Have we reached a known branch point? It's optimal. */ |
1482 | 0 | if (c == branch_point) |
1483 | 0 | break; |
1484 | | |
1485 | 0 | repo_parse_commit(r, c); |
1486 | 0 | if (!c->parents) |
1487 | 0 | continue; |
1488 | | |
1489 | 0 | parent = c->parents->item; |
1490 | 0 | repo_parse_commit(r, parent); |
1491 | 0 | best_for_p = get_best(parent); |
1492 | |
|
1493 | 0 | if (!best_for_p) { |
1494 | | /* 'parent' is new, so pass along best_for_c. */ |
1495 | 0 | set_best(parent, best_for_c); |
1496 | 0 | prio_queue_put(&queue, parent); |
1497 | 0 | continue; |
1498 | 0 | } |
1499 | | |
1500 | 0 | if (best_for_p > 0 && best_for_c > 0) { |
1501 | | /* Collision among bases. Minimize. */ |
1502 | 0 | if (best_for_c < best_for_p) |
1503 | 0 | set_best(parent, best_for_c); |
1504 | 0 | continue; |
1505 | 0 | } |
1506 | | |
1507 | | /* |
1508 | | * At this point, we have reached a commit that is reachable |
1509 | | * from the tip, either from 'c' or from an earlier commit to |
1510 | | * have 'parent' as its first parent. |
1511 | | * |
1512 | | * Update 'best_index' to match the minimum of all base indices |
1513 | | * to reach 'parent'. |
1514 | | */ |
1515 | | |
1516 | | /* Exactly one is positive due to initial conditions. */ |
1517 | 0 | positive = (best_for_c < 0) ? best_for_p : best_for_c; |
1518 | |
|
1519 | 0 | if (best_index < 0 || positive < best_index) |
1520 | 0 | best_index = positive; |
1521 | | |
1522 | | /* No matter what, track that the parent is reachable from tip. */ |
1523 | 0 | set_best(parent, -1); |
1524 | 0 | branch_point = parent; |
1525 | 0 | } |
1526 | |
|
1527 | 0 | cleanup: |
1528 | 0 | clear_best_branch_base(&best_branch_base); |
1529 | 0 | clear_prio_queue(&queue); |
1530 | 0 | return best_index > 0 ? best_index - 1 : -1; |
1531 | 0 | } |