Commit c861a0a0 authored by Nick Thomas's avatar Nick Thomas

Remove GitlabShell#create_repository and wrappers

Project repository and wiki repository creation was indirected through
Gitlab::Shell unnecessarily. `GitlabShell#create_repository` build an
(incomplete) `Gitlab::Git::Repository` to run the creation code, but
all users already had access to `Repository` instances.
parent fd2ebba8
...@@ -1460,14 +1460,15 @@ class Project < ApplicationRecord ...@@ -1460,14 +1460,15 @@ class Project < ApplicationRecord
# Forked import is handled asynchronously # Forked import is handled asynchronously
return if forked? && !force return if forked? && !force
if gitlab_shell.create_project_repository(self) repository.create_repository
repository.after_create repository.after_create
true true
else rescue => err
errors.add(:base, _('Failed to create repository via gitlab-shell')) Gitlab::ErrorTracking.track_exception(err, project: { id: id, full_path: full_path, disk_path: disk_path })
errors.add(:base, _('Failed to create repository'))
false false
end end
end
def hook_attrs(backward: true) def hook_attrs(backward: true)
attrs = { attrs = {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
class ProjectWiki class ProjectWiki
include Storage::LegacyProjectWiki include Storage::LegacyProjectWiki
include Gitlab::Utils::StrongMemoize
MARKUPS = { MARKUPS = {
'Markdown' => :markdown, 'Markdown' => :markdown,
...@@ -63,14 +64,15 @@ class ProjectWiki ...@@ -63,14 +64,15 @@ class ProjectWiki
# Returns the Gitlab::Git::Wiki object. # Returns the Gitlab::Git::Wiki object.
def wiki def wiki
@wiki ||= begin strong_memoize(:wiki) do
gl_repository = Gitlab::GlRepository::WIKI.identifier_for_container(project) repository.create_if_not_exists
raw_repository = Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', gl_repository, full_path) raise CouldNotCreateWikiError unless repository_exists?
create_repo!(raw_repository) unless raw_repository.exists? Gitlab::Git::Wiki.new(repository.raw)
Gitlab::Git::Wiki.new(raw_repository)
end end
rescue => err
Gitlab::ErrorTracking.track_exception(err, project_wiki: { project_id: project.id, full_path: full_path, disk_path: disk_path })
raise CouldNotCreateWikiError
end end
def repository_exists? def repository_exists?
...@@ -192,14 +194,6 @@ class ProjectWiki ...@@ -192,14 +194,6 @@ class ProjectWiki
private private
def create_repo!(raw_repository)
gitlab_shell.create_wiki_repository(project)
raise CouldNotCreateWikiError unless raw_repository.exists?
repository.after_create
end
def commit_details(action, message = nil, title = nil) def commit_details(action, message = nil, title = nil)
commit_message = message.presence || default_message(action, title) commit_message = message.presence || default_message(action, title)
git_user = Gitlab::Git::User.from_gitlab(@user) git_user = Gitlab::Git::User.from_gitlab(@user)
......
...@@ -52,11 +52,14 @@ module Projects ...@@ -52,11 +52,14 @@ module Projects
checksum = repository.checksum checksum = repository.checksum
# Initialize a git repository on the target path # Initialize a git repository on the target path
gitlab_shell.create_repository(new_storage_key, raw_repository.relative_path, full_path) new_repository = Gitlab::Git::Repository.new(
new_repository = Gitlab::Git::Repository.new(new_storage_key, new_storage_key,
raw_repository.relative_path, raw_repository.relative_path,
raw_repository.gl_repository, raw_repository.gl_repository,
full_path) full_path
)
new_repository.create_repository
new_repository.replicate(raw_repository) new_repository.replicate(raw_repository)
new_checksum = new_repository.checksum new_checksum = new_repository.checksum
......
...@@ -72,10 +72,7 @@ module Geo ...@@ -72,10 +72,7 @@ module Geo
log_info("Attempting to fetch repository via git") log_info("Attempting to fetch repository via git")
# `git fetch` needs an empty bare repository to fetch into # `git fetch` needs an empty bare repository to fetch into
unless gitlab_shell.create_repository(project.repository_storage, disk_path_temp, project.full_path) temp_repo.create_repository
raise Gitlab::Shell::Error, 'Can not create a temporary repository'
end
fetch_geo_mirror(temp_repo) fetch_geo_mirror(temp_repo)
set_temp_repository_as_main set_temp_repository_as_main
......
...@@ -4,7 +4,6 @@ require 'yaml' ...@@ -4,7 +4,6 @@ require 'yaml'
module Backup module Backup
class Repository class Repository
include Gitlab::ShellAdapter
attr_reader :progress attr_reader :progress
def initialize(progress) def initialize(progress)
...@@ -71,22 +70,13 @@ module Backup ...@@ -71,22 +70,13 @@ module Backup
def restore def restore
Project.find_each(batch_size: 1000) do |project| Project.find_each(batch_size: 1000) do |project|
progress.print " * #{project.full_path} ... " progress.print " * #{project.full_path} ... "
path_to_project_bundle = path_to_bundle(project)
project.repository.remove rescue nil
restore_repo_success = nil
if File.exist?(path_to_project_bundle) restore_repo_success =
begin begin
project.repository.create_from_bundle(path_to_project_bundle) try_restore_repository(project)
restore_custom_hooks(project) rescue => err
restore_repo_success = true progress.puts "Error: #{err}".color(:red)
rescue => e false
restore_repo_success = false
progress.puts "Error: #{e}".color(:red)
end
else
restore_repo_success = gitlab_shell.create_project_repository(project)
end end
if restore_repo_success if restore_repo_success
...@@ -118,6 +108,20 @@ module Backup ...@@ -118,6 +108,20 @@ module Backup
protected protected
def try_restore_repository(project)
path_to_project_bundle = path_to_bundle(project)
project.repository.remove rescue nil
if File.exist?(path_to_project_bundle)
project.repository.create_from_bundle(path_to_project_bundle)
restore_custom_hooks(project)
else
project.repository.create_repository
end
true
end
def path_to_bundle(project) def path_to_bundle(project)
File.join(backup_repos_path, project.disk_path + '.bundle') File.join(backup_repos_path, project.disk_path + '.bundle')
end end
......
...@@ -77,47 +77,6 @@ module Gitlab ...@@ -77,47 +77,6 @@ module Gitlab
end end
end end
# Initialize a new project repository using a Project model
#
# @param [Project] project
# @return [Boolean] whether repository could be created
def create_project_repository(project)
create_repository(project.repository_storage, project.disk_path, project.full_path)
end
# Initialize a new wiki repository using a Project model
#
# @param [Project] project
# @return [Boolean] whether repository could be created
def create_wiki_repository(project)
create_repository(project.repository_storage, project.wiki.disk_path, project.wiki.full_path)
end
# Init new repository
#
# @example Create a repository
# create_repository("default", "path/to/gitlab-ci", "gitlab/gitlab-ci")
#
# @param [String] storage the shard key
# @param [String] disk_path project path on disk
# @param [String] gl_project_path project name
# @return [Boolean] whether repository could be created
def create_repository(storage, disk_path, gl_project_path)
relative_path = disk_path.dup
relative_path << '.git' unless relative_path.end_with?('.git')
# During creation of a repository, gl_repository may not be known
# because that depends on a yet-to-be assigned project ID in the
# database (e.g. project-1234), so for now it is blank.
repository = Gitlab::Git::Repository.new(storage, relative_path, '', gl_project_path)
wrapped_gitaly_errors { repository.gitaly_repository_client.create_repository }
true
rescue => err # Once the Rugged codes gets removes this can be improved
Rails.logger.error("Failed to add repository #{storage}/#{disk_path}: #{err}") # rubocop:disable Gitlab/RailsLogger
false
end
# Import wiki repository from external service # Import wiki repository from external service
# #
# @param [Project] project # @param [Project] project
......
...@@ -8348,7 +8348,7 @@ msgstr "" ...@@ -8348,7 +8348,7 @@ msgstr ""
msgid "Failed to create a branch for this issue. Please try again." msgid "Failed to create a branch for this issue. Please try again."
msgstr "" msgstr ""
msgid "Failed to create repository via gitlab-shell" msgid "Failed to create repository"
msgstr "" msgstr ""
msgid "Failed to create resources" msgid "Failed to create resources"
......
...@@ -50,9 +50,9 @@ describe Backup::Repository do ...@@ -50,9 +50,9 @@ describe Backup::Repository do
describe 'command failure' do describe 'command failure' do
before do before do
allow_next_instance_of(Gitlab::Shell) do |instance| # Allow us to set expectations on the project directly
allow(instance).to receive(:create_repository).and_return(false) expect(Project).to receive(:find_each).and_yield(project)
end expect(project.repository).to receive(:create_repository) { raise 'Fail in tests' }
end end
context 'hashed storage' do context 'hashed storage' do
......
...@@ -8,7 +8,6 @@ describe Gitlab::Shell do ...@@ -8,7 +8,6 @@ describe Gitlab::Shell do
let(:repository) { project.repository } let(:repository) { project.repository }
let(:gitlab_shell) { described_class.new } let(:gitlab_shell) { described_class.new }
it { is_expected.to respond_to :create_repository }
it { is_expected.to respond_to :remove_repository } it { is_expected.to respond_to :remove_repository }
it { is_expected.to respond_to :fork_repository } it { is_expected.to respond_to :fork_repository }
...@@ -55,30 +54,6 @@ describe Gitlab::Shell do ...@@ -55,30 +54,6 @@ describe Gitlab::Shell do
allow(Gitlab.config.gitlab_shell).to receive(:git_timeout).and_return(800) allow(Gitlab.config.gitlab_shell).to receive(:git_timeout).and_return(800)
end end
describe '#create_repository' do
let(:repository_storage) { 'default' }
let(:repository_storage_path) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
Gitlab.config.repositories.storages[repository_storage].legacy_disk_path
end
end
let(:repo_name) { 'project/path' }
let(:created_path) { File.join(repository_storage_path, repo_name + '.git') }
after do
FileUtils.rm_rf(created_path)
end
it 'returns false when the command fails' do
FileUtils.mkdir_p(File.dirname(created_path))
# This file will block the creation of the repo's .git directory. That
# should cause #create_repository to fail.
FileUtils.touch(created_path)
expect(gitlab_shell.create_repository(repository_storage, repo_name, repo_name)).to be_falsy
end
end
describe '#remove_repository' do describe '#remove_repository' do
let!(:project) { create(:project, :repository, :legacy_storage) } let!(:project) { create(:project, :repository, :legacy_storage) }
let(:disk_path) { "#{project.disk_path}.git" } let(:disk_path) { "#{project.disk_path}.git" }
......
...@@ -1921,30 +1921,15 @@ describe Project do ...@@ -1921,30 +1921,15 @@ describe Project do
describe '#create_repository' do describe '#create_repository' do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:shell) { Gitlab::Shell.new }
before do
allow(project).to receive(:gitlab_shell).and_return(shell)
end
context 'using a regular repository' do context 'using a regular repository' do
it 'creates the repository' do it 'creates the repository' do
expect(shell).to receive(:create_repository) expect(project.repository).to receive(:create_repository)
.with(project.repository_storage, project.disk_path, project.full_path)
.and_return(true)
expect(project.repository).to receive(:after_create)
expect(project.create_repository).to eq(true) expect(project.create_repository).to eq(true)
end end
it 'adds an error if the repository could not be created' do it 'adds an error if the repository could not be created' do
expect(shell).to receive(:create_repository) expect(project.repository).to receive(:create_repository) { raise 'Fail in test' }
.with(project.repository_storage, project.disk_path, project.full_path)
.and_return(false)
expect(project.repository).not_to receive(:after_create)
expect(project.create_repository).to eq(false) expect(project.create_repository).to eq(false)
expect(project.errors).not_to be_empty expect(project.errors).not_to be_empty
end end
...@@ -1953,7 +1938,7 @@ describe Project do ...@@ -1953,7 +1938,7 @@ describe Project do
context 'using a forked repository' do context 'using a forked repository' do
it 'does nothing' do it 'does nothing' do
expect(project).to receive(:forked?).and_return(true) expect(project).to receive(:forked?).and_return(true)
expect(shell).not_to receive(:create_repository) expect(project.repository).not_to receive(:create_repository)
project.create_repository project.create_repository
end end
...@@ -1962,28 +1947,16 @@ describe Project do ...@@ -1962,28 +1947,16 @@ describe Project do
describe '#ensure_repository' do describe '#ensure_repository' do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:shell) { Gitlab::Shell.new }
before do
allow(project).to receive(:gitlab_shell).and_return(shell)
end
it 'creates the repository if it not exist' do it 'creates the repository if it not exist' do
allow(project).to receive(:repository_exists?) allow(project).to receive(:repository_exists?).and_return(false)
.and_return(false)
allow(shell).to receive(:create_repository)
.with(project.repository_storage, project.disk_path, project.full_path)
.and_return(true)
expect(project).to receive(:create_repository).with(force: true) expect(project).to receive(:create_repository).with(force: true)
project.ensure_repository project.ensure_repository
end end
it 'does not create the repository if it exists' do it 'does not create the repository if it exists' do
allow(project).to receive(:repository_exists?) allow(project).to receive(:repository_exists?).and_return(true)
.and_return(true)
expect(project).not_to receive(:create_repository) expect(project).not_to receive(:create_repository)
...@@ -1992,13 +1965,8 @@ describe Project do ...@@ -1992,13 +1965,8 @@ describe Project do
it 'creates the repository if it is a fork' do it 'creates the repository if it is a fork' do
expect(project).to receive(:forked?).and_return(true) expect(project).to receive(:forked?).and_return(true)
expect(project).to receive(:repository_exists?).and_return(false)
allow(project).to receive(:repository_exists?) expect(project.repository).to receive(:create_repository) { true }
.and_return(false)
expect(shell).to receive(:create_repository)
.with(project.repository_storage, project.disk_path, project.full_path)
.and_return(true)
project.ensure_repository project.ensure_repository
end end
......
...@@ -97,9 +97,7 @@ describe ProjectWiki do ...@@ -97,9 +97,7 @@ describe ProjectWiki do
it "raises CouldNotCreateWikiError if it can't create the wiki repository" do it "raises CouldNotCreateWikiError if it can't create the wiki repository" do
# Create a fresh project which will not have a wiki # Create a fresh project which will not have a wiki
project_wiki = described_class.new(create(:project), user) project_wiki = described_class.new(create(:project), user)
gitlab_shell = double(:gitlab_shell) expect(project_wiki.repository).to receive(:create_if_not_exists) { false }
allow(gitlab_shell).to receive(:create_wiki_repository)
allow(project_wiki).to receive(:gitlab_shell).and_return(gitlab_shell)
expect { project_wiki.send(:wiki) }.to raise_exception(ProjectWiki::CouldNotCreateWikiError) expect { project_wiki.send(:wiki) }.to raise_exception(ProjectWiki::CouldNotCreateWikiError)
end end
...@@ -416,26 +414,12 @@ describe ProjectWiki do ...@@ -416,26 +414,12 @@ describe ProjectWiki do
end end
end end
describe '#create_repo!' do
let(:project) { create(:project) }
it 'creates a repository' do
expect(raw_repository.exists?).to eq(false)
expect(subject.repository).to receive(:after_create)
subject.send(:create_repo!, raw_repository)
expect(raw_repository.exists?).to eq(true)
end
end
describe '#ensure_repository' do describe '#ensure_repository' do
let(:project) { create(:project) } let(:project) { create(:project) }
it 'creates the repository if it not exist' do it 'creates the repository if it not exist' do
expect(raw_repository.exists?).to eq(false) expect(raw_repository.exists?).to eq(false)
expect(subject).to receive(:create_repo!).and_call_original
subject.ensure_repository subject.ensure_repository
expect(raw_repository.exists?).to eq(true) expect(raw_repository.exists?).to eq(true)
......
...@@ -312,6 +312,8 @@ describe Projects::ForkService do ...@@ -312,6 +312,8 @@ describe Projects::ForkService do
# Stub everything required to move a project to a Gitaly shard that does not exist # Stub everything required to move a project to a Gitaly shard that does not exist
stub_storage_settings('test_second_storage' => { 'path' => TestEnv::SECOND_STORAGE_PATH }) stub_storage_settings('test_second_storage' => { 'path' => TestEnv::SECOND_STORAGE_PATH })
allow_any_instance_of(Gitlab::Git::Repository).to receive(:create_repository)
.and_return(true)
allow_any_instance_of(Gitlab::Git::Repository).to receive(:replicate) allow_any_instance_of(Gitlab::Git::Repository).to receive(:replicate)
allow_any_instance_of(Gitlab::Git::Repository).to receive(:checksum) allow_any_instance_of(Gitlab::Git::Repository).to receive(:checksum)
.and_return(::Gitlab::Git::BLANK_SHA) .and_return(::Gitlab::Git::BLANK_SHA)
......
...@@ -32,6 +32,8 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -32,6 +32,8 @@ describe Projects::UpdateRepositoryStorageService do
project.repository.path_to_repo project.repository.path_to_repo
end end
expect(project_repository_double).to receive(:create_repository)
.and_return(true)
expect(project_repository_double).to receive(:replicate) expect(project_repository_double).to receive(:replicate)
.with(project.repository.raw) .with(project.repository.raw)
expect(project_repository_double).to receive(:checksum) expect(project_repository_double).to receive(:checksum)
...@@ -58,6 +60,8 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -58,6 +60,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(project_repository_double).to receive(:create_repository)
.and_return(true)
expect(project_repository_double).to receive(:replicate) expect(project_repository_double).to receive(:replicate)
.with(project.repository.raw) .with(project.repository.raw)
.and_raise(Gitlab::Git::CommandError) .and_raise(Gitlab::Git::CommandError)
...@@ -73,6 +77,8 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -73,6 +77,8 @@ describe Projects::UpdateRepositoryStorageService do
context 'when the checksum does not match' do context 'when the checksum does not match' 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(project_repository_double).to receive(:create_repository)
.and_return(true)
expect(project_repository_double).to receive(:replicate) expect(project_repository_double).to receive(:replicate)
.with(project.repository.raw) .with(project.repository.raw)
expect(project_repository_double).to receive(:checksum) expect(project_repository_double).to receive(:checksum)
...@@ -91,6 +97,8 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -91,6 +97,8 @@ describe Projects::UpdateRepositoryStorageService do
let!(:pool) { create(:pool_repository, :ready, source_project: project) } let!(:pool) { create(:pool_repository, :ready, source_project: project) }
it 'leaves the pool' do it 'leaves the pool' do
expect(project_repository_double).to receive(:create_repository)
.and_return(true)
expect(project_repository_double).to receive(:replicate) expect(project_repository_double).to receive(:replicate)
.with(project.repository.raw) .with(project.repository.raw)
expect(project_repository_double).to receive(:checksum) expect(project_repository_double).to receive(:checksum)
......
...@@ -22,11 +22,15 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| ...@@ -22,11 +22,15 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type|
context 'when the move succeeds', :clean_gitlab_redis_shared_state do context 'when the move succeeds', :clean_gitlab_redis_shared_state do
before do before do
allow(project_repository_double).to receive(:create_repository)
.and_return(true)
allow(project_repository_double).to receive(:replicate) allow(project_repository_double).to receive(:replicate)
.with(project.repository.raw) .with(project.repository.raw)
allow(project_repository_double).to receive(:checksum) allow(project_repository_double).to receive(:checksum)
.and_return(project_repository_checksum) .and_return(project_repository_checksum)
allow(repository_double).to receive(:create_repository)
.and_return(true)
allow(repository_double).to receive(:replicate) allow(repository_double).to receive(:replicate)
.with(repository.raw) .with(repository.raw)
allow(repository_double).to receive(:checksum) allow(repository_double).to receive(:checksum)
...@@ -90,11 +94,15 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| ...@@ -90,11 +94,15 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type|
context "when the move of the #{repository_type} repository fails" do context "when the move of the #{repository_type} repository 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
allow(project_repository_double).to receive(:create_repository)
.and_return(true)
allow(project_repository_double).to receive(:replicate) allow(project_repository_double).to receive(:replicate)
.with(project.repository.raw) .with(project.repository.raw)
allow(project_repository_double).to receive(:checksum) allow(project_repository_double).to receive(:checksum)
.and_return(project_repository_checksum) .and_return(project_repository_checksum)
allow(repository_double).to receive(:create_repository)
.and_return(true)
allow(repository_double).to receive(:replicate) allow(repository_double).to receive(:replicate)
.with(repository.raw) .with(repository.raw)
.and_raise(Gitlab::Git::CommandError) .and_raise(Gitlab::Git::CommandError)
...@@ -111,11 +119,15 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| ...@@ -111,11 +119,15 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type|
context "when the checksum of the #{repository_type} repository does not match" do context "when the checksum of the #{repository_type} repository does not match" 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
allow(project_repository_double).to receive(:create_repository)
.and_return(true)
allow(project_repository_double).to receive(:replicate) allow(project_repository_double).to receive(:replicate)
.with(project.repository.raw) .with(project.repository.raw)
allow(project_repository_double).to receive(:checksum) allow(project_repository_double).to receive(:checksum)
.and_return(project_repository_checksum) .and_return(project_repository_checksum)
allow(repository_double).to receive(:create_repository)
.and_return(true)
allow(repository_double).to receive(:replicate) allow(repository_double).to receive(:replicate)
.with(repository.raw) .with(repository.raw)
allow(repository_double).to receive(:checksum) allow(repository_double).to receive(:checksum)
......
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