Commit 2b0f880a authored by Bob Van Landuyt's avatar Bob Van Landuyt

Allow matching only the repo-root for CODEOWNERS

When wanting to match files in the repo root, but only on the repo's
root. Users would supply `/*` as the pattern.

In our old implementation we would match this pattern as `*`, but
allowing `*` to match directory separators.

In this we treat the `/*` pattern as an entirely separate case:
Matching all files in the root, but only one level deep.
parent 0cbb601b
---
title: Allow matching only the repo-root for CODEOWNERS
merge_request: 8708
author:
type: fixed
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
module Gitlab module Gitlab
module CodeOwners module CodeOwners
class File class File
ROOT_DIR_PATTERN = '/*'
def initialize(blob) def initialize(blob)
@blob = blob @blob = blob
end end
...@@ -52,6 +54,8 @@ module Gitlab ...@@ -52,6 +54,8 @@ module Gitlab
end end
def normalize_pattern(pattern) def normalize_pattern(pattern)
return ROOT_DIR_PATTERN if pattern == ROOT_DIR_PATTERN
# Remove `\` when escaping `\#` # Remove `\` when escaping `\#`
pattern = pattern.sub(/\A\\#/, '#') pattern = pattern.sub(/\A\\#/, '#')
# Replace all whitespace preceded by a \ with a regular whitespace # Replace all whitespace preceded by a \ with a regular whitespace
...@@ -74,7 +78,11 @@ module Gitlab ...@@ -74,7 +78,11 @@ module Gitlab
def path_matches?(pattern, path) def path_matches?(pattern, path)
flags = ::File::FNM_DOTMATCH flags = ::File::FNM_DOTMATCH
if pattern.ends_with?('/*') if pattern == ROOT_DIR_PATTERN
# Matching everyting on the root, but only one level deep
flags |= ::File::FNM_PATHNAME
::File.fnmatch?('*', path, flags)
elsif pattern.ends_with?('/*')
# Then the pattern ends in a wildcard, we only want to go one level deep # Then the pattern ends in a wildcard, we only want to go one level deep
# setting `::File::FNM_PATHNAME` makes the `*` not match directory # setting `::File::FNM_PATHNAME` makes the `*` not match directory
# separators # separators
......
...@@ -160,5 +160,23 @@ describe Gitlab::CodeOwners::File do ...@@ -160,5 +160,23 @@ describe Gitlab::CodeOwners::File do
expect(owners).not_to include('username', 'and-email@lookalikes.com') expect(owners).not_to include('username', 'and-email@lookalikes.com')
end end
end end
context 'a glob on the root directory' do
let(:file_content) do
'/* @user-1 @user-2'
end
it 'matches files in the root directory' do
owners = file.owners_for_path('README.md')
expect(owners).to include('user-1', 'user-2')
end
it 'does not match nested files' do
owners = file.owners_for_path('nested/path/README.md')
expect(owners).to be_nil
end
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment