diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-11 15:07:26 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-11 15:07:26 +0000 |
commit | 6282dd78339f98cbc5624e7fdf744a342d3d8b73 (patch) | |
tree | 50952cb7a6f9ead4c805c20227871d3be845cc98 /tooling/lib | |
parent | b9ab87c14ce9ebe8284aeffa32c1cee934156e58 (diff) | |
download | gitlab-ce-6282dd78339f98cbc5624e7fdf744a342d3d8b73.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'tooling/lib')
-rw-r--r-- | tooling/lib/tooling/find_codeowners.rb | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/tooling/lib/tooling/find_codeowners.rb b/tooling/lib/tooling/find_codeowners.rb new file mode 100644 index 00000000000..35d8a9d7461 --- /dev/null +++ b/tooling/lib/tooling/find_codeowners.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +require 'yaml' + +module Tooling + class FindCodeowners + def execute + load_definitions.each do |section, group_defintions| + puts section + + group_defintions.each do |group, list| + matched_files = git_ls_files.each_line.select do |line| + list[:allow].find do |pattern| + path = "/#{line.chomp}" + + path_matches?(pattern, path) && + list[:deny].none? { |pattern| path_matches?(pattern, path) } + end + end + + consolidated = consolidate_paths(matched_files) + consolidated_again = consolidate_paths(consolidated) + + # Consider the directory structure is a tree structure: + # https://en.wikipedia.org/wiki/Tree_(data_structure) + # After we consolidated the leaf entries, it could be possible that + # we can consolidate further for the new leaves. Repeat this + # process until we see no improvements. + while consolidated_again.size < consolidated.size + consolidated = consolidated_again + consolidated_again = consolidate_paths(consolidated) + end + + consolidated.each do |file| + puts "/#{file.chomp} #{group}" + end + end + end + end + + def load_definitions + result = load_config + + result.each do |section, group_defintions| + group_defintions.each do |group, definitions| + definitions.transform_values! do |rules| + rules[:keywords].flat_map do |keyword| + rules[:patterns].map do |pattern| + pattern % { keyword: keyword } + end + end + end + end + end + + result + end + + def load_config + config_path = "#{__dir__}/../../config/CODEOWNERS.yml" + + if YAML.respond_to?(:safe_load_file) # Ruby 3.0+ + YAML.safe_load_file(config_path, symbolize_names: true) + else + YAML.safe_load(File.read(config_path), symbolize_names: true) + end + end + + # Copied and modified from ee/lib/gitlab/code_owners/file.rb + def path_matches?(pattern, path) + # `FNM_DOTMATCH` makes sure we also match files starting with a `.` + # `FNM_PATHNAME` makes sure ** matches path separators + flags = ::File::FNM_DOTMATCH | ::File::FNM_PATHNAME + + # BEGIN extension + flags |= ::File::FNM_EXTGLOB + # END extension + + ::File.fnmatch?(pattern, path, flags) + end + + def consolidate_paths(matched_files) + matched_files.group_by(&File.method(:dirname)).flat_map do |dir, files| + # First line is the dir itself + if find_dir_maxdepth_1(dir).lines.drop(1).sort == files.sort + "#{dir}\n" + else + files + end + end.sort + end + + private + + def find_dir_maxdepth_1(dir) + `find #{dir} -maxdepth 1` + end + + def git_ls_files + @git_ls_files ||= `git ls-files` + end + end +end |