diff options
Diffstat (limited to 'lib/gitlab/search/query.rb')
-rw-r--r-- | lib/gitlab/search/query.rb | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/lib/gitlab/search/query.rb b/lib/gitlab/search/query.rb index 5b1f9400bc7..c0420126ada 100644 --- a/lib/gitlab/search/query.rb +++ b/lib/gitlab/search/query.rb @@ -5,6 +5,9 @@ module Gitlab class Query < SimpleDelegator include EncodingHelper + QUOTES_REGEXP = %r{\A"|"\Z}.freeze + TOKEN_WITH_QUOTES_REGEXP = %r{\s(?=(?:[^"]|"[^"]*")*$)}.freeze + def initialize(query, filter_opts = {}, &block) @raw_query = query.dup @filters = [] @@ -35,22 +38,24 @@ module Gitlab def extract_filters fragments = [] + query_tokens = parse_raw_query filters = @filters.each_with_object([]) do |filter, parsed_filters| - match = @raw_query.split.find { |part| part =~ /\A-?#{filter[:name]}:/ } + match = query_tokens.find { |part| part =~ /\A-?#{filter[:name]}:/ } + next unless match input = match.split(':')[1..-1].join next if input.empty? filter[:negated] = match.start_with?("-") - filter[:value] = parse_filter(filter, input) + filter[:value] = parse_filter(filter, input.gsub(QUOTES_REGEXP, '')) filter[:regex_value] = Regexp.escape(filter[:value]).gsub('\*', '.*?') fragments << match parsed_filters << filter end - query = (@raw_query.split - fragments).join(' ') + query = (query_tokens - fragments).join(' ') query = '*' if query.empty? [query, filters] @@ -61,6 +66,13 @@ module Gitlab @filter_options[:encode_binary] ? encode_binary(result) : result end + + def parse_raw_query + # Positive lookahead for any non-quote char or even number of quotes + # for example '"search term" path:"foo bar.txt"' would break into + # ["search term", "path:\"foo bar.txt\""] + @raw_query.split(TOKEN_WITH_QUOTES_REGEXP).reject(&:empty?) + end end end end |