Skip to content

Commit 15ef5d6

Browse files
author
Robert Speicher
committed
Merge branch 'feature/migrate-import-repository-to-gitaly' into 'master'
Migrate importing repository to Gitaly Closes gitaly#907 See merge request gitlab-org/gitlab-ce!16431
2 parents 5c51cbc + 49d6ed9 commit 15ef5d6

File tree

5 files changed

+96
-45
lines changed

5 files changed

+96
-45
lines changed

Gemfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ group :ed25519 do
403403
end
404404

405405
# Gitaly GRPC client
406-
gem 'gitaly-proto', '~> 0.69.0', require: 'gitaly'
406+
gem 'gitaly-proto', '~> 0.73.0', require: 'gitaly'
407407

408408
gem 'toml-rb', '~> 0.3.15', require: false
409409

Gemfile.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ GEM
284284
po_to_json (>= 1.0.0)
285285
rails (>= 3.2.0)
286286
gherkin-ruby (0.3.2)
287-
gitaly-proto (0.69.0)
287+
gitaly-proto (0.73.0)
288288
google-protobuf (~> 3.1)
289289
grpc (~> 1.0)
290290
github-linguist (4.7.6)
@@ -1054,7 +1054,7 @@ DEPENDENCIES
10541054
gettext (~> 3.2.2)
10551055
gettext_i18n_rails (~> 1.8.0)
10561056
gettext_i18n_rails_js (~> 1.2.0)
1057-
gitaly-proto (~> 0.69.0)
1057+
gitaly-proto (~> 0.73.0)
10581058
github-linguist (~> 4.7.0)
10591059
gitlab-flowdock-git-hook (~> 1.0.1)
10601060
gitlab-markup (~> 1.6.2)

lib/gitlab/git/gitlab_projects.rb

+42-22
Original file line numberDiff line numberDiff line change
@@ -44,29 +44,13 @@ def output
4444
# Import project via git clone --bare
4545
# URL must be publicly cloneable
4646
def import_project(source, timeout)
47-
# Skip import if repo already exists
48-
return false if File.exist?(repository_absolute_path)
49-
50-
masked_source = mask_password_in_url(source)
51-
52-
logger.info "Importing project from <#{masked_source}> to <#{repository_absolute_path}>."
53-
cmd = %W(git clone --bare -- #{source} #{repository_absolute_path})
54-
55-
success = run_with_timeout(cmd, timeout, nil)
56-
57-
unless success
58-
logger.error("Importing project from <#{masked_source}> to <#{repository_absolute_path}> failed.")
59-
FileUtils.rm_rf(repository_absolute_path)
60-
return false
47+
Gitlab::GitalyClient.migrate(:import_repository) do |is_enabled|
48+
if is_enabled
49+
gitaly_import_repository(source)
50+
else
51+
git_import_repository(source, timeout)
52+
end
6153
end
62-
63-
Gitlab::Git::Repository.create_hooks(repository_absolute_path, global_hooks_path)
64-
65-
# The project was imported successfully.
66-
# Remove the origin URL since it may contain password.
67-
remove_origin_in_repo
68-
69-
true
7054
end
7155

7256
def fork_repository(new_shard_path, new_repository_relative_path)
@@ -231,6 +215,42 @@ def shard_name_from_shard_path(shard_path)
231215
raise(ShardNameNotFoundError, "no shard found for path '#{shard_path}'")
232216
end
233217

218+
def git_import_repository(source, timeout)
219+
# Skip import if repo already exists
220+
return false if File.exist?(repository_absolute_path)
221+
222+
masked_source = mask_password_in_url(source)
223+
224+
logger.info "Importing project from <#{masked_source}> to <#{repository_absolute_path}>."
225+
cmd = %W(git clone --bare -- #{source} #{repository_absolute_path})
226+
227+
success = run_with_timeout(cmd, timeout, nil)
228+
229+
unless success
230+
logger.error("Importing project from <#{masked_source}> to <#{repository_absolute_path}> failed.")
231+
FileUtils.rm_rf(repository_absolute_path)
232+
return false
233+
end
234+
235+
Gitlab::Git::Repository.create_hooks(repository_absolute_path, global_hooks_path)
236+
237+
# The project was imported successfully.
238+
# Remove the origin URL since it may contain password.
239+
remove_origin_in_repo
240+
241+
true
242+
end
243+
244+
def gitaly_import_repository(source)
245+
raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil)
246+
247+
Gitlab::GitalyClient::RepositoryService.new(raw_repository).import_repository(source)
248+
true
249+
rescue GRPC::BadStatus => e
250+
@output << e.message
251+
false
252+
end
253+
234254
def git_fork_repository(new_shard_path, new_repository_relative_path)
235255
from_path = repository_absolute_path
236256
to_path = File.join(new_shard_path, new_repository_relative_path)

lib/gitlab/gitaly_client/repository_service.rb

+15
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,21 @@ def fork_repository(source_repository)
100100
)
101101
end
102102

