Commit ead838cc authored by Francisco Javier López's avatar Francisco Javier López Committed by Douwe Maan

Add ability to search wiki titles

parent 7bd2eee9
......@@ -33,16 +33,16 @@ module SearchHelper
"Showing #{from} - #{to} of #{count} #{scope.humanize(capitalize: false)} for \"#{term}\""
end
def find_project_for_result_blob(result)
@project
end
def parse_search_result(result)
if result.is_a?(String)
Gitlab::ProjectSearchResults.parse_search_result(result)
else
Gitlab::Elastic::SearchResults.parse_search_result(result)
end
result
end
def find_project_for_blob(blob)
Project.find(blob['_parent'])
def search_blob_title(project, filename)
filename
end
private
......
......@@ -154,10 +154,6 @@ class ProjectWiki
[title, title_array.join("/")]
end
def search_files(query)
repository.search_files_by_content(query, default_branch)
end
def repository
@repository ||= Repository.new(full_path, @project, disk_path: disk_path, is_wiki: true)
end
......
- project = @project || find_project_for_blob(blob)
- if blob.is_a?(Array)
- file_name, blob = blob
- else
- blob = parse_search_result(blob)
- file_name = blob.filename
- project = find_project_for_result_blob(blob)
- file_name, blob = parse_search_result(blob)
- blob_link = project_blob_path(project, tree_join(blob.ref, file_name))
.blob-result
.file-holder
.js-file-title.file-title
= link_to blob_link do
= icon('fa-file')
%strong
- if @project
= file_name
- else
#{project.full_name}:
%i= file_name
- if blob.data
.file-content.code.term
= render 'shared/file_highlight', blob: blob, first_line_number: blob.startline, blob_link: blob_link
= render partial: 'search/results/blob_data', locals: { blob: blob, project: project, file_name: file_name, blob_link: blob_link }
.blob-result
.file-holder
.js-file-title.file-title
= link_to blob_link do
%i.fa.fa-file
%strong
= search_blob_title(project, file_name)
- if blob.data
.file-content.code.term
= render 'shared/file_highlight', blob: blob, first_line_number: blob.startline
- project = @project || find_project_for_blob(wiki_blob)
- wiki_blob = parse_search_result(wiki_blob)
- project = find_project_for_result_blob(wiki_blob)
- file_name, wiki_blob = parse_search_result(wiki_blob)
- wiki_blob_link = project_wiki_path(project, wiki_blob.basename)
.blob-result
.file-holder
.js-file-title.file-title
= link_to project_wiki_path(project, wiki_blob.basename) do
%i.fa.fa-file
%strong
- if @project
= wiki_blob.basename
- else
#{project.full_name}:
%i= wiki_blob.basename
.file-content.code.term
= render 'shared/file_highlight', blob: wiki_blob, first_line_number: wiki_blob.startline
= render partial: 'search/results/blob_data', locals: { blob: wiki_blob, project: project, file_name: file_name, blob_link: wiki_blob_link }
---
title: Added ability to search by wiki titles
merge_request: 19112
author:
type: added
module EE
module SearchHelper
extend ::Gitlab::Utils::Override
def search_filter_input_options(type)
options = super
options[:data][:'multiple-assignees'] = 'true' if search_multiple_assignees?(type)
......@@ -7,6 +9,29 @@ module EE
options
end
override :find_project_for_result_blob
def find_project_for_result_blob(result)
super || ::Project.find(result['_parent'])
end
override :parse_search_result
def parse_search_result(result)
return super if result.is_a?(Array)
blob = ::Gitlab::Elastic::SearchResults.parse_search_result(result)
[blob.filename, blob]
end
override :search_blob_title
def search_blob_title(project, file_name)
if @project
file_name
else
(project.full_name + ': ' + content_tag(:i, file_name)).html_safe
end
end
private
def search_multiple_assignees?(type)
......
......@@ -25,7 +25,7 @@ describe SearchHelper do
options: { highlight: true }
)[:blobs][:results][0]
parsed_result = helper.parse_search_result(result)
_, parsed_result = helper.parse_search_result(result)
expect(parsed_result.ref). to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0')
expect(parsed_result.filename).to eq('files/ruby/popen.rb')
......
......@@ -42,9 +42,7 @@ module API
end
case params[:scope]
when 'wiki_blobs'
paginate(results).map { |blob| Gitlab::ProjectSearchResults.parse_search_result(blob, user_project) }
when 'blobs'
when 'blobs', 'wiki_blobs'
paginate(results).map { |blob| blob[1] }
else
paginate(results)
......
......@@ -32,17 +32,13 @@ module Gitlab
end
def find_by_filename(query, except: [])
filenames = repository.search_files_by_name(query, ref).first(BATCH_SIZE)
filenames.delete_if { |filename| except.include?(filename) } unless except.empty?
filenames = search_filenames(query, except)
blob_refs = filenames.map { |filename| [ref, filename] }
blobs = Gitlab::Git::Blob.batch(repository, blob_refs, blob_size_limit: 1024)
blobs.map do |blob|
blobs(filenames).map do |blob|
Gitlab::SearchResults::FoundBlob.new(
id: blob.id,
filename: blob.path,
basename: File.basename(blob.path),
basename: File.basename(blob.path, File.extname(blob.path)),
ref: ref,
startline: 1,
data: blob.data,
......@@ -50,5 +46,21 @@ module Gitlab
)
end
end
def search_filenames(query, except)
filenames = repository.search_files_by_name(query, ref).first(BATCH_SIZE)
filenames.delete_if { |filename| except.include?(filename) } unless except.empty?
filenames
end
def blob_refs(filenames)
filenames.map { |filename| [ref, filename] }
end
def blobs(filenames)
Gitlab::Git::Blob.batch(repository, blob_refs(filenames), blob_size_limit: 1024)
end
end
end
......@@ -106,7 +106,8 @@ module Gitlab
project_wiki = ProjectWiki.new(project)
unless project_wiki.empty?
project_wiki.search_files(query)
ref = repository_ref || project.wiki.default_branch
Gitlab::WikiFileFinder.new(project, ref).find(query)
else
[]
end
......
module Gitlab
class WikiFileFinder < FileFinder
attr_reader :repository
def initialize(project, ref)
@project = project
@ref = ref
@repository = project.wiki.repository
end
private
def search_filenames(query, except)
safe_query = Regexp.escape(query.tr(' ', '-'))
safe_query = Regexp.new(safe_query, Regexp::IGNORECASE)
filenames = repository.ls_files(ref)
filenames.delete_if { |filename| except.include?(filename) } unless except.empty?
filenames.grep(safe_query).first(BATCH_SIZE)
end
end
end
......@@ -3,27 +3,11 @@ require 'spec_helper'
describe Gitlab::FileFinder 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')
filename, blob = results.find { |_, blob| blob.filename == 'files/images/wm.svg' }
expect(filename).to eq('files/images/wm.svg')
expect(blob).to be_a(Gitlab::SearchResults::FoundBlob)
expect(blob.ref).to eq(finder.ref)
expect(blob.data).not_to be_empty
end
it 'finds by content' do
results = finder.find('files')
filename, blob = results.find { |_, blob| blob.filename == 'CHANGELOG' }
expect(filename).to eq('CHANGELOG')
expect(blob).to be_a(Gitlab::SearchResults::FoundBlob)
expect(blob.ref).to eq(finder.ref)
expect(blob.data).not_to be_empty
it_behaves_like 'file finder' do
subject { described_class.new(project, project.default_branch) }
let(:expected_file_by_name) { 'files/images/wm.svg' }
let(:expected_file_by_content) { 'CHANGELOG' }
end
end
end
......@@ -22,47 +22,57 @@ describe Gitlab::ProjectSearchResults do
it { expect(results.query).to eq('hello world') }
end
describe 'blob search' do
let(:project) { create(:project, :public, :repository) }
subject(:results) { described_class.new(user, project, 'files').objects('blobs') }
context 'when repository is disabled' do
let(:project) { create(:project, :public, :repository, :repository_disabled) }
shared_examples 'general blob search' do |entity_type, blob_kind|
let(:query) { 'files' }
subject(:results) { described_class.new(user, project, query).objects(blob_type) }
it 'hides blobs from members' do
context "when #{entity_type} is disabled" do
let(:project) { disabled_project }
it "hides #{blob_kind} from members" do
project.add_reporter(user)
is_expected.to be_empty
end
it 'hides blobs from non-members' do
it "hides #{blob_kind} from non-members" do
is_expected.to be_empty
end
end
context 'when repository is internal' do
let(:project) { create(:project, :public, :repository, :repository_private) }
context "when #{entity_type} is internal" do
let(:project) { private_project }
it 'finds blobs for members' do
it "finds #{blob_kind} for members" do
project.add_reporter(user)
is_expected.not_to be_empty
end
it 'hides blobs from non-members' do
it "hides #{blob_kind} from non-members" do
is_expected.to be_empty
end
end
it 'finds by name' do
expect(results.map(&:first)).to include('files/images/wm.svg')
expect(results.map(&:first)).to include(expected_file_by_name)
end
it 'finds by content' do
blob = results.select { |result| result.first == 'CHANGELOG' }.flatten.last
blob = results.select { |result| result.first == expected_file_by_content }.flatten.last
expect(blob.filename).to eq("CHANGELOG")
expect(blob.filename).to eq(expected_file_by_content)
end
end
describe 'blob search' do
let(:project) { create(:project, :public, :repository) }
it_behaves_like 'general blob search', 'repository', 'blobs' do
let(:blob_type) { 'blobs' }
let(:disabled_project) { create(:project, :public, :repository, :repository_disabled) }
let(:private_project) { create(:project, :public, :repository, :repository_private) }
let(:expected_file_by_name) { 'files/images/wm.svg' }
let(:expected_file_by_content) { 'CHANGELOG' }
end
describe 'parsing results' do
......@@ -189,40 +199,18 @@ describe Gitlab::ProjectSearchResults do
describe 'wiki search' do
let(:project) { create(:project, :public, :wiki_repo) }
let(:wiki) { build(:project_wiki, project: project) }
let!(:wiki_page) { wiki.create_page('Title', 'Content') }
subject(:results) { described_class.new(user, project, 'Content').objects('wiki_blobs') }
context 'when wiki is disabled' do
let(:project) { create(:project, :public, :wiki_repo, :wiki_disabled) }
it 'hides wiki blobs from members' do
project.add_reporter(user)
is_expected.to be_empty
end
it 'hides wiki blobs from non-members' do
is_expected.to be_empty
end
end
context 'when wiki is internal' do
let(:project) { create(:project, :public, :wiki_repo, :wiki_private) }
it 'finds wiki blobs for guest' do
project.add_guest(user)
is_expected.not_to be_empty
end
it 'hides wiki blobs from non-members' do
is_expected.to be_empty
end
before do
wiki.create_page('Files/Title', 'Content')
wiki.create_page('CHANGELOG', 'Files example')
end
it 'finds by content' do
expect(results).to include("master:Title.md\x001\x00Content\n")
it_behaves_like 'general blob search', 'wiki', 'wiki blobs' do
let(:blob_type) { 'wiki_blobs' }
let(:disabled_project) { create(:project, :public, :wiki_repo, :wiki_disabled) }
let(:private_project) { create(:project, :public, :wiki_repo, :wiki_private) }
let(:expected_file_by_name) { 'Files/Title.md' }
let(:expected_file_by_content) { 'CHANGELOG.md' }
end
end
......
require 'spec_helper'
describe Gitlab::WikiFileFinder do
describe '#find' do
let(:project) { create(:project, :public, :wiki_repo) }
let(:wiki) { build(:project_wiki, project: project) }
before do
wiki.create_page('Files/Title', 'Content')
wiki.create_page('CHANGELOG', 'Files example')
end
it_behaves_like 'file finder' do
subject { described_class.new(project, project.wiki.default_branch) }
let(:expected_file_by_name) { 'Files/Title.md' }
let(:expected_file_by_content) { 'CHANGELOG.md' }
end
end
end
shared_examples 'file finder' do
let(:query) { 'files' }
let(:search_results) { subject.find(query) }
it 'finds by name' do
filename, blob = search_results.find { |_, blob| blob.filename == expected_file_by_name }
expect(filename).to eq(expected_file_by_name)
expect(blob).to be_a(Gitlab::SearchResults::FoundBlob)
expect(blob.ref).to eq(subject.ref)
expect(blob.data).not_to be_empty
end
it 'finds by content' do
filename, blob = search_results.find { |_, blob| blob.filename == expected_file_by_content }
expect(filename).to eq(expected_file_by_content)
expect(blob).to be_a(Gitlab::SearchResults::FoundBlob)
expect(blob.ref).to eq(subject.ref)
expect(blob.data).not_to be_empty
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment