2019-12-21 20:55:43 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Gitlab
|
|
|
|
module Ci
|
|
|
|
module Build
|
|
|
|
class Rules::Rule::Clause::Exists < Rules::Rule::Clause
|
|
|
|
# The maximum number of patterned glob comparisons that will be
|
|
|
|
# performed before the rule assumes that it has a match
|
|
|
|
MAX_PATTERN_COMPARISONS = 10_000
|
|
|
|
|
|
|
|
def initialize(globs)
|
|
|
|
globs = Array(globs)
|
|
|
|
|
|
|
|
@top_level_only = globs.all?(&method(:top_level_glob?))
|
|
|
|
@exact_globs, @pattern_globs = globs.partition(&method(:exact_glob?))
|
|
|
|
end
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
def satisfied_by?(_pipeline, context)
|
|
|
|
paths = worktree_paths(context)
|
2019-12-21 20:55:43 +05:30
|
|
|
|
|
|
|
exact_matches?(paths) || pattern_matches?(paths)
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
def worktree_paths(context)
|
|
|
|
return unless context.project
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
if @top_level_only
|
2021-12-11 22:18:48 +05:30
|
|
|
context.top_level_worktree_paths
|
2019-12-21 20:55:43 +05:30
|
|
|
else
|
2021-12-11 22:18:48 +05:30
|
|
|
context.all_worktree_paths
|
2019-12-21 20:55:43 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def exact_matches?(paths)
|
|
|
|
@exact_globs.any? { |glob| paths.bsearch { |path| glob <=> path } }
|
|
|
|
end
|
|
|
|
|
|
|
|
def pattern_matches?(paths)
|
|
|
|
comparisons = 0
|
|
|
|
@pattern_globs.any? do |glob|
|
|
|
|
paths.any? do |path|
|
|
|
|
comparisons += 1
|
|
|
|
comparisons > MAX_PATTERN_COMPARISONS || pattern_match?(glob, path)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def pattern_match?(glob, path)
|
|
|
|
File.fnmatch?(glob, path, File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB)
|
|
|
|
end
|
|
|
|
|
|
|
|
# matches glob patterns that only match files in the top level directory
|
|
|
|
def top_level_glob?(glob)
|
|
|
|
!glob.include?('/') && !glob.include?('**')
|
|
|
|
end
|
|
|
|
|
|
|
|
# matches glob patterns that have no metacharacters for File#fnmatch?
|
|
|
|
def exact_glob?(glob)
|
|
|
|
!glob.include?('*') && !glob.include?('?') && !glob.include?('[') && !glob.include?('{')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|