Commit 34f89db6 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '49591-use-cached-readme-blobs' into 'master'

Use cached readme blobs where appropriate

Closes #49591

See merge request gitlab-org/gitlab-ce!22325
parents a621c8d0 0669127a
...@@ -487,7 +487,20 @@ class Repository ...@@ -487,7 +487,20 @@ class Repository
end end
def blob_at(sha, path) def blob_at(sha, path)
Blob.decorate(raw_repository.blob_at(sha, path), project) blob = Blob.decorate(raw_repository.blob_at(sha, path), project)
# Don't attempt to return a special result if there is no blob at all
return unless blob
# Don't attempt to return a special result unless we're looking at HEAD
return blob unless head_commit&.sha == sha
case path
when head_tree&.readme_path
ReadmeBlob.new(blob, self)
else
blob
end
rescue Gitlab::Git::Repository::NoRepository rescue Gitlab::Git::Repository::NoRepository
nil nil
end end
...@@ -569,9 +582,7 @@ class Repository ...@@ -569,9 +582,7 @@ class Repository
cache_method :merge_request_template_names, fallback: [] cache_method :merge_request_template_names, fallback: []
def readme def readme
if readme = tree(:head)&.readme head_tree&.readme
ReadmeBlob.new(readme, self)
end
end end
def rendered_readme def rendered_readme
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
class Tree class Tree
include Gitlab::MarkupHelper include Gitlab::MarkupHelper
include Gitlab::Utils::StrongMemoize
attr_accessor :repository, :sha, :path, :entries attr_accessor :repository, :sha, :path, :entries
...@@ -16,9 +17,8 @@ class Tree ...@@ -16,9 +17,8 @@ class Tree
@entries = Gitlab::Git::Tree.where(git_repo, @sha, @path, recursive) @entries = Gitlab::Git::Tree.where(git_repo, @sha, @path, recursive)
end end
def readme def readme_path
return @readme if defined?(@readme) strong_memoize(:readme_path) do
available_readmes = blobs.select do |blob| available_readmes = blobs.select do |blob|
Gitlab::FileDetector.type_of(blob.name) == :readme Gitlab::FileDetector.type_of(blob.name) == :readme
end end
...@@ -32,16 +32,21 @@ class Tree ...@@ -32,16 +32,21 @@ class Tree
end end
# Prioritize previewable over plain readmes # Prioritize previewable over plain readmes
readme_tree = previewable_readmes.first || plain_readmes.first entry = previewable_readmes.first || plain_readmes.first
next nil unless entry
# Return if we can't preview any of them if path == '/'
if readme_tree.nil? entry.name
return @readme = nil else
File.join(path, entry.name)
end
end
end end
readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name) def readme
strong_memoize(:readme) do
@readme = repository.blob_at(sha, readme_path) repository.blob_at(sha, readme_path) if readme_path
end
end end
def trees def trees
......
---
title: Use cached readme contents when available
merge_request: 22325
author:
type: performance
...@@ -527,28 +527,28 @@ describe Project do ...@@ -527,28 +527,28 @@ describe Project do
end end
describe "#readme_url" do describe "#readme_url" do
let(:project) { create(:project, :repository, path: "somewhere") }
context 'with a non-existing repository' do context 'with a non-existing repository' do
it 'returns nil' do let(:project) { create(:project) }
allow(project.repository).to receive(:tree).with(:head).and_return(nil)
it 'returns nil' do
expect(project.readme_url).to be_nil expect(project.readme_url).to be_nil
end end
end end
context 'with an existing repository' do context 'with an existing repository' do
context 'when no README exists' do context 'when no README exists' do
it 'returns nil' do let(:project) { create(:project, :empty_repo) }
allow_any_instance_of(Tree).to receive(:readme).and_return(nil)
it 'returns nil' do
expect(project.readme_url).to be_nil expect(project.readme_url).to be_nil
end end
end end
context 'when a README exists' do context 'when a README exists' do
let(:project) { create(:project, :repository) }
it 'returns the README' do it 'returns the README' do
expect(project.readme_url).to eql("#{Gitlab.config.gitlab.url}/#{project.namespace.full_path}/somewhere/blob/master/README.md") expect(project.readme_url).to eq("#{project.web_url}/blob/master/README.md")
end end
end end
end end
......
...@@ -461,6 +461,24 @@ describe Repository do ...@@ -461,6 +461,24 @@ describe Repository do
it { is_expected.to be_nil } it { is_expected.to be_nil }
end end
context 'regular blob' do
subject { repository.blob_at(repository.head_commit.sha, '.gitignore') }
it { is_expected.to be_an_instance_of(::Blob) }
end
context 'readme blob on HEAD' do
subject { repository.blob_at(repository.head_commit.sha, 'README.md') }
it { is_expected.to be_an_instance_of(::ReadmeBlob) }
end
context 'readme blob not on HEAD' do
subject { repository.blob_at(repository.find_branch('feature').target, 'README.md') }
it { is_expected.to be_an_instance_of(::Blob) }
end
end end
describe '#merged_to_root_ref?' do describe '#merged_to_root_ref?' do
...@@ -1922,23 +1940,25 @@ describe Repository do ...@@ -1922,23 +1940,25 @@ describe Repository do
describe '#readme', :use_clean_rails_memory_store_caching do describe '#readme', :use_clean_rails_memory_store_caching do
context 'with a non-existing repository' do context 'with a non-existing repository' do
it 'returns nil' do let(:project) { create(:project) }
allow(repository).to receive(:tree).with(:head).and_return(nil)
it 'returns nil' do
expect(repository.readme).to be_nil expect(repository.readme).to be_nil
end end
end end
context 'with an existing repository' do context 'with an existing repository' do
context 'when no README exists' do context 'when no README exists' do
it 'returns nil' do let(:project) { create(:project, :empty_repo) }
allow_any_instance_of(Tree).to receive(:readme).and_return(nil)
it 'returns nil' do
expect(repository.readme).to be_nil expect(repository.readme).to be_nil
end end
end end
context 'when a README exists' do context 'when a README exists' do
let(:project) { create(:project, :repository) }
it 'returns the README' do it 'returns the README' do
expect(repository.readme).to be_an_instance_of(ReadmeBlob) expect(repository.readme).to be_an_instance_of(ReadmeBlob)
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