Commit 7f57fe5034f6fdfbdd4e29745b50e7bfa1576bf5
Committed by
Dmitriy Zaporozhets
1 parent
4353babe
Exists in
master
and in
4 other branches
Implemented code search feature
Showing
11 changed files
with
98 additions
and
7 deletions
Show diff stats
.travis.yml
Gemfile
@@ -23,7 +23,7 @@ gem 'omniauth-github' | @@ -23,7 +23,7 @@ gem 'omniauth-github' | ||
23 | 23 | ||
24 | # Extracting information from a git repository | 24 | # Extracting information from a git repository |
25 | # We cannot use original git since some bugs | 25 | # We cannot use original git since some bugs |
26 | -gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: '42297cdcee16284d2e4eff23d41377f52fc28b9d' | 26 | +gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git' |
27 | gem 'gitlab_git', '~> 1.0.6' | 27 | gem 'gitlab_git', '~> 1.0.6' |
28 | 28 | ||
29 | # Ruby/Rack Git Smart-HTTP Server Handler | 29 | # Ruby/Rack Git Smart-HTTP Server Handler |
Gemfile.lock
@@ -8,8 +8,7 @@ GIT | @@ -8,8 +8,7 @@ GIT | ||
8 | 8 | ||
9 | GIT | 9 | GIT |
10 | remote: https://github.com/gitlabhq/grit.git | 10 | remote: https://github.com/gitlabhq/grit.git |
11 | - revision: 42297cdcee16284d2e4eff23d41377f52fc28b9d | ||
12 | - ref: 42297cdcee16284d2e4eff23d41377f52fc28b9d | 11 | + revision: e873bb84ac3c4f8249311490d6a7c6ac9127625f |
13 | specs: | 12 | specs: |
14 | grit (2.5.0) | 13 | grit (2.5.0) |
15 | diff-lcs (~> 1.1) | 14 | diff-lcs (~> 1.1) |
app/contexts/search_context.rb
@@ -10,7 +10,11 @@ class SearchContext | @@ -10,7 +10,11 @@ class SearchContext | ||
10 | 10 | ||
11 | return result unless query.present? | 11 | return result unless query.present? |
12 | 12 | ||
13 | - result[:projects] = Project.where(id: project_ids).search(query).limit(10) | 13 | + projects = Project.where(id: project_ids) |
14 | + result[:projects] = projects.search(query).limit(10) | ||
15 | + if projects.length == 1 | ||
16 | + result[:snippets] = projects.first.files(query, params[:branch_ref]) | ||
17 | + end | ||
14 | result[:merge_requests] = MergeRequest.where(project_id: project_ids).search(query).limit(10) | 18 | result[:merge_requests] = MergeRequest.where(project_id: project_ids).search(query).limit(10) |
15 | result[:issues] = Issue.where(project_id: project_ids).search(query).limit(10) | 19 | result[:issues] = Issue.where(project_id: project_ids).search(query).limit(10) |
16 | result[:wiki_pages] = [] | 20 | result[:wiki_pages] = [] |
@@ -22,7 +26,8 @@ class SearchContext | @@ -22,7 +26,8 @@ class SearchContext | ||
22 | projects: [], | 26 | projects: [], |
23 | merge_requests: [], | 27 | merge_requests: [], |
24 | issues: [], | 28 | issues: [], |
25 | - wiki_pages: [] | 29 | + wiki_pages: [], |
30 | + snippets: [] | ||
26 | } | 31 | } |
27 | end | 32 | end |
28 | end | 33 | end |
app/controllers/search_controller.rb
@@ -18,5 +18,6 @@ class SearchController < ApplicationController | @@ -18,5 +18,6 @@ class SearchController < ApplicationController | ||
18 | @merge_requests = result[:merge_requests] | 18 | @merge_requests = result[:merge_requests] |
19 | @issues = result[:issues] | 19 | @issues = result[:issues] |
20 | @wiki_pages = result[:wiki_pages] | 20 | @wiki_pages = result[:wiki_pages] |
21 | + @snippets = result[:snippets] | ||
21 | end | 22 | end |
22 | end | 23 | end |
app/models/project.rb
@@ -411,4 +411,15 @@ class Project < ActiveRecord::Base | @@ -411,4 +411,15 @@ class Project < ActiveRecord::Base | ||
411 | !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) | 411 | !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) |
412 | end | 412 | end |
413 | 413 | ||
414 | + def files(query, treeish) | ||
415 | + snippets = [] | ||
416 | + tree = treeish.present? ? treeish : default_branch | ||
417 | + if repository && !tree.nil? | ||
418 | + greps = repository.repo.grep(query, 3, tree) | ||
419 | + greps.each do |g| | ||
420 | + snippets << Gitlab::BlobSnippet.new(self, tree, g.content, g.startline, g.filename) | ||
421 | + end | ||
422 | + end | ||
423 | + snippets | ||
424 | + end | ||
414 | end | 425 | end |
app/views/layouts/_search.html.haml
@@ -3,4 +3,13 @@ | @@ -3,4 +3,13 @@ | ||
3 | = text_field_tag "search", nil, placeholder: "Search", class: "search-input" | 3 | = text_field_tag "search", nil, placeholder: "Search", class: "search-input" |
4 | = hidden_field_tag :group_id, @group.try(:id) | 4 | = hidden_field_tag :group_id, @group.try(:id) |
5 | = hidden_field_tag :project_id, @project.try(:id) | 5 | = hidden_field_tag :project_id, @project.try(:id) |
6 | - .search-autocomplete-json.hide{:'data-autocomplete-opts' => search_autocomplete_source } | 6 | + - if @ref |
7 | + - @branch_ref = @ref | ||
8 | + - else | ||
9 | + - @branch_ref = @project.try(:default_branch) | ||
10 | + - if @branch_ref.blank? | ||
11 | + - @branch_ref = 'master' | ||
12 | + = hidden_field_tag :branch_ref, @branch_ref | ||
13 | + - if ENV['RAILS_ENV'] == 'test' | ||
14 | + = submit_tag 'Go' | ||
15 | + .search-autocomplete-json.hide{:'data-autocomplete-opts' => search_autocomplete_source } | ||
7 | \ No newline at end of file | 16 | \ No newline at end of file |
app/views/search/_result.html.haml
@@ -32,6 +32,15 @@ | @@ -32,6 +32,15 @@ | ||
32 | %strong.term | 32 | %strong.term |
33 | = truncate wiki_page.title, length: 50 | 33 | = truncate wiki_page.title, length: 50 |
34 | %span.light (#{wiki_page.project.name_with_namespace}) | 34 | %span.light (#{wiki_page.project.name_with_namespace}) |
35 | + - @snippets.each do |snippet| | ||
36 | + %li | ||
37 | + code: | ||
38 | + = link_to project_blob_path(snippet.project, tree_join(snippet.tree, snippet.filename), :anchor => "L" + snippet.startline.to_s) do | ||
39 | + %strong.term | ||
40 | + = snippet.filename | ||
41 | + .file_content.code | ||
42 | + %div{class: user_color_scheme_class} | ||
43 | + = raw snippet.colorize( formatter: :gitlab, options: { first_line_number: snippet.startline } ) | ||
35 | 44 | ||
36 | :javascript | 45 | :javascript |
37 | $(function() { | 46 | $(function() { |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +Feature: Project Search code | ||
2 | + Background: | ||
3 | + Given I sign in as a user | ||
4 | + And I own project "Shop" | ||
5 | + Given I visit project source page | ||
6 | + | ||
7 | + Scenario: Search for term "Welcome to Gitlab" | ||
8 | + When I search for term "Welcome to Gitlab" | ||
9 | + Then I should see files from repository containing "Welcome to Gitlab" |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +class ProjectSearchCode < Spinach::FeatureSteps | ||
2 | + include SharedAuthentication | ||
3 | + include SharedProject | ||
4 | + include SharedPaths | ||
5 | + | ||
6 | + When 'I search for term "Welcome to Gitlab"' do | ||
7 | + fill_in "search", with: "Welcome to Gitlab" | ||
8 | + click_button "Go" | ||
9 | + end | ||
10 | + | ||
11 | + Then 'I should see files from repository containing "Welcome to Gitlab"' do | ||
12 | + page.should have_content "Welcome to Gitlab" | ||
13 | + page.should have_content "GitLab is a free project and repository management application" | ||
14 | + end | ||
15 | + | ||
16 | +end |
@@ -0,0 +1,32 @@ | @@ -0,0 +1,32 @@ | ||
1 | +module Gitlab | ||
2 | + class BlobSnippet | ||
3 | + include Linguist::BlobHelper | ||
4 | + | ||
5 | + attr_accessor :project | ||
6 | + attr_accessor :tree | ||
7 | + attr_accessor :lines | ||
8 | + attr_accessor :filename | ||
9 | + attr_accessor :startline | ||
10 | + | ||
11 | + def initialize(project, tree, lines, startline, filename) | ||
12 | + @project, @tree, @lines, @startline, @filename = project, tree, lines, startline, filename | ||
13 | + end | ||
14 | + | ||
15 | + def data | ||
16 | + lines.join("\n") | ||
17 | + end | ||
18 | + | ||
19 | + def name | ||
20 | + filename | ||
21 | + end | ||
22 | + | ||
23 | + def size | ||
24 | + data.length | ||
25 | + end | ||
26 | + | ||
27 | + def mode | ||
28 | + nil | ||
29 | + end | ||
30 | + | ||
31 | + end | ||
32 | +end | ||
0 | \ No newline at end of file | 33 | \ No newline at end of file |