@@ -10,6 +10,8 @@ class DirectoryOwnership
1010 include Mapper
1111
1212 CODEOWNERS_DIRECTORY_FILE_NAME = '.codeowner'
13+ RELATIVE_ROOT = Pathname ( '.' ) . freeze
14+ ABSOLUTE_ROOT = Pathname ( '/' ) . freeze
1315
1416 @@directory_cache = T . let ( { } , T ::Hash [ String , T . nilable ( CodeTeams ::Team ) ] ) # rubocop:disable Style/ClassVars
1517
@@ -74,36 +76,46 @@ def owner_for_codeowners_file(codeowners_file)
7476 )
7577 end
7678
77- # takes a file and finds the relevant `.codeowner` file by walking up the directory
79+ # Takes a file and finds the relevant `.codeowner` file by walking up the directory
7880 # structure. Example, given `a/b/c.rb`, this looks for `a/b/.codeowner`, `a/.codeowner`,
7981 # and `.codeowner` in that order, stopping at the first file to actually exist.
80- # We do additional caching so that we don't have to check for file existence every time
82+ # If the parovided file is a directory, it will look for `.codeowner` in that directory and then upwards.
83+ # We do additional caching so that we don't have to check for file existence every time.
8184 sig { params ( file : String ) . returns ( T . nilable ( CodeTeams ::Team ) ) }
8285 def map_file_to_relevant_owner ( file )
8386 file_path = Pathname . new ( file )
84- path_components = file_path . each_filename . to_a . map { | path | Pathname . new ( path ) }
87+ team = T . let ( nil , T . nilable ( CodeTeams :: Team ) )
8588
86- ( path_components . length - 1 ) . downto ( 0 ) . each do |i |
87- potential_relative_path_name = T . must ( path_components [ 0 ...i ] ) . reduce ( Pathname . new ( '' ) ) { |built_path , path | built_path . join ( path ) }
88- potential_codeowners_file = potential_relative_path_name . join ( CODEOWNERS_DIRECTORY_FILE_NAME )
89+ if File . directory? ( file )
90+ team = get_team_from_codeowners_file_within_directory ( file_path )
91+ end
92+
93+ while team . nil? && file_path != RELATIVE_ROOT && file_path != ABSOLUTE_ROOT
94+ file_path = file_path . parent
95+ team = get_team_from_codeowners_file_within_directory ( file_path )
96+ end
97+
98+ team
99+ end
89100
90- potential_codeowners_file_name = potential_codeowners_file . to_s
101+ sig { params ( directory : Pathname ) . returns ( T . nilable ( CodeTeams ::Team ) ) }
102+ def get_team_from_codeowners_file_within_directory ( directory )
103+ potential_codeowners_file = directory . join ( CODEOWNERS_DIRECTORY_FILE_NAME )
91104
92- team = nil
93- if @@directory_cache . key? ( potential_codeowners_file_name )
94- team = @@directory_cache [ potential_codeowners_file_name ]
95- elsif potential_codeowners_file . exist?
96- team = owner_for_codeowners_file ( potential_codeowners_file )
105+ potential_codeowners_file_name = potential_codeowners_file . to_s
97106
98- @@directory_cache [ potential_codeowners_file_name ] = team
99- else
100- @@directory_cache [ potential_codeowners_file_name ] = nil
101- end
107+ team = nil
108+ if @@directory_cache . key? ( potential_codeowners_file_name )
109+ team = @@directory_cache [ potential_codeowners_file_name ]
110+ elsif potential_codeowners_file . exist?
111+ team = owner_for_codeowners_file ( potential_codeowners_file )
102112
103- return team unless team . nil?
113+ @@directory_cache [ potential_codeowners_file_name ] = team
114+ else
115+ @@directory_cache [ potential_codeowners_file_name ] = nil
104116 end
105117
106- nil
118+ return team
107119 end
108120 end
109121 end
0 commit comments