@@ -31,6 +31,58 @@ def map_files_to_owners(files) # rubocop:disable Lint/UnusedMethodArgument
3131 end
3232 end
3333
34+ class MappingContext < T ::Struct
35+ const :glob , String
36+ const :team , CodeTeams ::Team
37+ end
38+
39+ class GlobOverlap < T ::Struct
40+ extend T ::Sig
41+
42+ const :mapping_contexts , T ::Array [ MappingContext ]
43+
44+ sig { returns ( String ) }
45+ def description
46+ # These are sorted only to prevent non-determinism in output between local and CI environments.
47+ sorted_contexts = mapping_contexts . sort_by { |context | context . team . config_yml . to_s }
48+ description_args = sorted_contexts . map do |context |
49+ "`#{ context . glob } ` (from `#{ context . team . config_yml } `)"
50+ end
51+
52+ description_args . join ( ', ' )
53+ end
54+ end
55+
56+ sig do
57+ returns ( T ::Array [ GlobOverlap ] )
58+ end
59+ def find_overlapping_globs
60+ mapped_files = T . let ( { } , T ::Hash [ String , T ::Array [ MappingContext ] ] )
61+ CodeTeams . all . each_with_object ( { } ) do |team , map | # rubocop:disable Style/ClassVars
62+ TeamPlugins ::Ownership . for ( team ) . owned_globs . each do |glob |
63+ Dir . glob ( glob ) . each do |filename |
64+ mapped_files [ filename ] ||= [ ]
65+ T . must ( mapped_files [ filename ] ) << MappingContext . new ( glob : glob , team : team )
66+ end
67+ end
68+ end
69+
70+ overlaps = T . let ( [ ] , T ::Array [ GlobOverlap ] )
71+ mapped_files . each do |filename , mapping_contexts |
72+ if mapping_contexts . count > 1
73+ overlaps << GlobOverlap . new ( mapping_contexts : mapping_contexts )
74+ end
75+ end
76+
77+ deduplicated_overlaps = overlaps . uniq do |glob_overlap |
78+ glob_overlap . mapping_contexts . map do |context |
79+ [ context . glob , context . team . name ]
80+ end
81+ end
82+
83+ deduplicated_overlaps
84+ end
85+
3486 sig do
3587 override . params ( file : String ) .
3688 returns ( T . nilable ( ::CodeTeams ::Team ) )
0 commit comments