4 #include "prio-queue.h"
8 #include "commit-reach.h"
10 /* Remember to update object flag allocation in object.h */
11 #define PARENT1 (1u<<16)
12 #define PARENT2 (1u<<17)
13 #define STALE (1u<<18)
14 #define RESULT (1u<<19)
16 static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
18 static int queue_has_nonstale(struct prio_queue *queue)
21 for (i = 0; i < queue->nr; i++) {
22 struct commit *commit = queue->array[i].data;
23 if (!(commit->object.flags & STALE))
29 /* all input commits in one and twos[] must have been parsed! */
30 static struct commit_list *paint_down_to_common(struct commit *one, int n,
34 struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
35 struct commit_list *result = NULL;
37 uint32_t last_gen = GENERATION_NUMBER_INFINITY;
39 one->object.flags |= PARENT1;
41 commit_list_append(one, &result);
44 prio_queue_put(&queue, one);
46 for (i = 0; i < n; i++) {
47 twos[i]->object.flags |= PARENT2;
48 prio_queue_put(&queue, twos[i]);
51 while (queue_has_nonstale(&queue)) {
52 struct commit *commit = prio_queue_get(&queue);
53 struct commit_list *parents;
56 if (commit->generation > last_gen)
57 BUG("bad generation skip %8x > %8x at %s",
58 commit->generation, last_gen,
59 oid_to_hex(&commit->object.oid));
60 last_gen = commit->generation;
62 if (commit->generation < min_generation)
65 flags = commit->object.flags & (PARENT1 | PARENT2 | STALE);
66 if (flags == (PARENT1 | PARENT2)) {
67 if (!(commit->object.flags & RESULT)) {
68 commit->object.flags |= RESULT;
69 commit_list_insert_by_date(commit, &result);
71 /* Mark parents of a found merge stale */
74 parents = commit->parents;
76 struct commit *p = parents->item;
77 parents = parents->next;
78 if ((p->object.flags & flags) == flags)
82 p->object.flags |= flags;
83 prio_queue_put(&queue, p);
87 clear_prio_queue(&queue);
91 static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos)
93 struct commit_list *list = NULL;
94 struct commit_list *result = NULL;
97 for (i = 0; i < n; i++) {
100 * We do not mark this even with RESULT so we do not
101 * have to clean it up.
103 return commit_list_insert(one, &result);
106 if (parse_commit(one))
108 for (i = 0; i < n; i++) {
109 if (parse_commit(twos[i]))
113 list = paint_down_to_common(one, n, twos, 0);
116 struct commit *commit = pop_commit(&list);
117 if (!(commit->object.flags & STALE))
118 commit_list_insert_by_date(commit, &result);
123 struct commit_list *get_octopus_merge_bases(struct commit_list *in)
125 struct commit_list *i, *j, *k, *ret = NULL;
130 commit_list_insert(in->item, &ret);
132 for (i = in->next; i; i = i->next) {
133 struct commit_list *new_commits = NULL, *end = NULL;
135 for (j = ret; j; j = j->next) {
136 struct commit_list *bases;
137 bases = get_merge_bases(i->item, j->item);
142 for (k = bases; k; k = k->next)
150 static int remove_redundant(struct commit **array, int cnt)
153 * Some commit in the array may be an ancestor of
154 * another commit. Move such commit to the end of
155 * the array, and return the number of commits that
156 * are independent from each other.
158 struct commit **work;
159 unsigned char *redundant;
163 work = xcalloc(cnt, sizeof(*work));
164 redundant = xcalloc(cnt, 1);
165 ALLOC_ARRAY(filled_index, cnt - 1);
167 for (i = 0; i < cnt; i++)
168 parse_commit(array[i]);
169 for (i = 0; i < cnt; i++) {
170 struct commit_list *common;
171 uint32_t min_generation = array[i]->generation;
175 for (j = filled = 0; j < cnt; j++) {
176 if (i == j || redundant[j])
178 filled_index[filled] = j;
179 work[filled++] = array[j];
181 if (array[j]->generation < min_generation)
182 min_generation = array[j]->generation;
184 common = paint_down_to_common(array[i], filled, work,
186 if (array[i]->object.flags & PARENT2)
188 for (j = 0; j < filled; j++)
189 if (work[j]->object.flags & PARENT1)
190 redundant[filled_index[j]] = 1;
191 clear_commit_marks(array[i], all_flags);
192 clear_commit_marks_many(filled, work, all_flags);
193 free_commit_list(common);
196 /* Now collect the result */
197 COPY_ARRAY(work, array, cnt);
198 for (i = filled = 0; i < cnt; i++)
200 array[filled++] = work[i];
201 for (j = filled, i = 0; i < cnt; i++)
203 array[j++] = work[i];
210 static struct commit_list *get_merge_bases_many_0(struct commit *one,
212 struct commit **twos,
215 struct commit_list *list;
216 struct commit **rslt;
217 struct commit_list *result;
220 result = merge_bases_many(one, n, twos);
221 for (i = 0; i < n; i++) {
225 if (!result || !result->next) {
227 clear_commit_marks(one, all_flags);
228 clear_commit_marks_many(n, twos, all_flags);
233 /* There are more than one */
234 cnt = commit_list_count(result);
235 rslt = xcalloc(cnt, sizeof(*rslt));
236 for (list = result, i = 0; list; list = list->next)
237 rslt[i++] = list->item;
238 free_commit_list(result);
240 clear_commit_marks(one, all_flags);
241 clear_commit_marks_many(n, twos, all_flags);
243 cnt = remove_redundant(rslt, cnt);
245 for (i = 0; i < cnt; i++)
246 commit_list_insert_by_date(rslt[i], &result);
251 struct commit_list *get_merge_bases_many(struct commit *one,
253 struct commit **twos)
255 return get_merge_bases_many_0(one, n, twos, 1);
258 struct commit_list *get_merge_bases_many_dirty(struct commit *one,
260 struct commit **twos)
262 return get_merge_bases_many_0(one, n, twos, 0);
265 struct commit_list *get_merge_bases(struct commit *one, struct commit *two)
267 return get_merge_bases_many_0(one, 1, &two, 1);
271 * Is "commit" a descendant of one of the elements on the "with_commit" list?
273 int is_descendant_of(struct commit *commit, struct commit_list *with_commit)
277 while (with_commit) {
278 struct commit *other;
280 other = with_commit->item;
281 with_commit = with_commit->next;
282 if (in_merge_bases(other, commit))
289 * Is "commit" an ancestor of one of the "references"?
291 int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference)
293 struct commit_list *bases;
295 uint32_t min_generation = GENERATION_NUMBER_INFINITY;
297 if (parse_commit(commit))
299 for (i = 0; i < nr_reference; i++) {
300 if (parse_commit(reference[i]))
302 if (reference[i]->generation < min_generation)
303 min_generation = reference[i]->generation;
306 if (commit->generation > min_generation)
309 bases = paint_down_to_common(commit, nr_reference, reference, commit->generation);
310 if (commit->object.flags & PARENT2)
312 clear_commit_marks(commit, all_flags);
313 clear_commit_marks_many(nr_reference, reference, all_flags);
314 free_commit_list(bases);
319 * Is "commit" an ancestor of (i.e. reachable from) the "reference"?
321 int in_merge_bases(struct commit *commit, struct commit *reference)
323 return in_merge_bases_many(commit, 1, &reference);
326 struct commit_list *reduce_heads(struct commit_list *heads)
328 struct commit_list *p;
329 struct commit_list *result = NULL, **tail = &result;
330 struct commit **array;
337 for (p = heads; p; p = p->next)
338 p->item->object.flags &= ~STALE;
339 for (p = heads, num_head = 0; p; p = p->next) {
340 if (p->item->object.flags & STALE)
342 p->item->object.flags |= STALE;
345 array = xcalloc(num_head, sizeof(*array));
346 for (p = heads, i = 0; p; p = p->next) {
347 if (p->item->object.flags & STALE) {
348 array[i++] = p->item;
349 p->item->object.flags &= ~STALE;
352 num_head = remove_redundant(array, num_head);
353 for (i = 0; i < num_head; i++)
354 tail = &commit_list_insert(array[i], tail)->next;
359 void reduce_heads_replace(struct commit_list **heads)
361 struct commit_list *result = reduce_heads(*heads);
362 free_commit_list(*heads);
366 static void unmark_and_free(struct commit_list *list, unsigned int mark)
369 struct commit *commit = pop_commit(&list);
370 commit->object.flags &= ~mark;
374 int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid)
377 struct commit *old_commit, *new_commit;
378 struct commit_list *list, *used;
382 * Both new_commit and old_commit must be commit-ish and new_commit is descendant of
383 * old_commit. Otherwise we require --force.
385 o = deref_tag(the_repository, parse_object(the_repository, old_oid),
387 if (!o || o->type != OBJ_COMMIT)
389 old_commit = (struct commit *) o;
391 o = deref_tag(the_repository, parse_object(the_repository, new_oid),
393 if (!o || o->type != OBJ_COMMIT)
395 new_commit = (struct commit *) o;
397 if (parse_commit(new_commit) < 0)
401 commit_list_insert(new_commit, &list);
403 new_commit = pop_most_recent_commit(&list, TMP_MARK);
404 commit_list_insert(new_commit, &used);
405 if (new_commit == old_commit) {
410 unmark_and_free(list, TMP_MARK);
411 unmark_and_free(used, TMP_MARK);