Commit 82bab49d authored by Alejandro Rodríguez's avatar Alejandro Rodríguez

Add feature flag to use gitaly-ssh mirroring when cloning internal repos

This also allows us to simplify the naming since we can make some
fetching methods private.
parent e0a135dc
...@@ -35,7 +35,7 @@ module Projects ...@@ -35,7 +35,7 @@ module Projects
repository.relative_path, repository.relative_path,
repository.gl_repository) repository.gl_repository)
new_repository.fetch_as_mirror_without_shell(repository.path) new_repository.fetch_repository_as_mirror(repository)
end end
def mark_old_paths_for_archive def mark_old_paths_for_archive
......
...@@ -18,6 +18,7 @@ module Gitlab ...@@ -18,6 +18,7 @@ module Gitlab
GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE
].freeze ].freeze
SEARCH_CONTEXT_LINES = 3 SEARCH_CONTEXT_LINES = 3
GITALY_INTERNAL_URL = 'ssh://gitaly/internal.git'.freeze
NoRepository = Class.new(StandardError) NoRepository = Class.new(StandardError)
InvalidBlobName = Class.new(StandardError) InvalidBlobName = Class.new(StandardError)
...@@ -1150,12 +1151,25 @@ module Gitlab ...@@ -1150,12 +1151,25 @@ module Gitlab
@has_visible_content = has_local_branches? @has_visible_content = has_local_branches?
end end
# Like all public `Gitlab::Git::Repository` methods, this method is part def fetch_repository_as_mirror(repository)
# of `Repository`'s interface through `method_missing`. remote_name = "tmp-#{SecureRandom.hex}"
# `Repository` has its own `fetch_remote` which uses `gitlab-shell` and
# takes some extra attributes, so we qualify this method name to prevent confusion. # Notice that this feature flag is not for `fetch_repository_as_mirror`
def fetch_remote_without_shell(remote = 'origin') # as a whole but for the fetching mechanism (file path or gitaly-ssh).
run_git(['fetch', remote]).last.zero? url, env = gitaly_migrate(:fetch_internal) do |is_enabled|
if is_enabled
repository = RemoteRepository.new(repository) unless repository.is_a?(RemoteRepository)
[GITALY_INTERNAL_URL, repository.fetch_env]
else
[repository.path, nil]
end
end
add_remote(remote_name, url)
set_remote_as_mirror(remote_name)
fetch_remote(remote_name, env: env)
ensure
remove_remote(remote_name)
end end
def blob_at(sha, path) def blob_at(sha, path)
...@@ -1661,7 +1675,7 @@ module Gitlab ...@@ -1661,7 +1675,7 @@ module Gitlab
end end
def gitaly_fetch_ref(source_repository, source_ref:, target_ref:) def gitaly_fetch_ref(source_repository, source_ref:, target_ref:)
args = %W(fetch --no-tags -f ssh://gitaly/internal.git #{source_ref}:#{target_ref}) args = %W(fetch --no-tags -f #{GITALY_INTERNAL_URL} #{source_ref}:#{target_ref})
run_git(args, env: source_repository.fetch_env) run_git(args, env: source_repository.fetch_env)
end end
...@@ -1681,6 +1695,10 @@ module Gitlab ...@@ -1681,6 +1695,10 @@ module Gitlab
rescue Rugged::ReferenceError rescue Rugged::ReferenceError
raise ArgumentError, 'Invalid merge source' raise ArgumentError, 'Invalid merge source'
end end
def fetch_remote(remote_name = 'origin', env: nil)
run_git(['fetch', remote_name], env: env).last.zero?
end
end end
end end
end end
...@@ -31,19 +31,6 @@ module Gitlab ...@@ -31,19 +31,6 @@ module Gitlab
end end
end end
# Like all_refs public `Gitlab::Git::Repository` methods, this method is part
# of `Repository`'s interface through `method_missing`.
# `Repository` has its own `fetch_as_mirror` which uses `gitlab-shell` and
# takes some extra attributes, so we qualify this method name to prevent confusion.
def fetch_as_mirror_without_shell(url)
remote_name = "tmp-#{SecureRandom.hex}"
add_remote(remote_name, url)
set_remote_as_mirror(remote_name)
fetch_remote_without_shell(remote_name)
ensure
remove_remote(remote_name) if remote_name
end
def remote_tags(remote) def remote_tags(remote)
# Each line has this format: "dc872e9fa6963f8f03da6c8f6f264d0845d6b092\trefs/tags/v1.10.0\n" # Each line has this format: "dc872e9fa6963f8f03da6c8f6f264d0845d6b092\trefs/tags/v1.10.0\n"
# We want to convert it to: [{ 'v1.10.0' => 'dc872e9fa6963f8f03da6c8f6f264d0845d6b092' }, ...] # We want to convert it to: [{ 'v1.10.0' => 'dc872e9fa6963f8f03da6c8f6f264d0845d6b092' }, ...]
......
...@@ -588,12 +588,12 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -588,12 +588,12 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
end end
describe '#fetch_as_mirror_without_shell' do describe '#fetch_repository_as_mirror' do
let(:new_repository) do let(:new_repository) do
Gitlab::Git::Repository.new('default', 'my_project.git', '') Gitlab::Git::Repository.new('default', 'my_project.git', '')
end end
subject { new_repository.fetch_as_mirror_without_shell(repository.path) } subject { new_repository.fetch_repository_as_mirror(repository) }
before do before do
Gitlab::Shell.new.add_repository('default', 'my_project') Gitlab::Shell.new.add_repository('default', 'my_project')
...@@ -603,7 +603,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -603,7 +603,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
Gitlab::Shell.new.remove_repository(TestEnv.repos_path, 'my_project') Gitlab::Shell.new.remove_repository(TestEnv.repos_path, 'my_project')
end end
it 'fetches a url 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))
...@@ -1652,21 +1652,6 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1652,21 +1652,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
end end
describe '#fetch_remote_without_shell' do
let(:git_path) { Gitlab.config.git.bin_path }
let(:remote_name) { 'my_remote' }
subject { repository.fetch_remote_without_shell(remote_name) }
it 'fetches the remote and returns true if the command was successful' do
expect(repository).to receive(:popen)
.with(%W(#{git_path} fetch #{remote_name}), repository.path, {})
.and_return(['', 0])
expect(subject).to be(true)
end
end
describe '#merge' do describe '#merge' do
let(:repository) do let(:repository) do
Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
......
...@@ -31,8 +31,8 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -31,8 +31,8 @@ describe Projects::UpdateRepositoryStorageService do
context 'when the move succeeds' do context 'when the move succeeds' do
it 'moves the repository to the new storage and unmarks the repository as read only' do it 'moves the repository to the new storage and unmarks the repository as read only' do
expect_any_instance_of(Gitlab::Git::Repository).to receive(:fetch_as_mirror_without_shell) expect_any_instance_of(Gitlab::Git::Repository).to receive(:fetch_repository_as_mirror)
.with(project.repository.raw.path).and_return(true) .with(project.repository.raw).and_return(true)
expect(GitlabShellWorker).to receive(:perform_async) expect(GitlabShellWorker).to receive(:perform_async)
.with(:mv_repository, .with(:mv_repository,
'tmp/tests/storage_a', 'tmp/tests/storage_a',
...@@ -48,8 +48,8 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -48,8 +48,8 @@ describe Projects::UpdateRepositoryStorageService do
context 'when the move fails' do context 'when the move fails' do
it 'unmarks the repository as read-only without updating the repository storage' do it 'unmarks the repository as read-only without updating the repository storage' do
expect_any_instance_of(Gitlab::Git::Repository).to receive(:fetch_as_mirror_without_shell) expect_any_instance_of(Gitlab::Git::Repository).to receive(:fetch_repository_as_mirror)
.with(project.repository.raw.path).and_return(false) .with(project.repository.raw).and_return(false)
expect(GitlabShellWorker).not_to receive(:perform_async) expect(GitlabShellWorker).not_to receive(:perform_async)
subject.execute('b') subject.execute('b')
...@@ -84,16 +84,16 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -84,16 +84,16 @@ describe Projects::UpdateRepositoryStorageService do
context 'when the move succeeds' do context 'when the move succeeds' do
it 'moves the repository and its wiki to the new storage and unmarks the repository as read only' do it 'moves the repository and its wiki to the new storage and unmarks the repository as read only' do
expect(repository_double).to receive(:fetch_as_mirror_without_shell) expect(repository_double).to receive(:fetch_repository_as_mirror)
.with(project.repository.raw.path).and_return(true) .with(project.repository.raw).and_return(true)
expect(GitlabShellWorker).to receive(:perform_async) expect(GitlabShellWorker).to receive(:perform_async)
.with(:mv_repository, .with(:mv_repository,
'tmp/tests/storage_a', 'tmp/tests/storage_a',
project.disk_path, project.disk_path,
"#{project.disk_path}+#{project.id}+moved+#{time.to_i}") "#{project.disk_path}+#{project.id}+moved+#{time.to_i}")
expect(wiki_repository_double).to receive(:fetch_as_mirror_without_shell) expect(wiki_repository_double).to receive(:fetch_repository_as_mirror)
.with(project.wiki.repository.raw.path).and_return(true) .with(project.wiki.repository.raw).and_return(true)
expect(GitlabShellWorker).to receive(:perform_async) expect(GitlabShellWorker).to receive(:perform_async)
.with(:mv_repository, .with(:mv_repository,
'tmp/tests/storage_a', 'tmp/tests/storage_a',
...@@ -109,10 +109,10 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -109,10 +109,10 @@ describe Projects::UpdateRepositoryStorageService do
context 'when the move of the wiki fails' do context 'when the move of the wiki fails' do
it 'unmarks the repository as read-only without updating the repository storage' do it 'unmarks the repository as read-only without updating the repository storage' do
expect(repository_double).to receive(:fetch_as_mirror_without_shell) expect(repository_double).to receive(:fetch_repository_as_mirror)
.with(project.repository.raw.path).and_return(true) .with(project.repository.raw).and_return(true)
expect(wiki_repository_double).to receive(:fetch_as_mirror_without_shell) expect(wiki_repository_double).to receive(:fetch_repository_as_mirror)
.with(project.wiki.repository.raw.path).and_return(false) .with(project.wiki.repository.raw).and_return(false)
expect(GitlabShellWorker).not_to receive(:perform_async) expect(GitlabShellWorker).not_to receive(:perform_async)
subject.execute('b') subject.execute('b')
......
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