@@ -510,6 +510,68 @@ struct commit *pop_commit(struct commit_list **stack)
510510/* count number of children that have not been emitted */
511511define_commit_slab (indegree_slab , int );
512512
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+
513575static int compare_commits_by_commit_date (const void * a_ , const void * b_ , void * unused )
514576{
515577const struct commit * a = a_ , * b = b_ ;
@@ -531,26 +593,36 @@ void sort_in_topological_order(struct commit_list **list, enum rev_sort_order so
531593struct indegree_slab indegree ;
532594struct prio_queue queue ;
533595struct commit * commit ;
596+ struct author_date_slab author_date ;
534597
535598if (!orig )
536599return ;
537600* list = NULL ;
538601
539602init_indegree_slab (& indegree );
540603memset (& queue , '\0' , sizeof (queue ));
604+
541605switch (sort_order ) {
542606default : /* REV_SORT_IN_GRAPH_ORDER */
543607queue .compare = NULL ;
544608break ;
545609case REV_SORT_BY_COMMIT_DATE :
546610queue .compare = compare_commits_by_commit_date ;
547611break ;
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 ;
548617}
549618
550619/* Mark them and clear the indegree */
551620for (next = orig ; next ; next = next -> next ) {
552621struct commit * commit = next -> item ;
553622* (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 );
554626}
555627
556628/* update the indegree */
@@ -621,6 +693,8 @@ void sort_in_topological_order(struct commit_list **list, enum rev_sort_order so
621693
622694clear_indegree_slab (& indegree );
623695clear_prio_queue (& queue );
696+ if (sort_order == REV_SORT_BY_AUTHOR_DATE )
697+ clear_author_date_slab (& author_date );
624698}
625699
626700/* merge-base stuff */
0 commit comments