diff --git a/lib/gitlab/file_finder.rb b/lib/gitlab/file_finder.rb new file mode 100644 index 00000000000..093d9ed8092 --- /dev/null +++ b/lib/gitlab/file_finder.rb @@ -0,0 +1,32 @@ +# This class finds files in a repository by name and content +# the result is joined and sorted by file name +module Gitlab + class FileFinder + BATCH_SIZE = 100 + + attr_reader :project, :ref + + def initialize(project, ref) + @project = project + @ref = ref + end + + def find(query) + blobs = project.repository.search_files_by_content(query, ref).first(BATCH_SIZE) + found_file_names = Set.new + + results = blobs.map do |blob| + blob = Gitlab::ProjectSearchResults.parse_search_result(blob) + found_file_names << blob.filename + + [blob.filename, blob] + end + + project.repository.search_files_by_name(query, ref).first(BATCH_SIZE).each do |filename| + results << [filename, OpenStruct.new(ref: ref)] unless found_file_names.include?(filename) + end + + results.sort_by(&:first) + end + end +end diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb index 47cfe412715..561aa9e162c 100644 --- a/lib/gitlab/project_search_results.rb +++ b/lib/gitlab/project_search_results.rb @@ -84,23 +84,7 @@ module Gitlab def blobs return [] unless Ability.allowed?(@current_user, :download_code, @project) - @blobs ||= begin - blobs = project.repository.search_files_by_content(query, repository_ref).first(100) - found_file_names = Set.new - - results = blobs.map do |blob| - blob = self.class.parse_search_result(blob) - found_file_names << blob.filename - - [blob.filename, blob] - end - - project.repository.search_files_by_name(query, repository_ref).first(100).each do |filename| - results << [filename, nil] unless found_file_names.include?(filename) - end - - results.sort_by(&:first) - end + @blobs ||= Gitlab::FileFinder.new(project, repository_ref).find(query) end def wiki_blobs diff --git a/spec/lib/gitlab/file_finder_spec.rb b/spec/lib/gitlab/file_finder_spec.rb new file mode 100644 index 00000000000..5a32ffd462c --- /dev/null +++ b/spec/lib/gitlab/file_finder_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe Gitlab::FileFinder, lib: true do + describe '#find' do + let(:project) { create(:project, :public, :repository) } + let(:finder) { described_class.new(project, project.default_branch) } + + it 'finds by name' do + results = finder.find('files') + expect(results.map(&:first)).to include('files/images/wm.svg') + end + + it 'finds by content' do + results = finder.find('files') + + blob = results.select { |result| result.first == "CHANGELOG" }.flatten.last + + expect(blob.filename).to eq("CHANGELOG") + end + end +end diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb index 6e0b1192706..1b8690ba613 100644 --- a/spec/lib/gitlab/project_search_results_spec.rb +++ b/spec/lib/gitlab/project_search_results_spec.rb @@ -55,7 +55,7 @@ describe Gitlab::ProjectSearchResults, lib: true do end it 'finds by name' do - expect(results).to include(["files/images/wm.svg", nil]) + expect(results.map(&:first)).to include('files/images/wm.svg') end it 'finds by content' do