commit-reach.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. #include "cache.h"
  2. #include "commit.h"
  3. #include "commit-graph.h"
  4. #include "decorate.h"
  5. #include "prio-queue.h"
  6. #include "tree.h"
  7. #include "ref-filter.h"
  8. #include "revision.h"
  9. #include "tag.h"
  10. #include "commit-reach.h"
  11. /* Remember to update object flag allocation in object.h */
  12. #define PARENT1 (1u<<16)
  13. #define PARENT2 (1u<<17)
  14. #define STALE (1u<<18)
  15. #define RESULT (1u<<19)
  16. static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
  17. static int queue_has_nonstale(struct prio_queue *queue)
  18. {
  19. int i;
  20. for (i = 0; i < queue->nr; i++) {
  21. struct commit *commit = queue->array[i].data;
  22. if (!(commit->object.flags & STALE))
  23. return 1;
  24. }
  25. return 0;
  26. }
  27. /* all input commits in one and twos[] must have been parsed! */
  28. static struct commit_list *paint_down_to_common(struct repository *r,
  29. struct commit *one, int n,
  30. struct commit **twos,
  31. int min_generation)
  32. {
  33. struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
  34. struct commit_list *result = NULL;
  35. int i;
  36. uint32_t last_gen = GENERATION_NUMBER_INFINITY;
  37. if (!min_generation)
  38. queue.compare = compare_commits_by_commit_date;
  39. one->object.flags |= PARENT1;
  40. if (!n) {
  41. commit_list_append(one, &result);
  42. return result;
  43. }
  44. prio_queue_put(&queue, one);
  45. for (i = 0; i < n; i++) {
  46. twos[i]->object.flags |= PARENT2;
  47. prio_queue_put(&queue, twos[i]);
  48. }
  49. while (queue_has_nonstale(&queue)) {
  50. struct commit *commit = prio_queue_get(&queue);
  51. struct commit_list *parents;
  52. int flags;
  53. uint32_t generation = commit_graph_generation(commit);
  54. if (min_generation && generation > last_gen)
  55. BUG("bad generation skip %8x > %8x at %s",
  56. generation, last_gen,
  57. oid_to_hex(&commit->object.oid));
  58. last_gen = generation;
  59. if (generation < min_generation)
  60. break;
  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);
  66. }
  67. /* Mark parents of a found merge stale */
  68. flags |= STALE;
  69. }
  70. parents = commit->parents;
  71. while (parents) {
  72. struct commit *p = parents->item;
  73. parents = parents->next;
  74. if ((p->object.flags & flags) == flags)
  75. continue;
  76. if (repo_parse_commit(r, p))
  77. return NULL;
  78. p->object.flags |= flags;
  79. prio_queue_put(&queue, p);
  80. }
  81. }
  82. clear_prio_queue(&queue);
  83. return result;
  84. }
  85. static struct commit_list *merge_bases_many(struct repository *r,
  86. struct commit *one, int n,
  87. struct commit **twos)
  88. {
  89. struct commit_list *list = NULL;
  90. struct commit_list *result = NULL;
  91. int i;
  92. for (i = 0; i < n; i++) {
  93. if (one == twos[i])
  94. /*
  95. * We do not mark this even with RESULT so we do not
  96. * have to clean it up.
  97. */
  98. return commit_list_insert(one, &result);
  99. }
  100. if (repo_parse_commit(r, one))
  101. return NULL;
  102. for (i = 0; i < n; i++) {
  103. if (repo_parse_commit(r, twos[i]))
  104. return NULL;
  105. }
  106. list = paint_down_to_common(r, one, n, twos, 0);
  107. while (list) {
  108. struct commit *commit = pop_commit(&list);
  109. if (!(commit->object.flags & STALE))
  110. commit_list_insert_by_date(commit, &result);
  111. }
  112. return result;
  113. }
  114. struct commit_list *get_octopus_merge_bases(struct commit_list *in)
  115. {
  116. struct commit_list *i, *j, *k, *ret = NULL;
  117. if (!in)
  118. return ret;
  119. commit_list_insert(in->item, &ret);
  120. for (i = in->next; i; i = i->next) {
  121. struct commit_list *new_commits = NULL, *end = NULL;
  122. for (j = ret; j; j = j->next) {
  123. struct commit_list *bases;
  124. bases = get_merge_bases(i->item, j->item);
  125. if (!new_commits)
  126. new_commits = bases;
  127. else
  128. end->next = bases;
  129. for (k = bases; k; k = k->next)
  130. end = k;
  131. }
  132. ret = new_commits;
  133. }
  134. return ret;
  135. }
  136. static int remove_redundant(struct repository *r, struct commit **array, int cnt)
  137. {
  138. /*
  139. * Some commit in the array may be an ancestor of
  140. * another commit. Move such commit to the end of
  141. * the array, and return the number of commits that
  142. * are independent from each other.
  143. */
  144. struct commit **work;
  145. unsigned char *redundant;
  146. int *filled_index;
  147. int i, j, filled;
  148. work = xcalloc(cnt, sizeof(*work));
  149. redundant = xcalloc(cnt, 1);
  150. ALLOC_ARRAY(filled_index, cnt - 1);
  151. for (i = 0; i < cnt; i++)
  152. repo_parse_commit(r, array[i]);
  153. for (i = 0; i < cnt; i++) {
  154. struct commit_list *common;
  155. uint32_t min_generation = commit_graph_generation(array[i]);
  156. if (redundant[i])
  157. continue;
  158. for (j = filled = 0; j < cnt; j++) {
  159. uint32_t curr_generation;
  160. if (i == j || redundant[j])
  161. continue;
  162. filled_index[filled] = j;
  163. work[filled++] = array[j];
  164. curr_generation = commit_graph_generation(array[j]);
  165. if (curr_generation < min_generation)
  166. min_generation = curr_generation;
  167. }
  168. common = paint_down_to_common(r, array[i], filled,
  169. work, min_generation);
  170. if (array[i]->object.flags & PARENT2)
  171. redundant[i] = 1;
  172. for (j = 0; j < filled; j++)
  173. if (work[j]->object.flags & PARENT1)
  174. redundant[filled_index[j]] = 1;
  175. clear_commit_marks(array[i], all_flags);
  176. clear_commit_marks_many(filled, work, all_flags);
  177. free_commit_list(common);
  178. }
  179. /* Now collect the result */
  180. COPY_ARRAY(work, array, cnt);
  181. for (i = filled = 0; i < cnt; i++)
  182. if (!redundant[i])
  183. array[filled++] = work[i];
  184. for (j = filled, i = 0; i < cnt; i++)
  185. if (redundant[i])
  186. array[j++] = work[i];
  187. free(work);
  188. free(redundant);
  189. free(filled_index);
  190. return filled;
  191. }
  192. static struct commit_list *get_merge_bases_many_0(struct repository *r,
  193. struct commit *one,
  194. int n,
  195. struct commit **twos,
  196. int cleanup)
  197. {
  198. struct commit_list *list;
  199. struct commit **rslt;
  200. struct commit_list *result;
  201. int cnt, i;
  202. result = merge_bases_many(r, one, n, twos);
  203. for (i = 0; i < n; i++) {
  204. if (one == twos[i])
  205. return result;
  206. }
  207. if (!result || !result->next) {
  208. if (cleanup) {
  209. clear_commit_marks(one, all_flags);
  210. clear_commit_marks_many(n, twos, all_flags);
  211. }
  212. return result;
  213. }
  214. /* There are more than one */
  215. cnt = commit_list_count(result);
  216. rslt = xcalloc(cnt, sizeof(*rslt));
  217. for (list = result, i = 0; list; list = list->next)
  218. rslt[i++] = list->item;
  219. free_commit_list(result);
  220. clear_commit_marks(one, all_flags);
  221. clear_commit_marks_many(n, twos, all_flags);
  222. cnt = remove_redundant(r, rslt, cnt);
  223. result = NULL;
  224. for (i = 0; i < cnt; i++)
  225. commit_list_insert_by_date(rslt[i], &result);
  226. free(rslt);
  227. return result;
  228. }
  229. struct commit_list *repo_get_merge_bases_many(struct repository *r,
  230. struct commit *one,
  231. int n,
  232. struct commit **twos)
  233. {
  234. return get_merge_bases_many_0(r, one, n, twos, 1);
  235. }
  236. struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
  237. struct commit *one,
  238. int n,
  239. struct commit **twos)
  240. {
  241. return get_merge_bases_many_0(r, one, n, twos, 0);
  242. }
  243. struct commit_list *repo_get_merge_bases(struct repository *r,
  244. struct commit *one,
  245. struct commit *two)
  246. {
  247. return get_merge_bases_many_0(r, one, 1, &two, 1);
  248. }
  249. /*
  250. * Is "commit" a descendant of one of the elements on the "with_commit" list?
  251. */
  252. int repo_is_descendant_of(struct repository *r,
  253. struct commit *commit,
  254. struct commit_list *with_commit)
  255. {
  256. if (!with_commit)
  257. return 1;
  258. if (generation_numbers_enabled(the_repository)) {
  259. struct commit_list *from_list = NULL;
  260. int result;
  261. commit_list_insert(commit, &from_list);
  262. result = can_all_from_reach(from_list, with_commit, 0);
  263. free_commit_list(from_list);
  264. return result;
  265. } else {
  266. while (with_commit) {
  267. struct commit *other;
  268. other = with_commit->item;
  269. with_commit = with_commit->next;
  270. if (repo_in_merge_bases_many(r, other, 1, &commit))
  271. return 1;
  272. }
  273. return 0;
  274. }
  275. }
  276. /*
  277. * Is "commit" an ancestor of one of the "references"?
  278. */
  279. int repo_in_merge_bases_many(struct repository *r, struct commit *commit,
  280. int nr_reference, struct commit **reference)
  281. {
  282. struct commit_list *bases;
  283. int ret = 0, i;
  284. uint32_t generation, max_generation = GENERATION_NUMBER_ZERO;
  285. if (repo_parse_commit(r, commit))
  286. return ret;
  287. for (i = 0; i < nr_reference; i++) {
  288. if (repo_parse_commit(r, reference[i]))
  289. return ret;
  290. generation = commit_graph_generation(reference[i]);
  291. if (generation > max_generation)
  292. max_generation = generation;
  293. }
  294. generation = commit_graph_generation(commit);
  295. if (generation > max_generation)
  296. return ret;
  297. bases = paint_down_to_common(r, commit,
  298. nr_reference, reference,
  299. generation);
  300. if (commit->object.flags & PARENT2)
  301. ret = 1;
  302. clear_commit_marks(commit, all_flags);
  303. clear_commit_marks_many(nr_reference, reference, all_flags);
  304. free_commit_list(bases);
  305. return ret;
  306. }
  307. /*
  308. * Is "commit" an ancestor of (i.e. reachable from) the "reference"?
  309. */
  310. int repo_in_merge_bases(struct repository *r,
  311. struct commit *commit,
  312. struct commit *reference)
  313. {
  314. int res;
  315. struct commit_list *list = NULL;
  316. struct commit_list **next = &list;
  317. next = commit_list_append(commit, next);
  318. res = repo_is_descendant_of(r, reference, list);
  319. free_commit_list(list);
  320. return res;
  321. }
  322. struct commit_list *reduce_heads(struct commit_list *heads)
  323. {
  324. struct commit_list *p;
  325. struct commit_list *result = NULL, **tail = &result;
  326. struct commit **array;
  327. int num_head, i;
  328. if (!heads)
  329. return NULL;
  330. /* Uniquify */
  331. for (p = heads; p; p = p->next)
  332. p->item->object.flags &= ~STALE;
  333. for (p = heads, num_head = 0; p; p = p->next) {
  334. if (p->item->object.flags & STALE)
  335. continue;
  336. p->item->object.flags |= STALE;
  337. num_head++;
  338. }
  339. array = xcalloc(num_head, sizeof(*array));
  340. for (p = heads, i = 0; p; p = p->next) {
  341. if (p->item->object.flags & STALE) {
  342. array[i++] = p->item;
  343. p->item->object.flags &= ~STALE;
  344. }
  345. }
  346. num_head = remove_redundant(the_repository, array, num_head);
  347. for (i = 0; i < num_head; i++)
  348. tail = &commit_list_insert(array[i], tail)->next;
  349. free(array);
  350. return result;
  351. }
  352. void reduce_heads_replace(struct commit_list **heads)
  353. {
  354. struct commit_list *result = reduce_heads(*heads);
  355. free_commit_list(*heads);
  356. *heads = result;
  357. }
  358. int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid)
  359. {
  360. struct object *o;
  361. struct commit *old_commit, *new_commit;
  362. struct commit_list *old_commit_list = NULL;
  363. int ret;
  364. /*
  365. * Both new_commit and old_commit must be commit-ish and new_commit is descendant of
  366. * old_commit. Otherwise we require --force.
  367. */
  368. o = deref_tag(the_repository, parse_object(the_repository, old_oid),
  369. NULL, 0);
  370. if (!o || o->type != OBJ_COMMIT)
  371. return 0;
  372. old_commit = (struct commit *) o;
  373. o = deref_tag(the_repository, parse_object(the_repository, new_oid),
  374. NULL, 0);
  375. if (!o || o->type != OBJ_COMMIT)
  376. return 0;
  377. new_commit = (struct commit *) o;
  378. if (parse_commit(new_commit) < 0)
  379. return 0;
  380. commit_list_insert(old_commit, &old_commit_list);
  381. ret = repo_is_descendant_of(the_repository,
  382. new_commit, old_commit_list);
  383. free_commit_list(old_commit_list);
  384. return ret;
  385. }
  386. /*
  387. * Mimicking the real stack, this stack lives on the heap, avoiding stack
  388. * overflows.
  389. *
  390. * At each recursion step, the stack items points to the commits whose
  391. * ancestors are to be inspected.
  392. */
  393. struct contains_stack {
  394. int nr, alloc;
  395. struct contains_stack_entry {
  396. struct commit *commit;
  397. struct commit_list *parents;
  398. } *contains_stack;
  399. };
  400. static int in_commit_list(const struct commit_list *want, struct commit *c)
  401. {
  402. for (; want; want = want->next)
  403. if (oideq(&want->item->object.oid, &c->object.oid))
  404. return 1;
  405. return 0;
  406. }
  407. /*
  408. * Test whether the candidate is contained in the list.
  409. * Do not recurse to find out, though, but return -1 if inconclusive.
  410. */
  411. static enum contains_result contains_test(struct commit *candidate,
  412. const struct commit_list *want,
  413. struct contains_cache *cache,
  414. uint32_t cutoff)
  415. {
  416. enum contains_result *cached = contains_cache_at(cache, candidate);
  417. /* If we already have the answer cached, return that. */
  418. if (*cached)
  419. return *cached;
  420. /* or are we it? */
  421. if (in_commit_list(want, candidate)) {
  422. *cached = CONTAINS_YES;
  423. return CONTAINS_YES;
  424. }
  425. /* Otherwise, we don't know; prepare to recurse */
  426. parse_commit_or_die(candidate);
  427. if (commit_graph_generation(candidate) < cutoff)
  428. return CONTAINS_NO;
  429. return CONTAINS_UNKNOWN;
  430. }
  431. static void push_to_contains_stack(struct commit *candidate, struct contains_stack *contains_stack)
  432. {
  433. ALLOC_GROW(contains_stack->contains_stack, contains_stack->nr + 1, contains_stack->alloc);
  434. contains_stack->contains_stack[contains_stack->nr].commit = candidate;
  435. contains_stack->contains_stack[contains_stack->nr++].parents = candidate->parents;
  436. }
  437. static enum contains_result contains_tag_algo(struct commit *candidate,
  438. const struct commit_list *want,
  439. struct contains_cache *cache)
  440. {
  441. struct contains_stack contains_stack = { 0, 0, NULL };
  442. enum contains_result result;
  443. uint32_t cutoff = GENERATION_NUMBER_INFINITY;
  444. const struct commit_list *p;
  445. for (p = want; p; p = p->next) {
  446. uint32_t generation;
  447. struct commit *c = p->item;
  448. load_commit_graph_info(the_repository, c);
  449. generation = commit_graph_generation(c);
  450. if (generation < cutoff)
  451. cutoff = generation;
  452. }
  453. result = contains_test(candidate, want, cache, cutoff);
  454. if (result != CONTAINS_UNKNOWN)
  455. return result;
  456. push_to_contains_stack(candidate, &contains_stack);
  457. while (contains_stack.nr) {
  458. struct contains_stack_entry *entry = &contains_stack.contains_stack[contains_stack.nr - 1];
  459. struct commit *commit = entry->commit;
  460. struct commit_list *parents = entry->parents;
  461. if (!parents) {
  462. *contains_cache_at(cache, commit) = CONTAINS_NO;
  463. contains_stack.nr--;
  464. }
  465. /*
  466. * If we just popped the stack, parents->item has been marked,
  467. * therefore contains_test will return a meaningful yes/no.
  468. */
  469. else switch (contains_test(parents->item, want, cache, cutoff)) {
  470. case CONTAINS_YES:
  471. *contains_cache_at(cache, commit) = CONTAINS_YES;
  472. contains_stack.nr--;
  473. break;
  474. case CONTAINS_NO:
  475. entry->parents = parents->next;
  476. break;
  477. case CONTAINS_UNKNOWN:
  478. push_to_contains_stack(parents->item, &contains_stack);
  479. break;
  480. }
  481. }
  482. free(contains_stack.contains_stack);
  483. return contains_test(candidate, want, cache, cutoff);
  484. }
  485. int commit_contains(struct ref_filter *filter, struct commit *commit,
  486. struct commit_list *list, struct contains_cache *cache)
  487. {
  488. if (filter->with_commit_tag_algo)
  489. return contains_tag_algo(commit, list, cache) == CONTAINS_YES;
  490. return repo_is_descendant_of(the_repository, commit, list);
  491. }
  492. static int compare_commits_by_gen(const void *_a, const void *_b)
  493. {
  494. const struct commit *a = *(const struct commit * const *)_a;
  495. const struct commit *b = *(const struct commit * const *)_b;
  496. uint32_t generation_a = commit_graph_generation(a);
  497. uint32_t generation_b = commit_graph_generation(b);
  498. if (generation_a < generation_b)
  499. return -1;
  500. if (generation_a > generation_b)
  501. return 1;
  502. return 0;
  503. }
  504. int can_all_from_reach_with_flag(struct object_array *from,
  505. unsigned int with_flag,
  506. unsigned int assign_flag,
  507. time_t min_commit_date,
  508. uint32_t min_generation)
  509. {
  510. struct commit **list = NULL;
  511. int i;
  512. int nr_commits;
  513. int result = 1;
  514. ALLOC_ARRAY(list, from->nr);
  515. nr_commits = 0;
  516. for (i = 0; i < from->nr; i++) {
  517. struct object *from_one = from->objects[i].item;
  518. if (!from_one || from_one->flags & assign_flag)
  519. continue;
  520. from_one = deref_tag(the_repository, from_one,
  521. "a from object", 0);
  522. if (!from_one || from_one->type != OBJ_COMMIT) {
  523. /*
  524. * no way to tell if this is reachable by
  525. * looking at the ancestry chain alone, so
  526. * leave a note to ourselves not to worry about
  527. * this object anymore.
  528. */
  529. from->objects[i].item->flags |= assign_flag;
  530. continue;
  531. }
  532. list[nr_commits] = (struct commit *)from_one;
  533. if (parse_commit(list[nr_commits]) ||
  534. commit_graph_generation(list[nr_commits]) < min_generation) {
  535. result = 0;
  536. goto cleanup;
  537. }
  538. nr_commits++;
  539. }
  540. QSORT(list, nr_commits, compare_commits_by_gen);
  541. for (i = 0; i < nr_commits; i++) {
  542. /* DFS from list[i] */
  543. struct commit_list *stack = NULL;
  544. list[i]->object.flags |= assign_flag;
  545. commit_list_insert(list[i], &stack);
  546. while (stack) {
  547. struct commit_list *parent;
  548. if (stack->item->object.flags & (with_flag | RESULT)) {
  549. pop_commit(&stack);
  550. if (stack)
  551. stack->item->object.flags |= RESULT;
  552. continue;
  553. }
  554. for (parent = stack->item->parents; parent; parent = parent->next) {
  555. if (parent->item->object.flags & (with_flag | RESULT))
  556. stack->item->object.flags |= RESULT;
  557. if (!(parent->item->object.flags & assign_flag)) {
  558. parent->item->object.flags |= assign_flag;
  559. if (parse_commit(parent->item) ||
  560. parent->item->date < min_commit_date ||
  561. commit_graph_generation(parent->item) < min_generation)
  562. continue;
  563. commit_list_insert(parent->item, &stack);
  564. break;
  565. }
  566. }
  567. if (!parent)
  568. pop_commit(&stack);
  569. }
  570. if (!(list[i]->object.flags & (with_flag | RESULT))) {
  571. result = 0;
  572. goto cleanup;
  573. }
  574. }
  575. cleanup:
  576. clear_commit_marks_many(nr_commits, list, RESULT | assign_flag);
  577. free(list);
  578. for (i = 0; i < from->nr; i++)
  579. from->objects[i].item->flags &= ~assign_flag;
  580. return result;
  581. }
  582. int can_all_from_reach(struct commit_list *from, struct commit_list *to,
  583. int cutoff_by_min_date)
  584. {
  585. struct object_array from_objs = OBJECT_ARRAY_INIT;
  586. time_t min_commit_date = cutoff_by_min_date ? from->item->date : 0;
  587. struct commit_list *from_iter = from, *to_iter = to;
  588. int result;
  589. uint32_t min_generation = GENERATION_NUMBER_INFINITY;
  590. while (from_iter) {
  591. add_object_array(&from_iter->item->object, NULL, &from_objs);
  592. if (!parse_commit(from_iter->item)) {
  593. uint32_t generation;
  594. if (from_iter->item->date < min_commit_date)
  595. min_commit_date = from_iter->item->date;
  596. generation = commit_graph_generation(from_iter->item);
  597. if (generation < min_generation)
  598. min_generation = generation;
  599. }
  600. from_iter = from_iter->next;
  601. }
  602. while (to_iter) {
  603. if (!parse_commit(to_iter->item)) {
  604. uint32_t generation;
  605. if (to_iter->item->date < min_commit_date)
  606. min_commit_date = to_iter->item->date;
  607. generation = commit_graph_generation(to_iter->item);
  608. if (generation < min_generation)
  609. min_generation = generation;
  610. }
  611. to_iter->item->object.flags |= PARENT2;
  612. to_iter = to_iter->next;
  613. }
  614. result = can_all_from_reach_with_flag(&from_objs, PARENT2, PARENT1,
  615. min_commit_date, min_generation);
  616. while (from) {
  617. clear_commit_marks(from->item, PARENT1);
  618. from = from->next;
  619. }
  620. while (to) {
  621. clear_commit_marks(to->item, PARENT2);
  622. to = to->next;
  623. }
  624. object_array_clear(&from_objs);
  625. return result;
  626. }
  627. struct commit_list *get_reachable_subset(struct commit **from, int nr_from,
  628. struct commit **to, int nr_to,
  629. unsigned int reachable_flag)
  630. {
  631. struct commit **item;
  632. struct commit *current;
  633. struct commit_list *found_commits = NULL;
  634. struct commit **to_last = to + nr_to;
  635. struct commit **from_last = from + nr_from;
  636. uint32_t min_generation = GENERATION_NUMBER_INFINITY;
  637. int num_to_find = 0;
  638. struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
  639. for (item = to; item < to_last; item++) {
  640. uint32_t generation;
  641. struct commit *c = *item;
  642. parse_commit(c);
  643. generation = commit_graph_generation(c);
  644. if (generation < min_generation)
  645. min_generation = generation;
  646. if (!(c->object.flags & PARENT1)) {
  647. c->object.flags |= PARENT1;
  648. num_to_find++;
  649. }
  650. }
  651. for (item = from; item < from_last; item++) {
  652. struct commit *c = *item;
  653. if (!(c->object.flags & PARENT2)) {
  654. c->object.flags |= PARENT2;
  655. parse_commit(c);
  656. prio_queue_put(&queue, *item);
  657. }
  658. }
  659. while (num_to_find && (current = prio_queue_get(&queue)) != NULL) {
  660. struct commit_list *parents;
  661. if (current->object.flags & PARENT1) {
  662. current->object.flags &= ~PARENT1;
  663. current->object.flags |= reachable_flag;
  664. commit_list_insert(current, &found_commits);
  665. num_to_find--;
  666. }
  667. for (parents = current->parents; parents; parents = parents->next) {
  668. struct commit *p = parents->item;
  669. parse_commit(p);
  670. if (commit_graph_generation(p) < min_generation)
  671. continue;
  672. if (p->object.flags & PARENT2)
  673. continue;
  674. p->object.flags |= PARENT2;
  675. prio_queue_put(&queue, p);
  676. }
  677. }
  678. clear_commit_marks_many(nr_to, to, PARENT1);
  679. clear_commit_marks_many(nr_from, from, PARENT2);
  680. return found_commits;
  681. }