debian-mirror-gitlab/lib/gitlab/ci/build/rules/rule/clause/exists.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

80 lines
2.3 KiB
Ruby
Raw Normal View History

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)
2023-01-13 00:05:48 +05:30
@globs = Array(globs)
@top_level_only = @globs.all?(&method(:top_level_glob?))
2019-12-21 20:55:43 +05:30
end
2021-12-11 22:18:48 +05:30
def satisfied_by?(_pipeline, context)
paths = worktree_paths(context)
2023-01-13 00:05:48 +05:30
exact_globs, pattern_globs = separate_globs(context)
2019-12-21 20:55:43 +05:30
2023-01-13 00:05:48 +05:30
exact_matches?(paths, exact_globs) || pattern_matches?(paths, pattern_globs)
2019-12-21 20:55:43 +05:30
end
private
2023-01-13 00:05:48 +05:30
def separate_globs(context)
expanded_globs = expand_globs(context)
expanded_globs.partition(&method(:exact_glob?))
end
def expand_globs(context)
@globs.map do |glob|
ExpandVariables.expand_existing(glob, -> { context.variables_hash })
end
end
2021-12-11 22:18:48 +05:30
def worktree_paths(context)
2022-10-11 01:57:18 +05:30
return [] unless context.project
2021-12-11 22:18:48 +05:30
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
2023-01-13 00:05:48 +05:30
def exact_matches?(paths, exact_globs)
exact_globs.any? do |glob|
paths.bsearch { |path| glob <=> path }
end
2019-12-21 20:55:43 +05:30
end
2023-01-13 00:05:48 +05:30
def pattern_matches?(paths, pattern_globs)
2019-12-21 20:55:43 +05:30
comparisons = 0
2023-01-13 00:05:48 +05:30
pattern_globs.any? do |glob|
2019-12-21 20:55:43 +05:30
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