blob: aebd81e7b0798c32d08fb5d43893810cf95abbc9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
# 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
def satisfied_by?(_pipeline, context)
paths = worktree_paths(context)
exact_matches?(paths) || pattern_matches?(paths)
end
private
def worktree_paths(context)
return [] unless context.project
if @top_level_only
context.top_level_worktree_paths
else
context.all_worktree_paths
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
|