2 #include "prio-queue.h"
4 #include "commit-reach.h"
6 /* Remember to update object flag allocation in object.h */
7 #define PARENT1 (1u<<16)
8 #define PARENT2 (1u<<17)
10 #define RESULT (1u<<19)
12 static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
14 static int queue_has_nonstale(struct prio_queue *queue)
17 for (i = 0; i < queue->nr; i++) {
18 struct commit *commit = queue->array[i].data;
19 if (!(commit->object.flags & STALE))
25 /* all input commits in one and twos[] must have been parsed! */
26 static struct commit_list *paint_down_to_common(struct commit *one, int n,
30 struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
31 struct commit_list *result = NULL;
33 uint32_t last_gen = GENERATION_NUMBER_INFINITY;
35 one->object.flags |= PARENT1;
37 commit_list_append(one, &result);
40 prio_queue_put(&queue, one);
42 for (i = 0; i < n; i++) {
43 twos[i]->object.flags |= PARENT2;
44 prio_queue_put(&queue, twos[i]);
47 while (queue_has_nonstale(&queue)) {
48 struct commit *commit = prio_queue_get(&queue);
49 struct commit_list *parents;
52 if (commit->generation > last_gen)
53 BUG("bad generation skip %8x > %8x at %s",
54 commit->generation, last_gen,
55 oid_to_hex(&commit->object.oid));
56 last_gen = commit->generation;
58 if (commit->generation < min_generation)
61 flags = commit->object.flags & (PARENT1 | PARENT2 | STALE);
62 if (flags == (PARENT1 | PARENT2)) {
63 if (!(commit->object.flags & RESULT)) {
64 commit->object.flags |= RESULT;
65 commit_list_insert_by_date(commit, &result);
67 /* Mark parents of a found merge stale */
70 parents = commit->parents;
72 struct commit *p = parents->item;
73 parents = parents->next;
74 if ((p->object.flags & flags) == flags)
78 p->object.flags |= flags;
79 prio_queue_put(&queue, p);
83 clear_prio_queue(&queue);
87 static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos)
89 struct commit_list *list = NULL;
90 struct commit_list *result = NULL;
93 for (i = 0; i < n; i++) {
96 * We do not mark this even with RESULT so we do not
97 * have to clean it up.
99 return commit_list_insert(one, &result);
102 if (parse_commit(one))
104 for (i = 0; i < n; i++) {
105 if (parse_commit(twos[i]))
109 list = paint_down_to_common(one, n, twos, 0);
112 struct commit *commit = pop_commit(&list);
113 if (!(commit->object.flags & STALE))
114 commit_list_insert_by_date(commit, &result);
119 struct commit_list *get_octopus_merge_bases(struct commit_list *in)
121 struct commit_list *i, *j, *k, *ret = NULL;
126 commit_list_insert(in->item, &ret);
128 for (i = in->next; i; i = i->next) {
129 struct commit_list *new_commits = NULL, *end = NULL;
131 for (j = ret; j; j = j->next) {
132 struct commit_list *bases;
133 bases = get_merge_bases(i->item, j->item);
138 for (k = bases; k; k = k->next)
146 static int remove_redundant(struct commit **array, int cnt)
149 * Some commit in the array may be an ancestor of
150 * another commit. Move such commit to the end of
151 * the array, and return the number of commits that
152 * are independent from each other.
154 struct commit **work;
155 unsigned char *redundant;
159 work = xcalloc(cnt, sizeof(*work));
160 redundant = xcalloc(cnt, 1);
161 ALLOC_ARRAY(filled_index, cnt - 1);
163 for (i = 0; i < cnt; i++)
164 parse_commit(array[i]);
165 for (i = 0; i < cnt; i++) {
166 struct commit_list *common;
167 uint32_t min_generation = array[i]->generation;
171 for (j = filled = 0; j < cnt; j++) {
172 if (i == j || redundant[j])
174 filled_index[filled] = j;
175 work[filled++] = array[j];
177 if (array[j]->generation < min_generation)
178 min_generation = array[j]->generation;
180 common = paint_down_to_common(array[i], filled, work,
182 if (array[i]->object.flags & PARENT2)
184 for (j = 0; j < filled; j++)
185 if (work[j]->object.flags & PARENT1)
186 redundant[filled_index[j]] = 1;
187 clear_commit_marks(array[i], all_flags);
188 clear_commit_marks_many(filled, work, all_flags);
189 free_commit_list(common);
192 /* Now collect the result */
193 COPY_ARRAY(work, array, cnt);
194 for (i = filled = 0; i < cnt; i++)
196 array[filled++] = work[i];
197 for (j = filled, i = 0; i < cnt; i++)
199 array[j++] = work[i];
206 static struct commit_list *get_merge_bases_many_0(struct commit *one,
208 struct commit **twos,
211 struct commit_list *list;
212 struct commit **rslt;
213 struct commit_list *result;
216 result = merge_bases_many(one, n, twos);
217 for (i = 0; i < n; i++) {
221 if (!result || !result->next) {
223 clear_commit_marks(one, all_flags);
224 clear_commit_marks_many(n, twos, all_flags);
229 /* There are more than one */
230 cnt = commit_list_count(result);
231 rslt = xcalloc(cnt, sizeof(*rslt));
232 for (list = result, i = 0; list; list = list->next)
233 rslt[i++] = list->item;
234 free_commit_list(result);
236 clear_commit_marks(one, all_flags);
237 clear_commit_marks_many(n, twos, all_flags);
239 cnt = remove_redundant(rslt, cnt);
241 for (i = 0; i < cnt; i++)
242 commit_list_insert_by_date(rslt[i], &result);
247 struct commit_list *get_merge_bases_many(struct commit *one,
249 struct commit **twos)
251 return get_merge_bases_many_0(one, n, twos, 1);
254 struct commit_list *get_merge_bases_many_dirty(struct commit *one,
256 struct commit **twos)
258 return get_merge_bases_many_0(one, n, twos, 0);
261 struct commit_list *get_merge_bases(struct commit *one, struct commit *two)
263 return get_merge_bases_many_0(one, 1, &two, 1);
267 * Is "commit" a descendant of one of the elements on the "with_commit" list?
269 int is_descendant_of(struct commit *commit, struct commit_list *with_commit)
273 while (with_commit) {
274 struct commit *other;
276 other = with_commit->item;
277 with_commit = with_commit->next;
278 if (in_merge_bases(other, commit))
285 * Is "commit" an ancestor of one of the "references"?
287 int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference)
289 struct commit_list *bases;
291 uint32_t min_generation = GENERATION_NUMBER_INFINITY;
293 if (parse_commit(commit))
295 for (i = 0; i < nr_reference; i++) {
296 if (parse_commit(reference[i]))
298 if (reference[i]->generation < min_generation)
299 min_generation = reference[i]->generation;
302 if (commit->generation > min_generation)
305 bases = paint_down_to_common(commit, nr_reference, reference, commit->generation);
306 if (commit->object.flags & PARENT2)
308 clear_commit_marks(commit, all_flags);
309 clear_commit_marks_many(nr_reference, reference, all_flags);
310 free_commit_list(bases);
315 * Is "commit" an ancestor of (i.e. reachable from) the "reference"?
317 int in_merge_bases(struct commit *commit, struct commit *reference)
319 return in_merge_bases_many(commit, 1, &reference);
322 struct commit_list *reduce_heads(struct commit_list *heads)
324 struct commit_list *p;
325 struct commit_list *result = NULL, **tail = &result;
326 struct commit **array;
333 for (p = heads; p; p = p->next)
334 p->item->object.flags &= ~STALE;
335 for (p = heads, num_head = 0; p; p = p->next) {
336 if (p->item->object.flags & STALE)
338 p->item->object.flags |= STALE;
341 array = xcalloc(num_head, sizeof(*array));
342 for (p = heads, i = 0; p; p = p->next) {
343 if (p->item->object.flags & STALE) {
344 array[i++] = p->item;
345 p->item->object.flags &= ~STALE;
348 num_head = remove_redundant(array, num_head);
349 for (i = 0; i < num_head; i++)
350 tail = &commit_list_insert(array[i], tail)->next;
355 void reduce_heads_replace(struct commit_list **heads)
357 struct commit_list *result = reduce_heads(*heads);
358 free_commit_list(*heads);