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

Add ability to search wiki titles

parent 0b4f9ff4
...@@ -25,14 +25,22 @@ module SearchHelper ...@@ -25,14 +25,22 @@ module SearchHelper
return unless collection.count > 0 return unless collection.count > 0
from = collection.offset_value + 1 from = collection.offset_value + 1
to = collection.offset_value + collection.length to = collection.offset_value + collection.count
count = collection.total_count count = collection.total_count
"Showing #{from} - #{to} of #{count} #{scope.humanize(capitalize: false)} for \"#{term}\"" "Showing #{from} - #{to} of #{count} #{scope.humanize(capitalize: false)} for \"#{term}\""
end end
def find_project_for_result_blob(result)
@project
end
def parse_search_result(result) def parse_search_result(result)
Gitlab::ProjectSearchResults.parse_search_result(result) result
end
def search_blob_title(project, filename)
filename
end end
private private
......
...@@ -140,10 +140,6 @@ class ProjectWiki ...@@ -140,10 +140,6 @@ class ProjectWiki
[title, title_array.join("/")] [title, title_array.join("/")]
end end
def search_files(query)
repository.search_files_by_content(query, default_branch)
end
def repository def repository
@repository ||= Repository.new(full_path, @project, disk_path: disk_path, is_wiki: true) @repository ||= Repository.new(full_path, @project, disk_path: disk_path, is_wiki: true)
end end
......
- file_name, blob = blob - project = find_project_for_result_blob(blob)
.blob-result - file_name, blob = parse_search_result(blob)
.file-holder - blob_link = project_blob_path(project, tree_join(blob.ref, file_name))
.js-file-title.file-title
- ref = @search_results.repository_ref = render partial: 'search/results/blob_data', locals: { blob: blob, project: project, file_name: file_name, blob_link: blob_link }
- blob_link = project_blob_path(@project, tree_join(ref, file_name))
= link_to blob_link do
%i.fa.fa-file
%strong
= file_name
- if blob
.file-content.code.term
= render 'shared/file_highlight', blob: blob, first_line_number: blob.startline, blob_link: blob_link
.blob-result
.file-holder
.js-file-title.file-title
= link_to blob_link do
%i.fa.fa-file
= search_blob_title(project, file_name)
- if blob.data
.file-content.code.term
= render 'shared/file_highlight', blob: blob, first_line_number: blob.startline
- wiki_blob = parse_search_result(wiki_blob) - project = find_project_for_result_blob(wiki_blob)
.blob-result - file_name, wiki_blob = parse_search_result(wiki_blob)
.file-holder - wiki_blob_link = project_wiki_path(project, wiki_blob.basename)
.js-file-title.file-title
= link_to project_wiki_path(@project, wiki_blob.basename) do = render partial: 'search/results/blob_data', locals: { blob: wiki_blob, project: project, file_name: file_name, blob_link: wiki_blob_link }
%i.fa.fa-file
%strong
= wiki_blob.basename
.file-content.code.term
= render 'shared/file_highlight', blob: wiki_blob, first_line_number: wiki_blob.startline
---
title: Added ability to search by wiki titles
merge_request: 19112
author:
type: added
...@@ -34,9 +34,7 @@ module API ...@@ -34,9 +34,7 @@ module API
def process_results(results) def process_results(results)
case params[:scope] case params[:scope]
when 'wiki_blobs' when 'blobs', 'wiki_blobs'
paginate(results).map { |blob| Gitlab::ProjectSearchResults.parse_search_result(blob, user_project) }
when 'blobs'
paginate(results).map { |blob| blob[1] } paginate(results).map { |blob| blob[1] }
else else
paginate(results) paginate(results)
......
...@@ -32,17 +32,13 @@ module Gitlab ...@@ -32,17 +32,13 @@ module Gitlab
end end
def find_by_filename(query, except: []) def find_by_filename(query, except: [])
filenames = repository.search_files_by_name(query, ref).first(BATCH_SIZE) filenames = search_filenames(query, except)
filenames.delete_if { |filename| except.include?(filename) } unless except.empty?
blob_refs = filenames.map { |filename| [ref, filename] } blobs(filenames).map do |blob|
blobs = Gitlab::Git::Blob.batch(repository, blob_refs, blob_size_limit: 1024)
blobs.map do |blob|
Gitlab::SearchResults::FoundBlob.new( Gitlab::SearchResults::FoundBlob.new(
id: blob.id, id: blob.id,
filename: blob.path, filename: blob.path,
basename: File.basename(blob.path), basename: File.basename(blob.path, File.extname(blob.path)),
ref: ref, ref: ref,
startline: 1, startline: 1,
data: blob.data, data: blob.data,
...@@ -50,5 +46,21 @@ module Gitlab ...@@ -50,5 +46,21 @@ module Gitlab
) )
end end
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
end end
...@@ -106,7 +106,8 @@ module Gitlab ...@@ -106,7 +106,8 @@ module Gitlab
project_wiki = ProjectWiki.new(project) project_wiki = ProjectWiki.new(project)
unless project_wiki.empty? unless project_wiki.empty?
project_wiki.search_files(query) ref = repository_ref || project.wiki.default_branch
Gitlab::WikiFileFinder.new(project, ref).find(query)
else else
[] []
end 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' ...@@ -3,27 +3,11 @@ require 'spec_helper'
describe Gitlab::FileFinder do describe Gitlab::FileFinder do
describe '#find' do describe '#find' do
let(:project) { create(:project, :public, :repository) } let(:project) { create(:project, :public, :repository) }
let(:finder) { described_class.new(project, project.default_branch) }
it 'finds by name' do it_behaves_like 'file finder' do
results = finder.find('files') subject { described_class.new(project, project.default_branch) }
let(:expected_file_by_name) { 'files/images/wm.svg' }
filename, blob = results.find { |_, blob| blob.filename == 'files/images/wm.svg' } let(:expected_file_by_content) { 'CHANGELOG' }
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
end end
end end
end end
...@@ -22,47 +22,57 @@ describe Gitlab::ProjectSearchResults do ...@@ -22,47 +22,57 @@ describe Gitlab::ProjectSearchResults do
it { expect(results.query).to eq('hello world') } it { expect(results.query).to eq('hello world') }
end end
describe 'blob search' do shared_examples 'general blob search' do |entity_type, blob_kind|
let(:project) { create(:project, :public, :repository) } let(:query) { 'files' }
subject(:results) { described_class.new(user, project, query).objects(blob_type) }
subject(:results) { described_class.new(user, project, 'files').objects('blobs') }
context 'when repository is disabled' do
let(:project) { create(:project, :public, :repository, :repository_disabled) }
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) project.add_reporter(user)
is_expected.to be_empty is_expected.to be_empty
end end
it 'hides blobs from non-members' do it "hides #{blob_kind} from non-members" do
is_expected.to be_empty is_expected.to be_empty
end end
end end
context 'when repository is internal' do context "when #{entity_type} is internal" do
let(:project) { create(:project, :public, :repository, :repository_private) } let(:project) { private_project }
it 'finds blobs for members' do it "finds #{blob_kind} for members" do
project.add_reporter(user) project.add_reporter(user)
is_expected.not_to be_empty is_expected.not_to be_empty
end end
it 'hides blobs from non-members' do it "hides #{blob_kind} from non-members" do
is_expected.to be_empty is_expected.to be_empty
end end
end end
it 'finds by name' do 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 end
it 'finds by content' do 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 end
describe 'parsing results' do describe 'parsing results' do
...@@ -189,40 +199,18 @@ describe Gitlab::ProjectSearchResults do ...@@ -189,40 +199,18 @@ describe Gitlab::ProjectSearchResults do
describe 'wiki search' do describe 'wiki search' do
let(:project) { create(:project, :public, :wiki_repo) } let(:project) { create(:project, :public, :wiki_repo) }
let(:wiki) { build(:project_wiki, project: project) } 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 before do
project.add_reporter(user) wiki.create_page('Files/Title', 'Content')
wiki.create_page('CHANGELOG', 'Files example')
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
end end
it 'finds by content' do it_behaves_like 'general blob search', 'wiki', 'wiki blobs' do
expect(results).to include("master:Title.md\x001\x00Content\n") 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
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