mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-15 07:36:41 +10:00
Optimize Banzai::Filter::RelativeLinkFilter
A lot of git operations were being repeated, for example, to build a url
you would ask if the path was a Tree, which would call a recursive routine
in Gitlab::Git::Tree#where, then ask if the path was a Blob, which would
call a recursive routine at Gitlab::Git::Blob#find, making reference to
the same git objects several times. Now we call Rugged::Tree#path, which
allows us to determine the type of the path in one pass.
Some other minor improvement added, like saving commonly used references
instead of calculating them each time.
This commit is contained in:
@@ -8,6 +8,7 @@ v 8.9.0 (unreleased)
|
||||
- Bulk assign/unassign labels to issues.
|
||||
- Ability to prioritize labels !4009 / !3205 (Thijs Wouters)
|
||||
- Show Star and Fork buttons on mobile.
|
||||
- Performance improvements on RelativeLinkFilter
|
||||
- Fix endless redirections when accessing user OAuth applications when they are disabled
|
||||
- Allow enabling wiki page events from Webhook management UI
|
||||
- Bump rouge to 1.11.0
|
||||
|
||||
@@ -271,6 +271,32 @@ class Commit
|
||||
merged_merge_request ? 'merge request' : 'commit'
|
||||
end
|
||||
|
||||
# Get the URI type of the given path
|
||||
#
|
||||
# Used to build URLs to files in the repository in GFM.
|
||||
#
|
||||
# path - String path to check
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# uri_type('doc/README.md') # => :blob
|
||||
# uri_type('doc/logo.png') # => :raw
|
||||
# uri_type('doc/api') # => :tree
|
||||
# uri_type('not/found') # => :nil
|
||||
#
|
||||
# Returns a symbol
|
||||
def uri_type(path)
|
||||
entry = @raw.tree.path(path)
|
||||
if entry[:type] == :blob
|
||||
blob = Gitlab::Git::Blob.new(name: entry[:name])
|
||||
blob.image? ? :raw : :blob
|
||||
else
|
||||
entry[:type]
|
||||
end
|
||||
rescue Rugged::TreeError
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def repo_changes
|
||||
|
||||
@@ -14,6 +14,8 @@ module Banzai
|
||||
def call
|
||||
return doc unless linkable_files?
|
||||
|
||||
@uri_types = {}
|
||||
|
||||
doc.search('a:not(.gfm)').each do |el|
|
||||
process_link_attr el.attribute('href')
|
||||
end
|
||||
@@ -48,7 +50,7 @@ module Banzai
|
||||
uri.path = [
|
||||
relative_url_root,
|
||||
context[:project].path_with_namespace,
|
||||
path_type(file_path),
|
||||
uri_type(file_path),
|
||||
ref || context[:project].default_branch, # if no ref exists, point to the default branch
|
||||
file_path
|
||||
].compact.join('/').squeeze('/').chomp('/')
|
||||
@@ -87,7 +89,7 @@ module Banzai
|
||||
return path unless request_path
|
||||
|
||||
parts = request_path.split('/')
|
||||
parts.pop if path_type(request_path) != 'tree'
|
||||
parts.pop if uri_type(request_path) != :tree
|
||||
|
||||
while path.start_with?('../')
|
||||
parts.pop
|
||||
@@ -98,45 +100,20 @@ module Banzai
|
||||
end
|
||||
|
||||
def file_exists?(path)
|
||||
return false if path.nil?
|
||||
repository.blob_at(current_sha, path).present? ||
|
||||
repository.tree(current_sha, path).entries.any?
|
||||
path.present? && !!uri_type(path)
|
||||
end
|
||||
|
||||
# Get the type of the given path
|
||||
#
|
||||
# path - String path to check
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# path_type('doc/README.md') # => 'blob'
|
||||
# path_type('doc/logo.png') # => 'raw'
|
||||
# path_type('doc/api') # => 'tree'
|
||||
#
|
||||
# Returns a String
|
||||
def path_type(path)
|
||||
unescaped_path = Addressable::URI.unescape(path)
|
||||
def uri_type(path)
|
||||
@uri_types[path] ||= begin
|
||||
unescaped_path = Addressable::URI.unescape(path)
|
||||
|
||||
if tree?(unescaped_path)
|
||||
'tree'
|
||||
elsif image?(unescaped_path)
|
||||
'raw'
|
||||
else
|
||||
'blob'
|
||||
current_commit.uri_type(unescaped_path)
|
||||
end
|
||||
end
|
||||
|
||||
def tree?(path)
|
||||
repository.tree(current_sha, path).entries.any?
|
||||
end
|
||||
|
||||
def image?(path)
|
||||
repository.blob_at(current_sha, path).try(:image?)
|
||||
end
|
||||
|
||||
def current_sha
|
||||
context[:commit].try(:id) ||
|
||||
ref ? repository.commit(ref).try(:sha) : repository.head_commit.sha
|
||||
def current_commit
|
||||
@current_commit ||= context[:commit] ||
|
||||
ref ? repository.commit(ref) : repository.head_commit
|
||||
end
|
||||
|
||||
def relative_url_root
|
||||
@@ -148,7 +125,7 @@ module Banzai
|
||||
end
|
||||
|
||||
def repository
|
||||
context[:project].try(:repository)
|
||||
@repository ||= context[:project].try(:repository)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -132,11 +132,8 @@ describe Banzai::Filter::RelativeLinkFilter, lib: true do
|
||||
path = 'files/images/한글.png'
|
||||
escaped = Addressable::URI.escape(path)
|
||||
|
||||
# Stub these methods so the file doesn't actually need to be in the repo
|
||||
allow_any_instance_of(described_class).
|
||||
to receive(:file_exists?).and_return(true)
|
||||
allow_any_instance_of(described_class).
|
||||
to receive(:image?).with(path).and_return(true)
|
||||
# Stub this method so the file doesn't actually need to be in the repo
|
||||
allow_any_instance_of(described_class).to receive(:uri_type).and_return(:raw)
|
||||
|
||||
doc = filter(image(escaped))
|
||||
expect(doc.at_css('img')['src']).to match '/raw/'
|
||||
|
||||
@@ -207,4 +207,16 @@ eos
|
||||
expect(commit.participants).to include(note1.author, note2.author)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#uri_type' do
|
||||
it 'returns the URI type at the given path' do
|
||||
expect(commit.uri_type('files/html')).to be(:tree)
|
||||
expect(commit.uri_type('files/images/logo-black.png')).to be(:raw)
|
||||
expect(commit.uri_type('files/js/application.js')).to be(:blob)
|
||||
end
|
||||
|
||||
it "returns nil if the path doesn't exists" do
|
||||
expect(commit.uri_type('this/path/doesnt/exist')).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user