2323#include "list-objects.h"
2424#include "commit-slab.h"
2525#include "wildmatch.h"
26+ #include "prio-queue.h"
2627
2728#define MAX_TAGS (FLAG_BITS - 1)
2829#define DEFAULT_CANDIDATES 10
@@ -249,32 +250,70 @@ static int compare_pt(const void *a_, const void *b_)
249250 return 0 ;
250251}
251252
252- static unsigned long finish_depth_computation (
253- struct commit_list * * list ,
254- struct possible_tag * best )
253+ struct lazy_queue {
254+ struct prio_queue queue ;
255+ bool get_pending ;
256+ };
257+
258+ #define LAZY_QUEUE_INIT { { compare_commits_by_commit_date }, false }
259+
260+ static void * lazy_queue_get (struct lazy_queue * queue )
261+ {
262+ if (queue -> get_pending )
263+ prio_queue_get (& queue -> queue );
264+ else
265+ queue -> get_pending = true;
266+ return prio_queue_peek (& queue -> queue );
267+ }
268+
269+ static void lazy_queue_put (struct lazy_queue * queue , void * thing )
270+ {
271+ if (queue -> get_pending )
272+ prio_queue_replace (& queue -> queue , thing );
273+ else
274+ prio_queue_put (& queue -> queue , thing );
275+ queue -> get_pending = false;
276+ }
277+
278+ static bool lazy_queue_empty (const struct lazy_queue * queue )
279+ {
280+ return queue -> queue .nr == (queue -> get_pending ? 1 : 0 );
281+ }
282+
283+ static void lazy_queue_clear (struct lazy_queue * queue )
284+ {
285+ clear_prio_queue (& queue -> queue );
286+ queue -> get_pending = false;
287+ }
288+
289+ static bool all_have_flag (const struct lazy_queue * queue , unsigned flag )
290+ {
291+ for (size_t i = queue -> get_pending ? 1 : 0 ; i < queue -> queue .nr ; i ++ ) {
292+ struct commit * commit = queue -> queue .array [i ].data ;
293+ if (!(commit -> object .flags & flag ))
294+ return false;
295+ }
296+ return true;
297+ }
298+
299+ static unsigned long finish_depth_computation (struct lazy_queue * queue ,
300+ struct possible_tag * best )
255301{
256302 unsigned long seen_commits = 0 ;
257- while (* list ) {
258- struct commit * c = pop_commit ( list );
303+ while (! lazy_queue_empty ( queue ) ) {
304+ struct commit * c = lazy_queue_get ( queue );
259305 struct commit_list * parents = c -> parents ;
260306 seen_commits ++ ;
261307 if (c -> object .flags & best -> flag_within ) {
262- struct commit_list * a = * list ;
263- while (a ) {
264- struct commit * i = a -> item ;
265- if (!(i -> object .flags & best -> flag_within ))
266- break ;
267- a = a -> next ;
268- }
269- if (!a )
308+ if (all_have_flag (queue , best -> flag_within ))
270309 break ;
271310 } else
272311 best -> depth ++ ;
273312 while (parents ) {
274313 struct commit * p = parents -> item ;
275314 repo_parse_commit (the_repository , p );
276315 if (!(p -> object .flags & SEEN ))
277- commit_list_insert_by_date ( p , list );
316+ lazy_queue_put ( queue , p );
278317 p -> object .flags |= c -> object .flags ;
279318 parents = parents -> next ;
280319 }
@@ -316,7 +355,7 @@ static void append_suffix(int depth, const struct object_id *oid, struct strbuf
316355static void describe_commit (struct object_id * oid , struct strbuf * dst )
317356{
318357 struct commit * cmit , * gave_up_on = NULL ;
319- struct commit_list * list ;
358+ struct lazy_queue queue = LAZY_QUEUE_INIT ;
320359 struct commit_name * n ;
321360 struct possible_tag all_matches [MAX_TAGS ];
322361 unsigned int match_cnt = 0 , annotated_cnt = 0 , cur_match ;
@@ -359,11 +398,10 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
359398 have_util = 1 ;
360399 }
361400
362- list = NULL ;
363401 cmit -> object .flags = SEEN ;
364- commit_list_insert ( cmit , & list );
365- while (list ) {
366- struct commit * c = pop_commit ( & list );
402+ lazy_queue_put ( & queue , cmit );
403+ while (! lazy_queue_empty ( & queue ) ) {
404+ struct commit * c = lazy_queue_get ( & queue );
367405 struct commit_list * parents = c -> parents ;
368406 struct commit_name * * slot ;
369407
@@ -397,7 +435,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
397435 t -> depth ++ ;
398436 }
399437 /* Stop if last remaining path already covered by best candidate(s) */
400- if (annotated_cnt && ! list ) {
438+ if (annotated_cnt && lazy_queue_empty ( & queue ) ) {
401439 int best_depth = INT_MAX ;
402440 unsigned best_within = 0 ;
403441 for (cur_match = 0 ; cur_match < match_cnt ; cur_match ++ ) {
@@ -420,7 +458,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
420458 struct commit * p = parents -> item ;
421459 repo_parse_commit (the_repository , p );
422460 if (!(p -> object .flags & SEEN ))
423- commit_list_insert_by_date ( p , & list );
461+ lazy_queue_put ( & queue , p );
424462 p -> object .flags |= c -> object .flags ;
425463 parents = parents -> next ;
426464
@@ -435,6 +473,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
435473 strbuf_add_unique_abbrev (dst , cmit_oid , abbrev );
436474 if (suffix )
437475 strbuf_addstr (dst , suffix );
476+ lazy_queue_clear (& queue );
438477 return ;
439478 }
440479 if (unannotated_cnt )
@@ -450,11 +489,11 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
450489 QSORT (all_matches , match_cnt , compare_pt );
451490
452491 if (gave_up_on ) {
453- commit_list_insert_by_date ( gave_up_on , & list );
492+ lazy_queue_put ( & queue , gave_up_on );
454493 seen_commits -- ;
455494 }
456- seen_commits += finish_depth_computation (& list , & all_matches [0 ]);
457- free_commit_list ( list );
495+ seen_commits += finish_depth_computation (& queue , & all_matches [0 ]);
496+ lazy_queue_clear ( & queue );
458497
459498 if (debug ) {
460499 static int label_width = -1 ;
0 commit comments