@@ -39,7 +39,8 @@ def globs_to_owner(files)
3939 owner = file_annotation_based_owner ( filename_relative_to_root )
4040 next unless owner
4141
42- mapping [ filename_relative_to_root ] = owner
42+ escaped_filename = escaped_path_for_codeowners_file ( filename_relative_to_root )
43+ mapping [ escaped_filename ] = owner
4344 end
4445 end
4546
@@ -55,7 +56,8 @@ def update_cache(cache, files)
5556
5657 invalid_files = cache . keys . select do |file |
5758 # If a file is not tracked, it should be removed from the cache
58- !Private . file_tracked? ( file ) ||
59+ unescaped_file = unescaped_path_for_codeowners_file ( file )
60+ !Private . file_tracked? ( unescaped_file ) ||
5961 # If a file no longer has a file annotation (i.e. `globs_to_owner` doesn't map it)
6062 # it should be removed from the cache
6163 # We make sure to only apply this to the input files since otherwise `updated_cache_for_files.key?(file)` would always return `false` when files == []
@@ -126,6 +128,32 @@ def description
126128
127129 sig { override . void }
128130 def bust_caches! ; end
131+
132+ sig { params ( filename : String ) . returns ( String ) }
133+ def escaped_path_for_codeowners_file ( filename )
134+ # Globs can contain certain regex characters, like "[" and "]".
135+ # However, when we are generating a glob from a file annotation, we
136+ # need to escape bracket characters and interpret them literally.
137+ # Otherwise the resulting glob will not actually match the directory
138+ # containing the file.
139+ #
140+ # Example
141+ # filename: "/some/[xId]/myfile.tsx"
142+ # matches: "/some/1/file"
143+ # matches: "/some/2/file"
144+ # matches: "/some/3/file"
145+ # does not match!: "/some/[xId]/myfile.tsx"
146+ filename . gsub ( /[\[ \] ]/ ) { |x | "\\ #{ x } " }
147+ end
148+
149+ sig { params ( filename : String ) . returns ( String ) }
150+ def unescaped_path_for_codeowners_file ( filename )
151+ # Globs can contain certain regex characters, like "[" and "]".
152+ # We escape bracket characters and interpret them literally for
153+ # the CODEOWNERS file. However, we want to compare the unescaped
154+ # glob to the actual file path when we check if the file was deleted.
155+ filename . gsub ( /\\ ([\[ \] ])/ , '\1' )
156+ end
129157 end
130158 end
131159 end
0 commit comments