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
);