@@ -510,6 +510,68 @@ struct commit *pop_commit(struct commit_list **stack)
510
510
/* count number of children that have not been emitted */
511
511
define_commit_slab (indegree_slab , int );
512
512
513
+ /* record author-date for each commit object */
514
+ define_commit_slab (author_date_slab , unsigned long );
515
+
516
+ static void record_author_date (struct author_date_slab * author_date ,
517
+ struct commit * commit )
518
+ {
519
+ const char * buf , * line_end ;
520
+ char * buffer = NULL ;
521
+ struct ident_split ident ;
522
+ char * date_end ;
523
+ unsigned long date ;
524
+
525
+ if (!commit -> buffer ) {
526
+ unsigned long size ;
527
+ enum object_type type ;
528
+ buffer = read_sha1_file (commit -> object .sha1 , & type , & size );
529
+ if (!buffer )
530
+ return ;
531
+ }
532
+
533
+ for (buf = commit -> buffer ? commit -> buffer : buffer ;
534
+ buf ;
535
+ buf = line_end + 1 ) {
536
+ line_end = strchrnul (buf , '\n' );
537
+ if (prefixcmp (buf , "author " )) {
538
+ if (!line_end [0 ] || line_end [1 ] == '\n' )
539
+ return ; /* end of header */
540
+ continue ;
541
+ }
542
+ if (split_ident_line (& ident ,
543
+ buf + strlen ("author " ),
544
+ line_end - (buf + strlen ("author " ))) ||
545
+ !ident .date_begin || !ident .date_end )
546
+ goto fail_exit ; /* malformed "author" line */
547
+ break ;
548
+ }
549
+
550
+ date = strtoul (ident .date_begin , & date_end , 10 );
551
+ if (date_end != ident .date_end )
552
+ goto fail_exit ; /* malformed date */
553
+ * (author_date_slab_at (author_date , commit )) = date ;
554
+
555
+ fail_exit :
556
+ free (buffer );
557
+ }
558
+
559
+ static int compare_commits_by_author_date (const void * a_ , const void * b_ ,
560
+ void * cb_data )
561
+ {
562
+ const struct commit * a = a_ , * b = b_ ;
563
+ struct author_date_slab * author_date = cb_data ;
564
+ unsigned long a_date = * (author_date_slab_at (author_date , a ));
565
+ unsigned long b_date = * (author_date_slab_at (author_date , b ));
566
+
567
+ /* newer commits with larger date first */
568
+ if (a_date < b_date )
569
+ return 1 ;
570
+ else if (a_date > b_date )
571
+ return -1 ;
572
+ return 0 ;
573
+ }
574
+
513
575
static int compare_commits_by_commit_date (const void * a_ , const void * b_ , void * unused )
514
576
{
515
577
const struct commit * a = a_ , * b = b_ ;
@@ -531,26 +593,36 @@ void sort_in_topological_order(struct commit_list **list, enum rev_sort_order so
531
593
struct indegree_slab indegree ;
532
594
struct prio_queue queue ;
533
595
struct commit * commit ;
596
+ struct author_date_slab author_date ;
534
597
535
598
if (!orig )
536
599
return ;
537
600
* list = NULL ;
538
601
539
602
init_indegree_slab (& indegree );
540
603
memset (& queue , '\0' , sizeof (queue ));
604
+
541
605
switch (sort_order ) {
542
606
default : /* REV_SORT_IN_GRAPH_ORDER */
543
607
queue .compare = NULL ;
544
608
break ;
545
609
case REV_SORT_BY_COMMIT_DATE :
546
610
queue .compare = compare_commits_by_commit_date ;
547
611
break ;
612
+ case REV_SORT_BY_AUTHOR_DATE :
613
+ init_author_date_slab (& author_date );
614
+ queue .compare = compare_commits_by_author_date ;
615
+ queue .cb_data = & author_date ;
616
+ break ;
548
617
}
549
618
550
619
/* Mark them and clear the indegree */
551
620
for (next = orig ; next ; next = next -> next ) {
552
621
struct commit * commit = next -> item ;
553
622
* (indegree_slab_at (& indegree , commit )) = 1 ;
623
+ /* also record the author dates, if needed */
624
+ if (sort_order == REV_SORT_BY_AUTHOR_DATE )
625
+ record_author_date (& author_date , commit );
554
626
}
555
627
556
628
/* update the indegree */
@@ -621,6 +693,8 @@ void sort_in_topological_order(struct commit_list **list, enum rev_sort_order so
621
693
622
694
clear_indegree_slab (& indegree );
623
695
clear_prio_queue (& queue );
696
+ if (sort_order == REV_SORT_BY_AUTHOR_DATE )
697
+ clear_author_date_slab (& author_date );
624
698
}
625
699
626
700
/* merge-base stuff */
0 commit comments