Commit 7f57fe5034f6fdfbdd4e29745b50e7bfa1576bf5

Authored by Javier Castro
Committed by Dmitriy Zaporozhets
1 parent 4353babe

Implemented code search feature

@@ -6,7 +6,7 @@ before_install: @@ -6,7 +6,7 @@ before_install:
6 - gem install charlock_holmes -v="0.6.9" 6 - gem install charlock_holmes -v="0.6.9"
7 branches: 7 branches:
8 only: 8 only:
9 - - 'master' 9 + - 'code-search'
10 rvm: 10 rvm:
11 - 1.9.3-p392 11 - 1.9.3-p392
12 - 2.0.0 12 - 2.0.0
@@ -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
@@ -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() {
features/project/source/search_code.feature 0 → 100644
@@ -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"
features/steps/project/project_search_code.rb 0 → 100644
@@ -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
lib/gitlab/blob_snippet.rb 0 → 100644
@@ -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