Commit 7f57fe5034f6fdfbdd4e29745b50e7bfa1576bf5

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

Implemented code search feature

.travis.yml
... ... @@ -6,7 +6,7 @@ before_install:
6 6 - gem install charlock_holmes -v="0.6.9"
7 7 branches:
8 8 only:
9   - - 'master'
  9 + - 'code-search'
10 10 rvm:
11 11 - 1.9.3-p392
12 12 - 2.0.0
... ...
Gemfile
... ... @@ -23,7 +23,7 @@ gem 'omniauth-github'
23 23  
24 24 # Extracting information from a git repository
25 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 27 gem 'gitlab_git', '~> 1.0.6'
28 28  
29 29 # Ruby/Rack Git Smart-HTTP Server Handler
... ...
Gemfile.lock
... ... @@ -8,8 +8,7 @@ GIT
8 8  
9 9 GIT
10 10 remote: https://github.com/gitlabhq/grit.git
11   - revision: 42297cdcee16284d2e4eff23d41377f52fc28b9d
12   - ref: 42297cdcee16284d2e4eff23d41377f52fc28b9d
  11 + revision: e873bb84ac3c4f8249311490d6a7c6ac9127625f
13 12 specs:
14 13 grit (2.5.0)
15 14 diff-lcs (~> 1.1)
... ...
app/contexts/search_context.rb
... ... @@ -10,7 +10,11 @@ class SearchContext
10 10  
11 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 18 result[:merge_requests] = MergeRequest.where(project_id: project_ids).search(query).limit(10)
15 19 result[:issues] = Issue.where(project_id: project_ids).search(query).limit(10)
16 20 result[:wiki_pages] = []
... ... @@ -22,7 +26,8 @@ class SearchContext
22 26 projects: [],
23 27 merge_requests: [],
24 28 issues: [],
25   - wiki_pages: []
  29 + wiki_pages: [],
  30 + snippets: []
26 31 }
27 32 end
28 33 end
... ...
app/controllers/search_controller.rb
... ... @@ -18,5 +18,6 @@ class SearchController < ApplicationController
18 18 @merge_requests = result[:merge_requests]
19 19 @issues = result[:issues]
20 20 @wiki_pages = result[:wiki_pages]
  21 + @snippets = result[:snippets]
21 22 end
22 23 end
... ...
app/models/project.rb
... ... @@ -411,4 +411,15 @@ class Project < ActiveRecord::Base
411 411 !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
412 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 425 end
... ...
app/views/layouts/_search.html.haml
... ... @@ -3,4 +3,13 @@
3 3 = text_field_tag "search", nil, placeholder: "Search", class: "search-input"
4 4 = hidden_field_tag :group_id, @group.try(:id)
5 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 16 \ No newline at end of file
... ...
app/views/search/_result.html.haml
... ... @@ -32,6 +32,15 @@
32 32 %strong.term
33 33 = truncate wiki_page.title, length: 50
34 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 45 :javascript
37 46 $(function() {
... ...
features/project/source/search_code.feature 0 → 100644
... ... @@ -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 @@
  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 @@
  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 33 \ No newline at end of file
... ...