summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/build
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-09-24 15:06:34 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-09-24 15:06:34 +0000
commitf1a5755898e865428c923587402fd965b601c4ea (patch)
treea93aab01a1d3ba0e93c0fbf1450babfe4674f9dc /lib/gitlab/ci/build
parent1ae627c65192ae1a01fdac253065ef561a9d6b7e (diff)
downloadgitlab-ce-f1a5755898e865428c923587402fd965b601c4ea.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib/gitlab/ci/build')
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause/exists.rb64
1 files changed, 64 insertions, 0 deletions
diff --git a/lib/gitlab/ci/build/rules/rule/clause/exists.rb b/lib/gitlab/ci/build/rules/rule/clause/exists.rb
new file mode 100644
index 00000000000..62f8371283f
--- /dev/null
+++ b/lib/gitlab/ci/build/rules/rule/clause/exists.rb
@@ -0,0 +1,64 @@
+# 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, seed)
+ paths = worktree_paths(pipeline)
+
+ exact_matches?(paths) || pattern_matches?(paths)
+ end
+
+ private
+
+ def worktree_paths(pipeline)
+ if @top_level_only
+ pipeline.top_level_worktree_paths
+ else
+ pipeline.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