Use `git diff --name-only --diff-filer` to instead of `commits.each do( commit.diffs.each do)` can more efficiently to check git hook file_name_regex
Scenario
If a push contains more than 1000 commits or more, and I have set the git hook filename check. It takes a long time to check, although gitlab-shell has used an HTTP timeout of 5 minutes
Now code
https://gitlab.com/gitlab-org/gitlab-ee/blob/master/lib/gitlab/git_access.rb#L217
https://gitlab.com/gitlab-org/gitlab-ee/blob/master/lib/gitlab/git_access.rb#L277
commits(newrev, oldrev, project).each do |commit|
....
....
if status_object = check_commit(commit, git_hook)
return status_object
end
....
....
if git_hook.file_name_regex.present?
commit.diffs.each do |diff|
if (diff.renamed_file || diff.new_file) && diff.new_path =~ Regexp.new(git_hook.file_name_regex)
return build_status_object(false, "File name #{diff.new_path.inspect} is prohibited by the pattern '#{git_hook.file_name_regex}'")
end
.....
After optimize
....
....
if git_hook.file_name_regex.present?
arg = %W(#{Gitlab.config.git.bin_path} diff --name-only --diff-filter=ACMR #{oldrev} #{newrev})
all_commits_diffs_filenames = Gitlab::Popen.popen(arg)
check_result_index = (all_commits_diffs_filenames =~ Regexp.new(git_hook.file_name_regex))
if check_result_index
begin_index = all_commits_diffs_filenames.rindex("\n", check_result_index)
begin_index = 0 unless begin_index
last_index = all_commits_diffs_filenames.index("\n",check_result_index)
last_index = all_commits_diffs_filenames.size unless last_index
return build_status_object(false, "File name #{all_commits_diffs_filenames.slice(begin_index,last_index-begin_index)} is prohibited by the pattern '#{git_hook.file_name_regex}'")
....
....
Edited by 🤖 GitLab Bot 🤖