Commit e254014d authored by Douwe Maan's avatar Douwe Maan

Merge branch '34533-speed-up-project-creation' into 'master'

Speed up project creation by inlining repository creation

Closes #34533

See merge request !13529
parents fdd03d29 5fc87138
...@@ -474,7 +474,6 @@ db:rollback-mysql: ...@@ -474,7 +474,6 @@ db:rollback-mysql:
variables: variables:
SIZE: "1" SIZE: "1"
SETUP_DB: "false" SETUP_DB: "false"
RAILS_ENV: "development"
script: script:
- git clone https://gitlab.com/gitlab-org/gitlab-test.git - git clone https://gitlab.com/gitlab-org/gitlab-test.git
/home/git/repositories/gitlab-org/gitlab-test.git /home/git/repositories/gitlab-org/gitlab-test.git
......
...@@ -18,6 +18,28 @@ module Gitlab ...@@ -18,6 +18,28 @@ module Gitlab
InvalidBlobName = Class.new(StandardError) InvalidBlobName = Class.new(StandardError)
InvalidRef = Class.new(StandardError) InvalidRef = Class.new(StandardError)
class << self
# Unlike `new`, `create` takes the storage path, not the storage name
def create(storage_path, name, bare: true, symlink_hooks_to: nil)
repo_path = File.join(storage_path, name)
repo_path += '.git' unless repo_path.end_with?('.git')
FileUtils.mkdir_p(repo_path, mode: 0770)
# Equivalent to `git --git-path=#{repo_path} init [--bare]`
repo = Rugged::Repository.init_at(repo_path, bare)
repo.close
if symlink_hooks_to.present?
hooks_path = File.join(repo_path, 'hooks')
FileUtils.rm_rf(hooks_path)
FileUtils.ln_s(symlink_hooks_to, hooks_path)
end
true
end
end
# Full path to repo # Full path to repo
attr_reader :path attr_reader :path
......
...@@ -73,8 +73,10 @@ module Gitlab ...@@ -73,8 +73,10 @@ module Gitlab
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387 # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def add_repository(storage, name) def add_repository(storage, name)
gitlab_shell_fast_execute([gitlab_shell_projects_path, Gitlab::Git::Repository.create(storage, name, bare: true, symlink_hooks_to: gitlab_shell_hooks_path)
'add-project', storage, "#{name}.git"]) rescue => err
Rails.logger.error("Failed to add repository #{storage}/#{name}: #{err}")
false
end end
# Import repository # Import repository
...@@ -273,7 +275,11 @@ module Gitlab ...@@ -273,7 +275,11 @@ module Gitlab
protected protected
def gitlab_shell_path def gitlab_shell_path
Gitlab.config.gitlab_shell.path File.expand_path(Gitlab.config.gitlab_shell.path)
end
def gitlab_shell_hooks_path
File.expand_path(Gitlab.config.gitlab_shell.hooks_path)
end end
def gitlab_shell_user_home def gitlab_shell_user_home
......
...@@ -94,28 +94,41 @@ describe Gitlab::Shell do ...@@ -94,28 +94,41 @@ describe Gitlab::Shell do
end end
describe 'projects commands' do describe 'projects commands' do
let(:projects_path) { 'tmp/tests/shell-projects-test/bin/gitlab-projects' } let(:gitlab_shell_path) { File.expand_path('tmp/tests/gitlab-shell') }
let(:projects_path) { File.join(gitlab_shell_path, 'bin/gitlab-projects') }
let(:gitlab_shell_hooks_path) { File.join(gitlab_shell_path, 'hooks') }
before do before do
allow(Gitlab.config.gitlab_shell).to receive(:path).and_return('tmp/tests/shell-projects-test') allow(Gitlab.config.gitlab_shell).to receive(:path).and_return(gitlab_shell_path)
allow(Gitlab.config.gitlab_shell).to receive(:hooks_path).and_return(gitlab_shell_hooks_path)
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 '#add_repository' do describe '#add_repository' do
it 'returns true when the command succeeds' do it 'creates a repository' do
expect(Gitlab::Popen).to receive(:popen) created_path = File.join(TestEnv.repos_path, 'project', 'path.git')
.with([projects_path, 'add-project', 'current/storage', 'project/path.git'], hooks_path = File.join(created_path, 'hooks')
nil, popen_vars).and_return([nil, 0])
begin
result = gitlab_shell.add_repository(TestEnv.repos_path, 'project/path')
expect(gitlab_shell.add_repository('current/storage', 'project/path')).to be true repo_stat = File.stat(created_path) rescue nil
hooks_stat = File.lstat(hooks_path) rescue nil
hooks_dir = File.realpath(hooks_path)
ensure
FileUtils.rm_rf(created_path)
end
expect(result).to be_truthy
expect(repo_stat.mode & 0o777).to eq(0o770)
expect(hooks_stat.symlink?).to be_truthy
expect(hooks_dir).to eq(gitlab_shell_hooks_path)
end end
it 'returns false when the command fails' do it 'returns false when the command fails' do
expect(Gitlab::Popen).to receive(:popen) expect(FileUtils).to receive(:mkdir_p).and_raise(Errno::EEXIST)
.with([projects_path, 'add-project', 'current/storage', 'project/path.git'],
nil, popen_vars).and_return(["error", 1])
expect(gitlab_shell.add_repository('current/storage', 'project/path')).to be false expect(gitlab_shell.add_repository('current/storage', 'project/path')).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