@@ -69,6 +69,23 @@ impl AuthorMap {
69
69
. extend ( set) ;
70
70
}
71
71
}
72
+
73
+ #[ must_use]
74
+ fn difference ( & self , other : & AuthorMap ) -> AuthorMap {
75
+ let mut new = AuthorMap :: new ( ) ;
76
+ new. map . reserve ( self . map . len ( ) ) ;
77
+ for ( author, set) in self . map . iter ( ) {
78
+ if let Some ( other_set) = other. map . get ( & author) {
79
+ let diff: HashSet < _ > = set. difference ( other_set) . cloned ( ) . collect ( ) ;
80
+ if !diff. is_empty ( ) {
81
+ new. map . insert ( author. clone ( ) , diff) ;
82
+ }
83
+ } else {
84
+ new. map . insert ( author. clone ( ) , set. clone ( ) ) ;
85
+ }
86
+ }
87
+ new
88
+ }
72
89
}
73
90
74
91
fn git ( args : & [ & str ] ) -> Result < String , Box < dyn std:: error:: Error > > {
@@ -165,6 +182,12 @@ impl fmt::Display for VersionTag {
165
182
}
166
183
}
167
184
185
+ impl std:: hash:: Hash for VersionTag {
186
+ fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
187
+ self . version . hash ( state) ;
188
+ }
189
+ }
190
+
168
191
impl cmp:: Eq for VersionTag { }
169
192
impl cmp:: PartialEq for VersionTag {
170
193
fn eq ( & self , other : & Self ) -> bool {
@@ -233,11 +256,13 @@ fn commit_coauthors(commit: &Commit) -> Vec<Author> {
233
256
}
234
257
235
258
for line in msg. lines ( ) . rev ( ) {
236
- if let Some ( caps) = RE . captures ( line) {
237
- coauthors. push ( Author {
238
- name : caps[ "name" ] . to_string ( ) ,
239
- email : caps[ "email" ] . to_string ( ) ,
240
- } ) ;
259
+ if line. starts_with ( "Co-authored-by" ) {
260
+ if let Some ( caps) = RE . captures ( line) {
261
+ coauthors. push ( Author {
262
+ name : caps[ "name" ] . to_string ( ) ,
263
+ email : caps[ "email" ] . to_string ( ) ,
264
+ } ) ;
265
+ }
241
266
}
242
267
}
243
268
}
@@ -378,6 +403,7 @@ fn build_author_map_(
378
403
for oid in walker {
379
404
let oid = oid?;
380
405
let commit = repo. find_commit ( oid) ?;
406
+
381
407
let mut commit_authors = Vec :: new ( ) ;
382
408
if !is_rollup_commit ( & commit) {
383
409
// We ignore the author of rollup-merge commits, and account for
@@ -424,6 +450,44 @@ fn mailmap_from_repo(repo: &git2::Repository) -> Result<Mailmap, Box<dyn std::er
424
450
Mailmap :: from_string ( file)
425
451
}
426
452
453
+ fn up_to_release (
454
+ repo : & Repository ,
455
+ reviewers : & Reviewers ,
456
+ mailmap : & Mailmap ,
457
+ to : & VersionTag ,
458
+ ) -> Result < AuthorMap , Box < dyn std:: error:: Error > > {
459
+ let to_commit = repo. find_commit ( to. commit ) . map_err ( |e| {
460
+ ErrorContext (
461
+ format ! (
462
+ "find_commit: repo={}, commit={}" ,
463
+ repo. path( ) . display( ) ,
464
+ to. commit
465
+ ) ,
466
+ Box :: new ( e) ,
467
+ )
468
+ } ) ?;
469
+ let modules = get_submodules ( & repo, & to_commit) ?;
470
+
471
+ let mut author_map = build_author_map ( & repo, & reviewers, & mailmap, "" , & to. raw_tag )
472
+ . map_err ( |e| ErrorContext ( format ! ( "Up to {}" , to) , e) ) ?;
473
+
474
+ for module in & modules {
475
+ if let Ok ( path) = update_repo ( & module. repository ) {
476
+ let subrepo = Repository :: open ( & path) ?;
477
+ let submap = build_author_map (
478
+ & subrepo,
479
+ & reviewers,
480
+ & mailmap,
481
+ "" ,
482
+ & module. commit . to_string ( ) ,
483
+ ) ?;
484
+ author_map. extend ( submap) ;
485
+ }
486
+ }
487
+
488
+ Ok ( author_map)
489
+ }
490
+
427
491
fn generate_thanks ( ) -> Result < BTreeMap < VersionTag , AuthorMap > , Box < dyn std:: error:: Error > > {
428
492
let path = update_repo ( "https://github.com/rust-lang/rust.git" ) ?;
429
493
let repo = git2:: Repository :: open ( & path) ?;
@@ -467,6 +531,8 @@ fn generate_thanks() -> Result<BTreeMap<VersionTag, AuthorMap>, Box<dyn std::err
467
531
468
532
let mut version_map = BTreeMap :: new ( ) ;
469
533
534
+ let mut cache = HashMap :: new ( ) ;
535
+
470
536
for ( idx, version) in versions. iter ( ) . enumerate ( ) {
471
537
let previous = if let Some ( v) = idx. checked_sub ( 1 ) . map ( |idx| & versions[ idx] ) {
472
538
v
@@ -478,75 +544,19 @@ fn generate_thanks() -> Result<BTreeMap<VersionTag, AuthorMap>, Box<dyn std::err
478
544
479
545
eprintln ! ( "Processing {:?} to {:?}" , previous, version) ;
480
546
481
- let mut modules: HashMap < PathBuf , ( Option < & Submodule > , Option < & Submodule > ) > =
482
- HashMap :: new ( ) ;
483
- let previous_commit = repo. find_commit ( previous. commit ) . map_err ( |e| {
484
- ErrorContext (
485
- format ! (
486
- "find_commit: repo={}, commit={}" ,
487
- repo. path( ) . display( ) ,
488
- previous. commit
489
- ) ,
490
- Box :: new ( e) ,
491
- )
492
- } ) ?;
493
- let previous_modules = get_submodules ( & repo, & previous_commit) ?;
494
- for module in & previous_modules {
495
- if let Ok ( path) = update_repo ( & module. repository ) {
496
- modules. insert ( path, ( Some ( module) , None ) ) ;
497
- }
498
- }
499
-
500
- let current_commit = repo. find_commit ( version. commit ) ?;
501
- let current_modules = get_submodules ( & repo, & current_commit) ?;
502
- for module in & current_modules {
503
- if let Ok ( path) = update_repo ( & module. repository ) {
504
- modules. entry ( path) . or_insert ( ( None , None ) ) . 1 = Some ( module) ;
505
- }
506
- }
507
-
508
- let mut author_map = build_author_map (
509
- & repo,
510
- & reviewers,
511
- & mailmap,
512
- & previous. raw_tag ,
513
- & version. raw_tag ,
514
- )
515
- . map_err ( |e| ErrorContext ( format ! ( "From {} to {}" , previous, version) , e) ) ?;
516
-
517
- for ( path, ( pre, cur) ) in & modules {
518
- match ( pre, cur) {
519
- ( Some ( previous) , Some ( current) ) => {
520
- let subrepo = Repository :: open ( & path) ?;
521
- let submap = build_author_map (
522
- & subrepo,
523
- & reviewers,
524
- & mailmap,
525
- & previous. commit . to_string ( ) ,
526
- & current. commit . to_string ( ) ,
527
- ) ?;
528
- author_map. extend ( submap) ;
529
- }
530
- ( None , Some ( current) ) => {
531
- let subrepo = Repository :: open ( & path) ?;
532
- let submap = build_author_map (
533
- & subrepo,
534
- & reviewers,
535
- & mailmap,
536
- "" ,
537
- & current. commit . to_string ( ) ,
538
- ) ?;
539
- author_map. extend ( submap) ;
540
- }
541
- ( None , None ) => unreachable ! ( ) ,
542
- ( Some ( _) , None ) => {
543
- // nothing, if submodule was deleted then we presume no changes since then
544
- // affect us
545
- }
546
- }
547
- }
547
+ cache. insert (
548
+ version,
549
+ up_to_release ( & repo, & reviewers, & mailmap, & version) ?,
550
+ ) ;
551
+ let previous = match cache. remove ( & previous) {
552
+ Some ( v) => v,
553
+ None => up_to_release ( & repo, & reviewers, & mailmap, & previous) ?,
554
+ } ;
555
+ let current = cache. get ( & version) . unwrap ( ) ;
548
556
549
- version_map. insert ( version. clone ( ) , author_map) ;
557
+ // Remove commits reachable from the previous release.
558
+ let only_current = current. difference ( & previous) ;
559
+ version_map. insert ( version. clone ( ) , only_current) ;
550
560
}
551
561
552
562
Ok ( version_map)
0 commit comments