Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/search_controller.rb3
-rw-r--r--app/helpers/application_helper.rb2
-rw-r--r--app/views/search/_filter.html.haml61
-rw-r--r--app/views/search/_results.html.haml4
-rw-r--r--app/views/search/show.html.haml5
-rw-r--r--features/snippet_search.feature20
-rw-r--r--features/steps/shared/search.rb11
-rw-r--r--features/steps/shared/snippet.rb8
-rw-r--r--features/steps/snippet_search.rb56
-rw-r--r--lib/gitlab/snippet_search_results.rb45
10 files changed, 171 insertions, 44 deletions
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index dab38858bf9..58ec8e75d7a 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -5,6 +5,7 @@ class SearchController < ApplicationController
@project = Project.find_by(id: params[:project_id]) if params[:project_id].present?
@group = Group.find_by(id: params[:group_id]) if params[:group_id].present?
@scope = params[:scope]
+ @show_snippets = params[:snippets].eql? 'true'
@search_results = if @project
return access_denied! unless can?(current_user, :download_code, @project)
@@ -14,7 +15,7 @@ class SearchController < ApplicationController
end
Search::ProjectService.new(@project, current_user, params).execute
- elsif params[:snippets].eql? 'true'
+ elsif @show_snippets
unless %w(snippet_blobs snippet_titles).include?(@scope)
@scope = 'snippet_blobs'
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index db2d7214077..c2c9301cc17 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -178,7 +178,7 @@ module ApplicationHelper
def search_placeholder
if @project && @project.persisted?
"Search in this project"
- elsif @snippet || @snippets || (params && params[:snippets] == 'true')
+ elsif @snippet || @snippets || @show_snippets
'Search snippets'
elsif @group && @group.persisted?
"Search in this group"
diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml
index 2f71541a472..049aff0bc9b 100644
--- a/app/views/search/_filter.html.haml
+++ b/app/views/search/_filter.html.haml
@@ -1,36 +1,35 @@
-- unless params[:snippets]
- .dropdown.inline
- %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
- %i.icon-tags
- %span.light Group:
- - if @group.present?
- %strong= @group.name
- - else
+.dropdown.inline
+ %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
+ %i.icon-tags
+ %span.light Group:
+ - if @group.present?
+ %strong= @group.name
+ - else
+ Any
+ %b.caret
+ %ul.dropdown-menu
+ %li
+ = link_to search_filter_path(group_id: nil) do
Any
- %b.caret
- %ul.dropdown-menu
+ - current_user.authorized_groups.sort_by(&:name).each do |group|
%li
- = link_to search_filter_path(group_id: nil) do
- Any
- - current_user.authorized_groups.sort_by(&:name).each do |group|
- %li
- = link_to search_filter_path(group_id: group.id, project_id: nil) do
- = group.name
+ = link_to search_filter_path(group_id: group.id, project_id: nil) do
+ = group.name
- .dropdown.inline.prepend-left-10.project-filter
- %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
- %i.icon-tags
- %span.light Project:
- - if @project.present?
- %strong= @project.name_with_namespace
- - else
+.dropdown.inline.prepend-left-10.project-filter
+ %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
+ %i.icon-tags
+ %span.light Project:
+ - if @project.present?
+ %strong= @project.name_with_namespace
+ - else
+ Any
+ %b.caret
+ %ul.dropdown-menu
+ %li
+ = link_to search_filter_path(project_id: nil) do
Any
- %b.caret
- %ul.dropdown-menu
+ - current_user.authorized_projects.sort_by(&:name_with_namespace).each do |project|
%li
- = link_to search_filter_path(project_id: nil) do
- Any
- - current_user.authorized_projects.sort_by(&:name_with_namespace).each do |project|
- %li
- = link_to search_filter_path(project_id: project.id, group_id: nil) do
- = project.name_with_namespace
+ = link_to search_filter_path(project_id: project.id, group_id: nil) do
+ = project.name_with_namespace
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index 83fd5ca10e5..58bcff9dbe3 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -1,6 +1,6 @@
%h4
#{@search_results.total_count} results found
- - unless params[:snippets].eql? 'true'
+ - unless @show_snippets
- if @project
for #{link_to @project.name_with_namespace, @project}
- elsif @group
@@ -12,7 +12,7 @@
.col-sm-3
- if @project
= render "project_filter"
- - elsif params[:snippets].eql? 'true'
+ - elsif @show_snippets
= render 'snippet_filter'
- else
= render "global_filter"
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index 9deec490953..bae57917a4c 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -9,8 +9,9 @@
= submit_tag 'Search', class: "btn btn-create"
.form-group
.col-sm-2
- .col-sm-10
- = render 'filter', f: f
+ - unless params[:snippets].eql? 'true'
+ .col-sm-10
+ = render 'filter', f: f
= hidden_field_tag :project_id, params[:project_id]
= hidden_field_tag :group_id, params[:group_id]
= hidden_field_tag :snippets, params[:snippets]
diff --git a/features/snippet_search.feature b/features/snippet_search.feature
new file mode 100644
index 00000000000..834bd3b2376
--- /dev/null
+++ b/features/snippet_search.feature
@@ -0,0 +1,20 @@
+@dashboard
+Feature: Snippet Search
+ Background:
+ Given I sign in as a user
+ And I have public "Personal snippet one" snippet
+ And I have private "Personal snippet private" snippet
+ And I have a public many lined snippet
+
+ Scenario: I should see my public and private snippets
+ When I search for "snippet" in snippet titles
+ Then I should see "Personal snippet one" in results
+ And I should see "Personal snippet private" in results
+
+ Scenario: I should see three surrounding lines on either side of a matching snippet line
+ When I search for "line seven" in snippet contents
+ Then I should see "line four" in results
+ And I should see "line seven" in results
+ And I should see "line ten" in results
+ And I should not see "line three" in results
+ And I should not see "line eleven" in results
diff --git a/features/steps/shared/search.rb b/features/steps/shared/search.rb
new file mode 100644
index 00000000000..6c3d601763d
--- /dev/null
+++ b/features/steps/shared/search.rb
@@ -0,0 +1,11 @@
+module SharedSearch
+ include Spinach::DSL
+
+ def search_snippet_contents(query)
+ visit "/search?search=#{URI::encode(query)}&snippets=true&scope=snippet_blobs"
+ end
+
+ def search_snippet_titles(query)
+ visit "/search?search=#{URI::encode(query)}&snippets=true&scope=snippet_titles"
+ end
+end
diff --git a/features/steps/shared/snippet.rb b/features/steps/shared/snippet.rb
index 543e43196a5..5f89a3ccf65 100644
--- a/features/steps/shared/snippet.rb
+++ b/features/steps/shared/snippet.rb
@@ -18,4 +18,12 @@ module SharedSnippet
private: true,
author: current_user)
end
+ And 'I have a public many lined snippet' do
+ create(:personal_snippet,
+ title: "Many lined snippet",
+ content: "line one\nline two\nline three\nline four\nline five\nline six\nline seven\nline eight\nline nine\nline ten\nline eleven\nline twelve\nline thirteen\nline fourteen",
+ file_name: "many_lined_snippet.rb",
+ private: true,
+ author: current_user)
+ end
end
diff --git a/features/steps/snippet_search.rb b/features/steps/snippet_search.rb
new file mode 100644
index 00000000000..eb7d56c5f3f
--- /dev/null
+++ b/features/steps/snippet_search.rb
@@ -0,0 +1,56 @@
+class Spinach::Features::SnippetSearch < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedPaths
+ include SharedSnippet
+ include SharedUser
+ include SharedSearch
+
+ step 'I search for "snippet" in snippet titles' do
+ search_snippet_titles "snippet"
+ end
+
+ step 'I search for "snippet private" in snippet titles' do
+ search_snippet_titles "snippet private"
+ end
+
+ step 'I search for "line seven" in snippet contents' do
+ search_snippet_contents "line seven"
+ end
+
+ step 'I should see "line seven" in results' do
+ page.should have_content "line seven"
+ end
+
+ step 'I should see "line four" in results' do
+ page.should have_content "line four"
+ end
+
+ step 'I should see "line ten" in results' do
+ page.should have_content "line ten"
+ end
+
+ step 'I should not see "line eleven" in results' do
+ page.should_not have_content "line eleven"
+ end
+
+ step 'I should not see "line three" in results' do
+ page.should_not have_content "line three"
+ end
+
+ Then 'I should see "Personal snippet one" in results' do
+ page.should have_content "Personal snippet one"
+ end
+
+ And 'I should see "Personal snippet private" in results' do
+ page.should have_content "Personal snippet private"
+ end
+
+ Then 'I should not see "Personal snippet one" in results' do
+ page.should_not have_content "Personal snippet one"
+ end
+
+ And 'I should not see "Personal snippet private" in results' do
+ page.should_not have_content "Personal snippet private"
+ end
+
+end
diff --git a/lib/gitlab/snippet_search_results.rb b/lib/gitlab/snippet_search_results.rb
index 04217aab49f..938219efdb2 100644
--- a/lib/gitlab/snippet_search_results.rb
+++ b/lib/gitlab/snippet_search_results.rb
@@ -48,53 +48,84 @@ module Gitlab
'snippet_blobs'
end
- def bounded_line_numbers(line, min, max, surrounding_lines)
+ # Get an array of line numbers surrounding a matching
+ # line, bounded by min/max.
+ #
+ # @returns Array of line numbers
+ def bounded_line_numbers(line, min, max)
lower = line - surrounding_lines > min ? line - surrounding_lines : min
upper = line + surrounding_lines < max ? line + surrounding_lines : max
(lower..upper).to_a
end
- def chunk_snippet(snippet)
- surrounding_lines = 3
+ # Returns a sorted set of lines to be included in a snippet preview.
+ # This ensures matching adjacent lines do not display duplicated
+ # surrounding code.
+ #
+ # @returns Array, unique and sorted.
+ def matching_lines(lined_content)
used_lines = []
- lined_content = snippet.content.split("\n")
lined_content.each_with_index do |line, line_number|
used_lines.concat bounded_line_numbers(
line_number,
0,
- lined_content.size,
- surrounding_lines
+ lined_content.size
) if line.include?(query)
end
- used_lines = used_lines.uniq.sort
+ used_lines.uniq.sort
+ end
+
+ # 'Chunkify' entire snippet. Splits the snippet data into matching lines +
+ # surrounding_lines() worth of unmatching lines.
+ #
+ # @returns a hash with {snippet_object, snippet_chunks:{data,start_line}}
+ def chunk_snippet(snippet)
+ lined_content = snippet.content.split("\n")
+ used_lines = matching_lines(lined_content)
snippet_chunk = []
snippet_chunks = []
snippet_start_line = 0
last_line = -1
+
+ # Go through each used line, and add consecutive lines as a single chunk
+ # to the snippet chunk array.
used_lines.each do |line_number|
if last_line < 0
+ # Start a new chunk.
snippet_start_line = line_number
snippet_chunk << lined_content[line_number]
elsif last_line == line_number - 1
+ # Consecutive line, continue chunk.
snippet_chunk << lined_content[line_number]
else
+ # Non-consecutive line, add chunk to chunk array.
snippet_chunks << {
data: snippet_chunk.join("\n"),
start_line: snippet_start_line + 1
}
+
+ # Start a new chunk.
snippet_chunk = [lined_content[line_number]]
snippet_start_line = line_number
end
last_line = line_number
end
+ # Add final chunk to chunk array
snippet_chunks << {
data: snippet_chunk.join("\n"),
start_line: snippet_start_line + 1
}
+ # Return snippet with chunk array
{ snippet_object: snippet, snippet_chunks: snippet_chunks }
end
+
+ # Defines how many unmatching lines should be
+ # included around the matching lines in a snippet
+ def surrounding_lines
+ 3
+ end
end
end