Commit fdb32ee4 authored by Nick Thomas's avatar Nick Thomas

Move the blob LFS enabled lookup to the repository

Blobs can "look through" LFS pointers to the backing object, but only
if the blob belongs to a project or project wiki repository (for now).
This change moves the logic for that to the repository as a precursor
to making it static data.
parent dfb38bf8
......@@ -129,7 +129,7 @@ class Blob < SimpleDelegator
def external_storage_error?
if external_storage == :lfs
!project&.lfs_enabled?
!repository.lfs_enabled?
else
false
end
......
......@@ -1120,6 +1120,17 @@ class Repository
end
end
# TODO: pass this in directly to `Blob` rather than delegating it to here
#
# https://gitlab.com/gitlab-org/gitlab/-/issues/201886
def lfs_enabled?
if container.is_a?(Project)
container.lfs_enabled?
else
false # LFS is not supported for snippet or group repositories
end
end
private
# TODO Genericize finder, later split this on finders by Ref or Oid
......
......@@ -219,6 +219,29 @@ describe Repository do
end
end
describe '#lfs_enabled? (design repositories)' do
let(:project) { create(:project, :design_repo, lfs_enabled: lfs_enabled) }
let(:repository) { project.design_repository }
before do
stub_lfs_setting(enabled: true)
end
subject { repository.lfs_enabled? }
context 'project has LFS disabled' do
let(:lfs_enabled) { false }
it { is_expected.to be_falsy }
end
context 'project has LFS enabled' do
let(:lfs_enabled) { true }
it { is_expected.to be_truthy }
end
end
describe '#upstream_branch_name' do
let(:pull_mirror_branch_prefix) { 'upstream/' }
let(:branch_name) { 'upstream/master' }
......
......@@ -5,12 +5,17 @@ require 'spec_helper'
describe Blob do
include FakeBlobHelpers
let(:project) { build(:project, lfs_enabled: true) }
using RSpec::Parameterized::TableSyntax
let(:project) { build(:project) }
let(:personal_snippet) { build(:personal_snippet) }
let(:project_snippet) { build(:project_snippet, project: project) }
let(:repository) { project.repository }
let(:lfs_enabled) { true }
before do
allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
allow(repository).to receive(:lfs_enabled?) { lfs_enabled }
end
describe '.decorate' do
......@@ -128,399 +133,84 @@ describe Blob do
end
describe '#external_storage_error?' do
shared_examples 'no error' do
it do
expect(blob.external_storage_error?).to be_falsey
end
end
shared_examples 'returns error' do
it do
expect(blob.external_storage_error?).to be_truthy
end
end
subject { blob.external_storage_error? }
context 'if the blob is stored in LFS' do
let(:blob) { fake_blob(path: 'file.pdf', lfs: true, container: container) }
context 'when the project has LFS enabled' do
context 'with project' do
let(:container) { project }
it_behaves_like 'no error'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns error'
end
let(:blob) { fake_blob(path: 'file.pdf', lfs: true) }
context 'with project snippet' do
let(:container) { project_snippet }
context 'when LFS is enabled' do
let(:lfs_enabled) { true }
it_behaves_like 'no error'
end
it { is_expected.to be_falsy }
end
context 'when the project does not have LFS enabled' do
before do
project.lfs_enabled = false
end
context 'with project' do
let(:container) { project }
context 'when LFS is not enabled' do
let(:lfs_enabled) { false }
it_behaves_like 'returns error'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns error'
end
it { is_expected.to be_truthy }
end
end
context 'if the blob is not stored in LFS' do
let(:blob) { fake_blob(path: 'file.md', container: container) }
context 'with project' do
let(:container) { project }
it_behaves_like 'no error'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'no error'
end
context 'with project snippet' do
let(:container) { project_snippet }
let(:blob) { fake_blob(path: 'file.md') }
it_behaves_like 'no error'
end
it { is_expected.to be_falsy }
end
end
describe '#stored_externally?' do
subject { blob.stored_externally? }
context 'if the blob is stored in LFS' do
let(:blob) { fake_blob(path: 'file.pdf', lfs: true) }
shared_examples 'returns true' do
it do
expect(blob.stored_externally?).to be_truthy
end
end
shared_examples 'returns false' do
it do
expect(blob.stored_externally?).to be_falsey
end
end
context 'when the project has LFS enabled' do
context 'with project' do
let(:container) { project }
it_behaves_like 'returns true'
end
context 'when LFS is enabled' do
let(:lfs_enabled) { true }
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns true'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns true'
end
it { is_expected.to be_truthy }
end
context 'when the project does not have LFS enabled' do
before do
project.lfs_enabled = false
end
context 'with project' do
let(:container) { project }
it_behaves_like 'returns false'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
context 'when LFS is not enabled' do
let(:lfs_enabled) { false }
it_behaves_like 'returns false'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns false'
end
it { is_expected.to be_falsy }
end
end
context 'if the blob is not stored in LFS' do
let(:blob) { fake_blob(path: 'file.md') }
it 'returns false' do
expect(blob.stored_externally?).to be_falsey
end
it { is_expected.to be_falsy }
end
end
describe '#binary?' do
shared_examples 'returns true' do
it do
expect(blob.binary?).to be_truthy
end
end
shared_examples 'returns false' do
it do
expect(blob.binary?).to be_falsey
end
end
context 'if the blob is stored externally' do
let(:blob) { fake_blob(path: file, lfs: true) }
context 'if the extension has a rich viewer' do
context 'if the viewer is binary' do
let(:file) { 'file.pdf' }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns true'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns true'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns true'
end
end
context 'if the viewer is text-based' do
let(:file) { 'file.md' }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns false'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns false'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns false'
end
end
context 'an lfs object' do
where(:filename, :is_binary) do
'file.pdf' | true
'file.md' | false
'file.txt' | false
'file.ics' | false
'file.rb' | false
'file.exe' | true
'file.ini' | false
'file.wtf' | true
end
context "if the extension doesn't have a rich viewer" do
context 'if the extension has a text mime type' do
context 'if the extension is for a programming language' do
let(:file) { 'file.txt' }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns false'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns false'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns false'
end
end
context 'if the extension is not for a programming language' do
let(:file) { 'file.ics' }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns false'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns false'
end
context 'with project snippet' do
let(:container) { project_snippet }
with_them do
let(:blob) { fake_blob(path: filename, lfs: true, container: project) }
it_behaves_like 'returns false'
end
end
end
context 'if the extension has a binary mime type' do
context 'if the extension is for a programming language' do
let(:file) { 'file.rb' }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns false'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns false'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns false'
end
end
context 'if the extension is not for a programming language' do
let(:file) { 'file.exe' }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns true'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns true'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns true'
end
end
end
context 'if the extension has an unknown mime type' do
context 'if the extension is for a programming language' do
let(:file) { 'file.ini' }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns false'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns false'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns false'
end
end
context 'if the extension is not for a programming language' do
let(:file) { 'file.wtf' }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns true'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns true'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns true'
end
end
end
it { expect(blob.binary?).to eq(is_binary) }
end
end
context 'if the blob is not stored externally' do
context 'if the blob is binary' do
let(:blob) { fake_blob(path: 'file.pdf', binary: true, container: container) }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns true'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns true'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns true'
end
end
context 'if the blob is text-based' do
let(:blob) { fake_blob(path: 'file.md', container: container) }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns false'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns false'
end
context 'a non-lfs object' do
let(:blob) { fake_blob(path: 'anything', container: project) }
context 'with project snippet' do
let(:container) { project_snippet }
it 'delegates to binary_in_repo?' do
expect(blob).to receive(:binary_in_repo?) { :result }
it_behaves_like 'returns false'
end
expect(blob.binary?).to eq(:result)
end
end
end
......@@ -569,9 +259,7 @@ describe Blob do
describe '#rich_viewer' do
context 'when the blob has an external storage error' do
before do
project.lfs_enabled = false
end
let(:lfs_enabled) { false }
it 'returns nil' do
blob = fake_blob(path: 'file.pdf', lfs: true)
......@@ -631,9 +319,7 @@ describe Blob do
describe '#auxiliary_viewer' do
context 'when the blob has an external storage error' do
before do
project.lfs_enabled = false
end
let(:lfs_enabled) { false }
it 'returns nil' do
blob = fake_blob(path: 'LICENSE', lfs: true)
......@@ -676,63 +362,21 @@ describe Blob do
end
describe '#rendered_as_text?' do
shared_examples 'returns true' do
it do
expect(blob.rendered_as_text?(ignore_errors: ignore_errors)).to be_truthy
end
end
shared_examples 'returns false' do
it do
expect(blob.rendered_as_text?(ignore_errors: ignore_errors)).to be_falsey
end
end
subject { blob.rendered_as_text?(ignore_errors: ignore_errors) }
context 'when ignoring errors' do
let(:ignore_errors) { true }
context 'when the simple viewer is text-based' do
let(:blob) { fake_blob(path: 'file.md', size: 100.megabytes, container: container) }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns true'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
let(:blob) { fake_blob(path: 'file.md', size: 100.megabytes) }
it_behaves_like 'returns true'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns true'
end
it { is_expected.to be_truthy }
end
context 'when the simple viewer is binary' do
let(:blob) { fake_blob(path: 'file.pdf', binary: true, size: 100.megabytes, container: container) }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns false'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns false'
end
context 'with project snippet' do
let(:container) { project_snippet }
let(:blob) { fake_blob(path: 'file.pdf', binary: true, size: 100.megabytes) }
it_behaves_like 'returns false'
end
it { is_expected.to be_falsy }
end
end
......@@ -740,47 +384,15 @@ describe Blob do
let(:ignore_errors) { false }
context 'when the viewer has render errors' do
let(:blob) { fake_blob(path: 'file.md', size: 100.megabytes, container: container) }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns false'
end
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns false'
end
context 'with project snippet' do
let(:container) { project_snippet }
let(:blob) { fake_blob(path: 'file.md', size: 100.megabytes) }
it_behaves_like 'returns false'
end
it { is_expected.to be_falsy }
end
context "when the viewer doesn't have render errors" do
let(:blob) { fake_blob(path: 'file.md', container: container) }
context 'with project' do
let(:container) { project }
it_behaves_like 'returns true'
end
let(:blob) { fake_blob(path: 'file.md') }
context 'with personal snippet' do
let(:container) { personal_snippet }
it_behaves_like 'returns true'
end
context 'with project snippet' do
let(:container) { project_snippet }
it_behaves_like 'returns true'
end
it { is_expected.to be_truthy }
end
end
end
......
......@@ -2874,4 +2874,64 @@ describe Repository do
expect(repository.submodule_links).to be_a(Gitlab::SubmoduleLinks)
end
end
describe '#lfs_enabled?' do
let_it_be(:project) { create(:project, :repository, lfs_enabled: true) }
subject { repository.lfs_enabled? }
context 'for a project repository' do
let(:repository) { project.repository }
it 'returns true when LFS is enabled' do
stub_lfs_setting(enabled: true)
is_expected.to be_truthy
end
it 'returns false when LFS is disabled' do
stub_lfs_setting(enabled: false)
is_expected.to be_falsy
end
end
context 'for a project wiki repository' do
let(:repository) { project.wiki.repository }
it 'returns true when LFS is enabled' do
stub_lfs_setting(enabled: true)
is_expected.to be_truthy
end
it 'returns false when LFS is disabled' do
stub_lfs_setting(enabled: false)
is_expected.to be_falsy
end
end
context 'for a project snippet repository' do
let(:snippet) { create(:project_snippet, project: project) }
let(:repository) { snippet.repository }
it 'returns false when LFS is enabled' do
stub_lfs_setting(enabled: true)
is_expected.to be_falsy
end
end
context 'for a personal snippet repository' do
let(:snippet) { create(:personal_snippet) }
let(:repository) { snippet.repository }
it 'returns false when LFS is enabled' do
stub_lfs_setting(enabled: true)
is_expected.to be_falsy
end
end
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