diff options
author | Kamil Trzciński <ayufan@ayufan.eu> | 2019-04-03 15:34:28 +0200 |
---|---|---|
committer | Kamil Trzciński <ayufan@ayufan.eu> | 2019-04-03 15:34:28 +0200 |
commit | d416b61d10adf8df694342ece44eeda120fe83b3 (patch) | |
tree | c06ccbc97ec6de3234d2be7826739a79496b917a | |
parent | 741b3e99476310838ac929008b4bac5af56b2521 (diff) | |
download | gitlab-ce-make-ref-matcher-to-support-wildcard-fully.tar.gz |
More flexible wildcard matchermake-ref-matcher-to-support-wildcard-fully
-rw-r--r-- | app/models/concerns/protected_ref.rb | 2 | ||||
-rw-r--r-- | app/models/hooks/active_hook_filter.rb | 2 | ||||
-rw-r--r-- | app/models/ref_matcher.rb | 63 | ||||
-rw-r--r-- | lib/gitlab/ref_matcher.rb | 65 | ||||
-rw-r--r-- | spec/lib/gitlab/ref_matcher_spec.rb | 26 |
5 files changed, 93 insertions, 65 deletions
diff --git a/app/models/concerns/protected_ref.rb b/app/models/concerns/protected_ref.rb index af387c99f3d..10df945efdb 100644 --- a/app/models/concerns/protected_ref.rb +++ b/app/models/concerns/protected_ref.rb @@ -64,6 +64,6 @@ module ProtectedRef private def ref_matcher - @ref_matcher ||= RefMatcher.new(self.name) + @ref_matcher ||= Gitlab::RefMatcher.new(self.name) end end diff --git a/app/models/hooks/active_hook_filter.rb b/app/models/hooks/active_hook_filter.rb index 283e2d680f4..1094d544c8b 100644 --- a/app/models/hooks/active_hook_filter.rb +++ b/app/models/hooks/active_hook_filter.rb @@ -3,7 +3,7 @@ class ActiveHookFilter def initialize(hook) @hook = hook - @push_events_filter_matcher = RefMatcher.new(@hook.push_events_branch_filter) + @push_events_filter_matcher = Gitlab::RefMatcher.new(@hook.push_events_branch_filter) end def matches?(hooks_scope, data) diff --git a/app/models/ref_matcher.rb b/app/models/ref_matcher.rb deleted file mode 100644 index f370b9f20ca..00000000000 --- a/app/models/ref_matcher.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: true - -class RefMatcher - CONVERT_PATTERNS = { - '*' => '.*', - '[' => '[', - ']' => ']', - '^' => '^', - '-' => '-', - }.freeze - - def initialize(ref_name_or_pattern) - @ref_name_or_pattern = ref_name_or_pattern - end - - # Returns all branches/tags (among the given list of refs [`Gitlab::Git::Branch`]) - # that match the current protected ref. - def matching(refs) - refs.select { |ref| matches?(ref.name) } - end - - # Checks if the protected ref matches the given ref name. - def matches?(ref_name) - return false if @ref_name_or_pattern.blank? - - exact_match?(ref_name) || wildcard_match?(ref_name) - end - - # Checks if this protected ref contains a wildcard - def wildcard? - @ref_name_or_pattern && PATTERNS.any? do |key, _| - @ref_name_or_pattern.include?(key) - end - end - - protected - - def exact_match?(ref_name) - @ref_name_or_pattern == ref_name - end - - def wildcard_match?(ref_name) - return false unless wildcard? - - puts wildcard_regex - wildcard_regex === ref_name - end - - def wildcard_regex - @wildcard_regex ||= begin - quoted_name = Regexp.quote(@ref_name_or_pattern) - regex_string = unescape_patterns(quoted_name) - /\A#{regex_string}\z/ - end - end - - def unescape_patterns(text) - CONVERT_PATTERNS.each do |key, value| - text = text.gsub(Regexp.quote(key), value) - end - text - end -end diff --git a/lib/gitlab/ref_matcher.rb b/lib/gitlab/ref_matcher.rb new file mode 100644 index 00000000000..581d59f0b89 --- /dev/null +++ b/lib/gitlab/ref_matcher.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +module Gitlab + class RefMatcher + PATTERNS = { + '*' => '.*', + '[' => '[', + ']' => ']', + '^' => '^', + '-' => '-', + }.freeze + + def initialize(ref_name_or_pattern) + @ref_name_or_pattern = ref_name_or_pattern + end + + # Returns all branches/tags (among the given list of refs [`Gitlab::Git::Branch`]) + # that match the current protected ref. + def matching(refs) + refs.select { |ref| matches?(ref.name) } + end + + # Checks if the protected ref matches the given ref name. + def matches?(ref_name) + return false if @ref_name_or_pattern.blank? + + exact_match?(ref_name) || wildcard_match?(ref_name) + end + + # Checks if this protected ref contains a wildcard + def wildcard? + @ref_name_or_pattern && PATTERNS.any? do |key, _| + @ref_name_or_pattern.include?(key) + end + end + + protected + + def exact_match?(ref_name) + @ref_name_or_pattern == ref_name + end + + def wildcard_match?(ref_name) + return false unless wildcard? + + puts wildcard_regex + wildcard_regex === ref_name + end + + def wildcard_regex + @wildcard_regex ||= begin + quoted_name = Regexp.quote(@ref_name_or_pattern) + regex_string = unescape_patterns(quoted_name) + /\A#{regex_string}\z/ + end + end + + def unescape_patterns(text) + PATTERNS.each do |key, value| + text = text.gsub(Regexp.quote(key), value) + end + text + end + end +end diff --git a/spec/lib/gitlab/ref_matcher_spec.rb b/spec/lib/gitlab/ref_matcher_spec.rb new file mode 100644 index 00000000000..f1e14698979 --- /dev/null +++ b/spec/lib/gitlab/ref_matcher_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' +require 'rspec-parameterized' + +describe Gitlab::RefMatcher do + describe '#matches?' do + using RSpec::Parameterized::TableSyntax + + where(:pattern, :ref, :result) do + 'v*' | 'v1.1.1' | true + 'v*[e]' | 'v1.1.1-ee' | true + 'v[0-9].*' | 'v1.1.1' | true + 'v[2-9].*' | 'v1.1.1' | false + 'v*-ee' | 'v1.1.1-ee' | true + 'v*[^e]' | 'v1.1.1-ee' | false + 'v*[^-][^e][^e]' | 'v1.1.1-ee' | false + end + + with_them do + subject { described_class.new(pattern).matches?(ref) } + + it { is_expected.to eq(result) } + end + end +end |