Commit 709e8b26 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'gitaly-tripswitch' into 'master'

Add "deny disk access" Gitaly feature (tripswitch)

Closes gitaly#1210

See merge request gitlab-org/gitlab-ce!19149
parents cc5890f2 edb9db37
...@@ -391,8 +391,10 @@ repositories_storages = Settings.repositories.storages.values ...@@ -391,8 +391,10 @@ repositories_storages = Settings.repositories.storages.values
repository_downloads_path = Settings.gitlab['repository_downloads_path'].to_s.gsub(%r{/$}, '') repository_downloads_path = Settings.gitlab['repository_downloads_path'].to_s.gsub(%r{/$}, '')
repository_downloads_full_path = File.expand_path(repository_downloads_path, Settings.gitlab['user_home']) repository_downloads_full_path = File.expand_path(repository_downloads_path, Settings.gitlab['user_home'])
if repository_downloads_path.blank? || repositories_storages.any? { |rs| [repository_downloads_path, repository_downloads_full_path].include?(rs.legacy_disk_path.gsub(%r{/$}, '')) } Gitlab::GitalyClient::StorageSettings.allow_disk_access do
Settings.gitlab['repository_downloads_path'] = File.join(Settings.shared['path'], 'cache/archive') if repository_downloads_path.blank? || repositories_storages.any? { |rs| [repository_downloads_path, repository_downloads_full_path].include?(rs.legacy_disk_path.gsub(%r{/$}, '')) }
Settings.gitlab['repository_downloads_path'] = File.join(Settings.shared['path'], 'cache/archive')
end
end end
# #
......
...@@ -38,10 +38,12 @@ def validate_storages_config ...@@ -38,10 +38,12 @@ def validate_storages_config
end end
def validate_storages_paths def validate_storages_paths
Gitlab.config.repositories.storages.each do |name, repository_storage| Gitlab::GitalyClient::StorageSettings.allow_disk_access do
parent_name, _parent_path = find_parent_path(name, repository_storage.legacy_disk_path) Gitlab.config.repositories.storages.each do |name, repository_storage|
if parent_name parent_name, _parent_path = find_parent_path(name, repository_storage.legacy_disk_path)
storage_validation_error("#{name} is a nested path of #{parent_name}. Nested paths are not supported for repository storages") if parent_name
storage_validation_error("#{name} is a nested path of #{parent_name}. Nested paths are not supported for repository storages")
end
end end
end end
end end
......
...@@ -7,7 +7,9 @@ module Gitlab ...@@ -7,7 +7,9 @@ module Gitlab
end end
def value def value
@value ||= count_commits Gitlab::GitalyClient::StorageSettings.allow_disk_access do
@value ||= count_commits
end
end end
private private
......
...@@ -1185,15 +1185,17 @@ module Gitlab ...@@ -1185,15 +1185,17 @@ module Gitlab
end end
def compare_source_branch(target_branch_name, source_repository, source_branch_name, straight:) def compare_source_branch(target_branch_name, source_repository, source_branch_name, straight:)
with_repo_branch_commit(source_repository, source_branch_name) do |commit| Gitlab::GitalyClient::StorageSettings.allow_disk_access do
break unless commit with_repo_branch_commit(source_repository, source_branch_name) do |commit|
break unless commit
Gitlab::Git::Compare.new(
self, Gitlab::Git::Compare.new(
target_branch_name, self,
commit.sha, target_branch_name,
straight: straight commit.sha,
) straight: straight
)
end
end end
end end
...@@ -1455,7 +1457,7 @@ module Gitlab ...@@ -1455,7 +1457,7 @@ module Gitlab
gitaly_repository_client.cleanup if is_enabled && exists? gitaly_repository_client.cleanup if is_enabled && exists?
end end
rescue Gitlab::Git::CommandError => e # Don't fail if we can't cleanup rescue Gitlab::Git::CommandError => e # Don't fail if we can't cleanup
Rails.logger.error("Unable to clean repository on storage #{storage} with path #{path}: #{e.message}") Rails.logger.error("Unable to clean repository on storage #{storage} with relative path #{relative_path}: #{e.message}")
Gitlab::Metrics.counter( Gitlab::Metrics.counter(
:failed_repository_cleanup_total, :failed_repository_cleanup_total,
'Number of failed repository cleanup events' 'Number of failed repository cleanup events'
......
...@@ -35,7 +35,7 @@ module Gitlab ...@@ -35,7 +35,7 @@ module Gitlab
def initialize(storage, logger = Rails.logger) def initialize(storage, logger = Rails.logger)
@storage = storage @storage = storage
config = Gitlab.config.repositories.storages[@storage] config = Gitlab.config.repositories.storages[@storage]
@storage_path = config.legacy_disk_path @storage_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { config.legacy_disk_path }
@logger = logger @logger = logger
@hostname = Gitlab::Environment.hostname @hostname = Gitlab::Environment.hostname
......
...@@ -22,13 +22,14 @@ module Gitlab ...@@ -22,13 +22,14 @@ module Gitlab
def self.build(storage, hostname = Gitlab::Environment.hostname) def self.build(storage, hostname = Gitlab::Environment.hostname)
config = Gitlab.config.repositories.storages[storage] config = Gitlab.config.repositories.storages[storage]
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
if !config.present? if !config.present?
NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Storage '#{storage}' is not configured")) NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Storage '#{storage}' is not configured"))
elsif !config.legacy_disk_path.present? elsif !config.legacy_disk_path.present?
NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Path for storage '#{storage}' is not configured")) NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Path for storage '#{storage}' is not configured"))
else else
new(storage, hostname) new(storage, hostname)
end
end end
end end
......
...@@ -33,6 +33,11 @@ module Gitlab ...@@ -33,6 +33,11 @@ module Gitlab
MAXIMUM_GITALY_CALLS = 35 MAXIMUM_GITALY_CALLS = 35
CLIENT_NAME = (Sidekiq.server? ? 'gitlab-sidekiq' : 'gitlab-web').freeze CLIENT_NAME = (Sidekiq.server? ? 'gitlab-sidekiq' : 'gitlab-web').freeze
# We have a mechanism to let GitLab automatically opt in to all Gitaly
# features. We want to be able to exclude some features from automatic
# opt-in. That is what EXPLICIT_OPT_IN_REQUIRED is for.
EXPLICIT_OPT_IN_REQUIRED = [Gitlab::GitalyClient::StorageSettings::DISK_ACCESS_DENIED_FLAG].freeze
MUTEX = Mutex.new MUTEX = Mutex.new
class << self class << self
...@@ -234,7 +239,7 @@ module Gitlab ...@@ -234,7 +239,7 @@ module Gitlab
when MigrationStatus::OPT_OUT when MigrationStatus::OPT_OUT
true true
when MigrationStatus::OPT_IN when MigrationStatus::OPT_IN
opt_into_all_features? opt_into_all_features? && !EXPLICIT_OPT_IN_REQUIRED.include?(feature_name)
else else
false false
end end
......
...@@ -4,6 +4,8 @@ module Gitlab ...@@ -4,6 +4,8 @@ module Gitlab
# where production code (app, config, db, lib) touches Git repositories # where production code (app, config, db, lib) touches Git repositories
# directly. # directly.
class StorageSettings class StorageSettings
extend Gitlab::TemporarilyAllow
DirectPathAccessError = Class.new(StandardError) DirectPathAccessError = Class.new(StandardError)
InvalidConfigurationError = Class.new(StandardError) InvalidConfigurationError = Class.new(StandardError)
...@@ -17,7 +19,21 @@ module Gitlab ...@@ -17,7 +19,21 @@ module Gitlab
# This class will give easily recognizable NoMethodErrors # This class will give easily recognizable NoMethodErrors
Deprecated = Class.new Deprecated = Class.new
attr_reader :legacy_disk_path MUTEX = Mutex.new
DISK_ACCESS_DENIED_FLAG = :deny_disk_access
ALLOW_KEY = :allow_disk_access
# If your code needs this method then your code needs to be fixed.
def self.allow_disk_access
temporarily_allow(ALLOW_KEY) { yield }
end
def self.disk_access_denied?
!temporarily_allowed?(ALLOW_KEY) && GitalyClient.feature_enabled?(DISK_ACCESS_DENIED_FLAG)
rescue
false # Err on the side of caution, don't break gitlab for people
end
def initialize(storage) def initialize(storage)
raise InvalidConfigurationError, "expected a Hash, got a #{storage.class.name}" unless storage.is_a?(Hash) raise InvalidConfigurationError, "expected a Hash, got a #{storage.class.name}" unless storage.is_a?(Hash)
...@@ -34,6 +50,14 @@ module Gitlab ...@@ -34,6 +50,14 @@ module Gitlab
@hash.fetch(:gitaly_address) @hash.fetch(:gitaly_address)
end end
def legacy_disk_path
if self.class.disk_access_denied?
raise DirectPathAccessError, "git disk access denied via the gitaly_#{DISK_ACCESS_DENIED_FLAG} feature"
end
@legacy_disk_path
end
private private
def method_missing(m, *args, &block) def method_missing(m, *args, &block)
......
...@@ -77,7 +77,9 @@ module Gitlab ...@@ -77,7 +77,9 @@ module Gitlab
end end
def storage_path(storage_name) def storage_path(storage_name)
storages_paths[storage_name]&.legacy_disk_path Gitlab::GitalyClient::StorageSettings.allow_disk_access do
storages_paths[storage_name]&.legacy_disk_path
end
end end
# All below test methods use shell commands to perform actions on storage volumes. # All below test methods use shell commands to perform actions on storage volumes.
......
module Gitlab
module TemporarilyAllow
TEMPORARILY_ALLOW_MUTEX = Mutex.new
def temporarily_allow(key)
temporarily_allow_add(key, 1)
yield
ensure
temporarily_allow_add(key, -1)
end
def temporarily_allowed?(key)
if RequestStore.active?
temporarily_allow_request_store[key] > 0
else
TEMPORARILY_ALLOW_MUTEX.synchronize do
temporarily_allow_ivar[key] > 0
end
end
end
private
def temporarily_allow_ivar
@temporarily_allow ||= Hash.new(0)
end
def temporarily_allow_request_store
RequestStore[:temporarily_allow] ||= Hash.new(0)
end
def temporarily_allow_add(key, value)
if RequestStore.active?
temporarily_allow_request_store[key] += value
else
TEMPORARILY_ALLOW_MUTEX.synchronize do
temporarily_allow_ivar[key] += value
end
end
end
end
end
...@@ -299,7 +299,11 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :m ...@@ -299,7 +299,11 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :m
let(:commits) { merge_request_diff.commits.map(&:to_hash) } let(:commits) { merge_request_diff.commits.map(&:to_hash) }
let(:first_commit) { project.repository.commit(merge_request_diff.head_commit_sha) } let(:first_commit) { project.repository.commit(merge_request_diff.head_commit_sha) }
let(:expected_commits) { commits } let(:expected_commits) { commits }
let(:diffs) { first_commit.rugged_diff_from_parent.patches } let(:diffs) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
first_commit.rugged_diff_from_parent.patches
end
end
let(:expected_diffs) { [] } let(:expected_diffs) { [] }
include_examples 'updated MR diff' include_examples 'updated MR diff'
...@@ -309,7 +313,11 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :m ...@@ -309,7 +313,11 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :m
let(:commits) { merge_request_diff.commits.map(&:to_hash) } let(:commits) { merge_request_diff.commits.map(&:to_hash) }
let(:first_commit) { project.repository.commit(merge_request_diff.head_commit_sha) } let(:first_commit) { project.repository.commit(merge_request_diff.head_commit_sha) }
let(:expected_commits) { commits } let(:expected_commits) { commits }
let(:diffs) { first_commit.rugged_diff_from_parent.deltas } let(:diffs) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
first_commit.rugged_diff_from_parent.deltas
end
end
let(:expected_diffs) { [] } let(:expected_diffs) { [] }
include_examples 'updated MR diff' include_examples 'updated MR diff'
......
...@@ -6,7 +6,9 @@ describe Gitlab::Checks::LfsIntegrity do ...@@ -6,7 +6,9 @@ describe Gitlab::Checks::LfsIntegrity do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:repository) { project.repository } let(:repository) { project.repository }
let(:newrev) do let(:newrev) do
operations = BareRepoOperations.new(repository.path) operations = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
BareRepoOperations.new(repository.path)
end
# Create a commit not pointed at by any ref to emulate being in the # Create a commit not pointed at by any ref to emulate being in the
# pre-receive hook so that `--not --all` returns some objects # pre-receive hook so that `--not --all` returns some objects
......
...@@ -3,7 +3,7 @@ require 'spec_helper' ...@@ -3,7 +3,7 @@ require 'spec_helper'
describe Gitlab::Conflict::File do describe Gitlab::Conflict::File do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:repository) { project.repository } let(:repository) { project.repository }
let(:rugged) { repository.rugged } let(:rugged) { Gitlab::GitalyClient::StorageSettings.allow_disk_access { repository.rugged } }
let(:their_commit) { rugged.branches['conflict-start'].target } let(:their_commit) { rugged.branches['conflict-start'].target }
let(:our_commit) { rugged.branches['conflict-resolvable'].target } let(:our_commit) { rugged.branches['conflict-resolvable'].target }
let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project) } let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project) }
......
...@@ -114,7 +114,9 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -114,7 +114,9 @@ describe Gitlab::Git::Repository, seed_helper: true do
it 'raises a no repository exception when there is no repo' do it 'raises a no repository exception when there is no repo' do
broken_repo = described_class.new('default', 'a/path.git', '') broken_repo = described_class.new('default', 'a/path.git', '')
expect { broken_repo.rugged }.to raise_error(Gitlab::Git::Repository::NoRepository) expect do
Gitlab::GitalyClient::StorageSettings.allow_disk_access { broken_repo.rugged }
end.to raise_error(Gitlab::Git::Repository::NoRepository)
end end
describe 'alternates keyword argument' do describe 'alternates keyword argument' do
...@@ -124,9 +126,9 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -124,9 +126,9 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
it "is passed an empty array" do it "is passed an empty array" do
expect(Rugged::Repository).to receive(:new).with(repository.path, alternates: []) expect(Rugged::Repository).to receive(:new).with(repository_path, alternates: [])
repository.rugged repository_rugged
end end
end end
...@@ -142,10 +144,10 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -142,10 +144,10 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
it "is passed the relative object dir envvars after being converted to absolute ones" do it "is passed the relative object dir envvars after being converted to absolute ones" do
alternates = %w[foo bar baz].map { |d| File.join(repository.path, './objects', d) } alternates = %w[foo bar baz].map { |d| File.join(repository_path, './objects', d) }
expect(Rugged::Repository).to receive(:new).with(repository.path, alternates: alternates) expect(Rugged::Repository).to receive(:new).with(repository_path, alternates: alternates)
repository.rugged repository_rugged
end end
end end
end end
...@@ -156,16 +158,22 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -156,16 +158,22 @@ describe Gitlab::Git::Repository, seed_helper: true do
let(:feature) { 'feature' } let(:feature) { 'feature' }
let(:feature2) { 'feature2' } let(:feature2) { 'feature2' }
around do |example|
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run
end
end
it "returns 'master' when master exists" do it "returns 'master' when master exists" do
expect(repository).to receive(:branch_names).at_least(:once).and_return([feature, master]) expect(repository).to receive(:branch_names).at_least(:once).and_return([feature, master])
expect(repository.discover_default_branch).to eq('master') expect(repository.discover_default_branch).to eq('master')
end end
it "returns non-master when master exists but default branch is set to something else" do it "returns non-master when master exists but default branch is set to something else" do
File.write(File.join(repository.path, 'HEAD'), 'ref: refs/heads/feature') File.write(File.join(repository_path, 'HEAD'), 'ref: refs/heads/feature')
expect(repository).to receive(:branch_names).at_least(:once).and_return([feature, master]) expect(repository).to receive(:branch_names).at_least(:once).and_return([feature, master])
expect(repository.discover_default_branch).to eq('feature') expect(repository.discover_default_branch).to eq('feature')
File.write(File.join(repository.path, 'HEAD'), 'ref: refs/heads/master') File.write(File.join(repository_path, 'HEAD'), 'ref: refs/heads/master')
end end
it "returns a non-master branch when only one exists" do it "returns a non-master branch when only one exists" do
...@@ -364,6 +372,12 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -364,6 +372,12 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
context '#submodules' do context '#submodules' do
around do |example|
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run
end
end
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
context 'where repo has submodules' do context 'where repo has submodules' do
...@@ -474,8 +488,8 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -474,8 +488,8 @@ describe Gitlab::Git::Repository, seed_helper: true do
# Sanity check # Sanity check
expect(repository.has_local_branches?).to eq(true) expect(repository.has_local_branches?).to eq(true)
FileUtils.rm_rf(File.join(repository.path, 'packed-refs')) FileUtils.rm_rf(File.join(repository_path, 'packed-refs'))
heads_dir = File.join(repository.path, 'refs/heads') heads_dir = File.join(repository_path, 'refs/heads')
FileUtils.rm_rf(heads_dir) FileUtils.rm_rf(heads_dir)
FileUtils.mkdir_p(heads_dir) FileUtils.mkdir_p(heads_dir)
...@@ -516,10 +530,10 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -516,10 +530,10 @@ describe Gitlab::Git::Repository, seed_helper: true do
branch_name = "to-be-deleted-soon" branch_name = "to-be-deleted-soon"
repository.create_branch(branch_name) repository.create_branch(branch_name)
expect(repository.rugged.branches[branch_name]).not_to be_nil expect(repository_rugged.branches[branch_name]).not_to be_nil
repository.delete_branch(branch_name) repository.delete_branch(branch_name)
expect(repository.rugged.branches[branch_name]).to be_nil expect(repository_rugged.branches[branch_name]).to be_nil
end end
context "when branch does not exist" do context "when branch does not exist" do
...@@ -577,6 +591,12 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -577,6 +591,12 @@ describe Gitlab::Git::Repository, seed_helper: true do
shared_examples 'deleting refs' do shared_examples 'deleting refs' do
let(:repo) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') } let(:repo) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
def repo_rugged
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repo.rugged
end
end
after do after do
ensure_seeds ensure_seeds
end end
...@@ -584,7 +604,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -584,7 +604,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
it 'deletes the ref' do it 'deletes the ref' do
repo.delete_refs('refs/heads/feature') repo.delete_refs('refs/heads/feature')
expect(repo.rugged.references['refs/heads/feature']).to be_nil expect(repo_rugged.references['refs/heads/feature']).to be_nil
end end
it 'deletes all refs' do it 'deletes all refs' do
...@@ -592,7 +612,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -592,7 +612,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
repo.delete_refs(*refs) repo.delete_refs(*refs)
refs.each do |ref| refs.each do |ref|
expect(repo.rugged.references[ref]).to be_nil expect(repo_rugged.references[ref]).to be_nil
end end
end end
...@@ -615,7 +635,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -615,7 +635,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
describe '#branch_names_contains_sha' do describe '#branch_names_contains_sha' do
let(:head_id) { repository.rugged.head.target.oid } let(:head_id) { repository_rugged.head.target.oid }
let(:new_branch) { head_id } let(:new_branch) { head_id }
let(:utf8_branch) { 'branch-é' } let(:utf8_branch) { 'branch-é' }
...@@ -699,7 +719,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -699,7 +719,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
it 'fetches a repository as a mirror remote' do it 'fetches a repository as a mirror remote' do
subject subject
expect(refs(new_repository.path)).to eq(refs(repository.path)) expect(refs(new_repository_path)).to eq(refs(repository_path))
end end
context 'with keep-around refs' do context 'with keep-around refs' do
...@@ -708,15 +728,15 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -708,15 +728,15 @@ describe Gitlab::Git::Repository, seed_helper: true do
let(:tmp_ref) { "refs/tmp/#{SecureRandom.hex}" } let(:tmp_ref) { "refs/tmp/#{SecureRandom.hex}" }
before do before do
repository.rugged.references.create(keep_around_ref, sha, force: true) repository_rugged.references.create(keep_around_ref, sha, force: true)
repository.rugged.references.create(tmp_ref, sha, force: true) repository_rugged.references.create(tmp_ref, sha, force: true)
end end
it 'includes the temporary and keep-around refs' do it 'includes the temporary and keep-around refs' do
subject subject
expect(refs(new_repository.path)).to include(keep_around_ref) expect(refs(new_repository_path)).to include(keep_around_ref)
expect(refs(new_repository.path)).to include(tmp_ref) expect(refs(new_repository_path)).to include(tmp_ref)
end end
end end
end end
...@@ -728,6 +748,12 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -728,6 +748,12 @@ describe Gitlab::Git::Repository, seed_helper: true do
context 'with gitaly enabled', :skip_gitaly_mock do context 'with gitaly enabled', :skip_gitaly_mock do
it_behaves_like 'repository mirror fecthing' it_behaves_like 'repository mirror fecthing'
end end
def new_repository_path
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
new_repository.path
end
end
end end
describe '#remote_tags' do describe '#remote_tags' do
...@@ -739,10 +765,17 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -739,10 +765,17 @@ describe Gitlab::Git::Repository, seed_helper: true do
Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
end end
around do |example|
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run
end
end
subject { repository.remote_tags(remote_name) } subject { repository.remote_tags(remote_name) }
before do before do
repository.add_remote(remote_name, remote_repository.path) remote_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { remote_repository.path }
repository.add_remote(remote_name, remote_repository_path)
remote_repository.add_tag(tag_name, user: user, target: target_commit_id) remote_repository.add_tag(tag_name, user: user, target: target_commit_id)
end end
...@@ -975,8 +1008,10 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -975,8 +1008,10 @@ describe Gitlab::Git::Repository, seed_helper: true do
let(:options) { { ref: 'master', path: ['PROCESS.md', 'README.md'] } } let(:options) { { ref: 'master', path: ['PROCESS.md', 'README.md'] } }
def commit_files(commit) def commit_files(commit)
commit.rugged_diff_from_parent.deltas.flat_map do |delta| Gitlab::GitalyClient::StorageSettings.allow_disk_access do
[delta.old_file[:path], delta.new_file[:path]].uniq.compact commit.rugged_diff_from_parent.deltas.flat_map do |delta|
[delta.old_file[:path], delta.new_file[:path]].uniq.compact
end
end end
end end
...@@ -1019,6 +1054,12 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1019,6 +1054,12 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
describe "#rugged_commits_between" do describe "#rugged_commits_between" do
around do |example|
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run
end
end
context 'two SHAs' do context 'two SHAs' do
let(:first_sha) { 'b0e52af38d7ea43cf41d8a6f2471351ac036d6c9' } let(:first_sha) { 'b0e52af38d7ea43cf41d8a6f2471351ac036d6c9' }
let(:second_sha) { '0e50ec4d3c7ce42ab74dda1d422cb2cbffe1e326' } let(:second_sha) { '0e50ec4d3c7ce42ab74dda1d422cb2cbffe1e326' }
...@@ -1363,7 +1404,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1363,7 +1404,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
allow(ref).to receive(:target) { raise Rugged::ReferenceError } allow(ref).to receive(:target) { raise Rugged::ReferenceError }
branches = double() branches = double()
allow(branches).to receive(:each) { [ref].each } allow(branches).to receive(:each) { [ref].each }
allow(repository.rugged).to receive(:branches) { branches } allow(repository_rugged).to receive(:branches) { branches }
expect(subject).to be_empty expect(subject).to be_empty
end end
...@@ -1661,6 +1702,12 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1661,6 +1702,12 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#batch_existence' do describe '#batch_existence' do
let(:refs) { ['deadbeef', SeedRepo::RubyBlob::ID, '909e6157199'] } let(:refs) { ['deadbeef', SeedRepo::RubyBlob::ID, '909e6157199'] }
around do |example|
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run
end
end
it 'returns existing refs back' do it 'returns existing refs back' do
result = repository.batch_existence(refs) result = repository.batch_existence(refs)
...@@ -1840,7 +1887,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1840,7 +1887,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
context 'when the branch exists' do context 'when the branch exists' do
context 'when the commit does not exist locally' do context 'when the commit does not exist locally' do
let(:source_branch) { 'new-branch-for-fetch-source-branch' } let(:source_branch) { 'new-branch-for-fetch-source-branch' }
let(:source_rugged) { source_repository.rugged } let(:source_rugged) { Gitlab::GitalyClient::StorageSettings.allow_disk_access { source_repository.rugged } }
let(:new_oid) { new_commit_edit_old_file(source_rugged).oid } let(:new_oid) { new_commit_edit_old_file(source_rugged).oid }
before do before do
...@@ -1898,7 +1945,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1898,7 +1945,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
it "removes the branch from the repo" do it "removes the branch from the repo" do
repository.rm_branch(branch_name, user: user) repository.rm_branch(branch_name, user: user)
expect(repository.rugged.branches[branch_name]).to be_nil expect(repository_rugged.branches[branch_name]).to be_nil
end end
end end
...@@ -1930,7 +1977,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1930,7 +1977,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#write_config' do describe '#write_config' do
before do before do
repository.rugged.config["gitlab.fullpath"] = repository.path repository_rugged.config["gitlab.fullpath"] = repository_path
end end
shared_examples 'writing repo config' do shared_examples 'writing repo config' do
...@@ -1938,7 +1985,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1938,7 +1985,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
it 'writes it to disk' do it 'writes it to disk' do
repository.write_config(full_path: "not-the/real-path.git") repository.write_config(full_path: "not-the/real-path.git")
config = File.read(File.join(repository.path, "config")) config = File.read(File.join(repository_path, "config"))
expect(config).to include("[gitlab]") expect(config).to include("[gitlab]")
expect(config).to include("fullpath = not-the/real-path.git") expect(config).to include("fullpath = not-the/real-path.git")
...@@ -1949,10 +1996,10 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1949,10 +1996,10 @@ describe Gitlab::Git::Repository, seed_helper: true do
it 'does not write it to disk' do it 'does not write it to disk' do
repository.write_config(full_path: "") repository.write_config(full_path: "")
config = File.read(File.join(repository.path, "config")) config = File.read(File.join(repository_path, "config"))
expect(config).to include("[gitlab]") expect(config).to include("[gitlab]")
expect(config).to include("fullpath = #{repository.path}") expect(config).to include("fullpath = #{repository_path}")
end end
end end
end end
...@@ -2173,7 +2220,11 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -2173,7 +2220,11 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#gitlab_projects' do describe '#gitlab_projects' do
subject { repository.gitlab_projects } subject { repository.gitlab_projects }
it { expect(subject.shard_path).to eq(storage_path) } it do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
expect(subject.shard_path).to eq(storage_path)
end
end
it { expect(subject.repository_relative_path).to eq(repository.relative_path) } it { expect(subject.repository_relative_path).to eq(repository.relative_path) }
end end
...@@ -2189,7 +2240,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -2189,7 +2240,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
repository.bundle_to_disk(save_path) repository.bundle_to_disk(save_path)
success = system( success = system(
*%W(#{Gitlab.config.git.bin_path} -C #{repository.path} bundle verify #{save_path}), *%W(#{Gitlab.config.git.bin_path} -C #{repository_path} bundle verify #{save_path}),
[:out, :err] => '/dev/null' [:out, :err] => '/dev/null'
) )
expect(success).to be true expect(success).to be true
...@@ -2231,7 +2282,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -2231,7 +2282,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
it 'creates a symlink to the global hooks dir' do it 'creates a symlink to the global hooks dir' do
imported_repo.create_from_bundle(bundle_path) imported_repo.create_from_bundle(bundle_path)
hooks_path = File.join(imported_repo.path, 'hooks') hooks_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { File.join(imported_repo.path, 'hooks') }
expect(File.readlink(hooks_path)).to eq(Gitlab.config.gitlab_shell.hooks_path) expect(File.readlink(hooks_path)).to eq(Gitlab.config.gitlab_shell.hooks_path)
end end
...@@ -2360,7 +2411,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -2360,7 +2411,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
describe '#clean_stale_repository_files' do describe '#clean_stale_repository_files' do
let(:worktree_path) { File.join(repository.path, 'worktrees', 'delete-me') } let(:worktree_path) { File.join(repository_path, 'worktrees', 'delete-me') }
it 'cleans up the files' do it 'cleans up the files' do
repository.with_worktree(worktree_path, 'master', env: ENV) do repository.with_worktree(worktree_path, 'master', env: ENV) do
...@@ -2507,7 +2558,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -2507,7 +2558,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
def create_remote_branch(repository, remote_name, branch_name, source_branch_name) def create_remote_branch(repository, remote_name, branch_name, source_branch_name)
source_branch = repository.branches.find { |branch| branch.name == source_branch_name } source_branch = repository.branches.find { |branch| branch.name == source_branch_name }
rugged = repository.rugged rugged = repository_rugged
rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", source_branch.dereferenced_target.sha) rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", source_branch.dereferenced_target.sha)
end end
...@@ -2586,4 +2637,16 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -2586,4 +2637,16 @@ describe Gitlab::Git::Repository, seed_helper: true do
line.split("\t").last line.split("\t").last
end end
end end
def repository_rugged
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repository.rugged
end
end
def repository_path
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repository.path
end
end
end end
...@@ -7,7 +7,10 @@ RSpec.configure do |config| ...@@ -7,7 +7,10 @@ RSpec.configure do |config|
next if example.metadata[:skip_gitaly_mock] next if example.metadata[:skip_gitaly_mock]
# Use 'and_wrap_original' to make sure the arguments are valid # Use 'and_wrap_original' to make sure the arguments are valid
allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_wrap_original { |m, *args| m.call(*args) || true } allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_wrap_original do |m, *args|
m.call(*args)
!Gitlab::GitalyClient::EXPLICIT_OPT_IN_REQUIRED.include?(args.first)
end
end end
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