103+
def import_repository(source)
104+
request = Gitaly::CreateRepositoryFromURLRequest.new(
105+
repository: @gitaly_repo,
106+
url: source
107+
)
108+
109+
GitalyClient.call(
110+
@storage,
111+
:repository_service,
112+
:create_repository_from_url,
113+
request,
114+
timeout: GitalyClient.default_timeout
115+
)
116+
end
117+
103118
def rebase_in_progress?(rebase_id)
104119
request = Gitaly::IsRebaseInProgressRequest.new(
105120
repository: @gitaly_repo,

spec/lib/gitlab/git/gitlab_projects_spec.rb

+36-20
Original file line numberDiff line numberDiff line change
@@ -158,39 +158,55 @@ def stub_tempfile(name, filename, opts = {})
158158

159159
subject { gl_projects.import_project(import_url, timeout) }
160160

161-
context 'success import' do
162-
it 'imports a repo' do
163-
expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
161+
shared_examples 'importing repository' do
162+
context 'success import' do
163+
it 'imports a repo' do
164+
expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
164165

165-
message = "Importing project from <#{import_url}> to <#{tmp_repo_path}>."
166-
expect(logger).to receive(:info).with(message)
166+
is_expected.to be_truthy
167167

168-
is_expected.to be_truthy
168+
expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_truthy
169+
end
170+
end
169171

170-
expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_truthy
172+
context 'already exists' do
173+
it "doesn't import" do
174+
FileUtils.mkdir_p(tmp_repo_path)
175+
176+
is_expected.to be_falsy
177+
end
171178
end
172179
end
173180

174-
context 'already exists' do
175-
it "doesn't import" do
176-
FileUtils.mkdir_p(tmp_repo_path)
181+
context 'when Gitaly import_repository feature is enabled' do
182+
it_behaves_like 'importing repository'
183+
end
184+
185+
context 'when Gitaly import_repository feature is disabled', :disable_gitaly do
186+
describe 'logging' do
187+
it 'imports a repo' do
188+
message = "Importing project from <#{import_url}> to <#{tmp_repo_path}>."
189+
expect(logger).to receive(:info).with(message)
177190

178-
is_expected.to be_falsy
191+
subject
192+
end
179193
end
180-
end
181194

182-
context 'timeout' do
183-
it 'does not import a repo' do
184-
stub_spawn_timeout(cmd, timeout, nil)
195+
context 'timeout' do
196+
it 'does not import a repo' do
197+
stub_spawn_timeout(cmd, timeout, nil)
185198

186-
message = "Importing project from <#{import_url}> to <#{tmp_repo_path}> failed."
187-
expect(logger).to receive(:error).with(message)
199+
message = "Importing project from <#{import_url}> to <#{tmp_repo_path}> failed."
200+
expect(logger).to receive(:error).with(message)
188201

189-
is_expected.to be_falsy
202+
is_expected.to be_falsy
190203

191-
expect(gl_projects.output).to eq("Timed out\n")
192-
expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
204+
expect(gl_projects.output).to eq("Timed out\n")
205+
expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
206+
end
193207
end
208+
209+
it_behaves_like 'importing repository'
194210
end
195211
end
196212

0 commit comments

Comments
 (0)