Commit 74e17ed9 authored by Douwe Maan's avatar Douwe Maan

Merge branch '20302-forking-a-project-from-one-storage-to-another-fails' into 'master'

Fix a bug where forking a project from a repository storage to another would fail

## What does this MR do?

Fix a bug where forking a project from a repository storage to another would fail.

## Are there points in the code the reviewer needs to double check?

No

## Why was this MR needed?

If you have a project in storage_a, change the default storage to storage_b, and attempt to fork said project, the import will fail.

## What are the relevant issue numbers?

Closes #20302 

- [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added
- [ ] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
- [ ] API support added
- Tests
  - [x] Added for this feature/bug
  - [ ] All builds are passing
- [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [ ] Branch has no merge conflicts with `master` (if you do - rebase it please)
- [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
- [ ] Merge https://gitlab.com/gitlab-org/gitlab-shell/merge_requests/75, publish the tag, and update `GITLAB_SHELL_VERSION`


See merge request !5509
parents a9399469 1dcfb1d3
...@@ -22,6 +22,7 @@ v 8.10.2 (unreleased) ...@@ -22,6 +22,7 @@ v 8.10.2 (unreleased)
- Fix backup restore. !5459 - Fix backup restore. !5459
- Rescue Rugged::OSError (lock exists) when creating references. !5497 - Rescue Rugged::OSError (lock exists) when creating references. !5497
- Disable MySQL foreign key checks before dropping all tables. !5472 - Disable MySQL foreign key checks before dropping all tables. !5472
- Fix a bug where forking a project from a repository storage to another would fail
- Show release notes in tags list - Show release notes in tags list
- Use project ID in repository cache to prevent stale data from persisting across projects. !5460 - Use project ID in repository cache to prevent stale data from persisting across projects. !5460
- Ensure relative paths for video are rewritten as we do for images. !5474 - Ensure relative paths for video are rewritten as we do for images. !5474
......
...@@ -451,7 +451,9 @@ class Project < ActiveRecord::Base ...@@ -451,7 +451,9 @@ class Project < ActiveRecord::Base
def add_import_job def add_import_job
if forked? if forked?
job_id = RepositoryForkWorker.perform_async(self.id, forked_from_project.path_with_namespace, self.namespace.path) job_id = RepositoryForkWorker.perform_async(id, forked_from_project.repository_storage_path,
forked_from_project.path_with_namespace,
self.namespace.path)
else else
job_id = RepositoryImportWorker.perform_async(self.id) job_id = RepositoryImportWorker.perform_async(self.id)
end end
......
...@@ -4,7 +4,7 @@ class RepositoryForkWorker ...@@ -4,7 +4,7 @@ class RepositoryForkWorker
sidekiq_options queue: :gitlab_shell sidekiq_options queue: :gitlab_shell
def perform(project_id, source_path, target_path) def perform(project_id, forked_from_repository_storage_path, source_path, target_path)
project = Project.find_by_id(project_id) project = Project.find_by_id(project_id)
unless project.present? unless project.present?
...@@ -12,7 +12,8 @@ class RepositoryForkWorker ...@@ -12,7 +12,8 @@ class RepositoryForkWorker
return return
end end
result = gitlab_shell.fork_repository(project.repository_storage_path, source_path, target_path) result = gitlab_shell.fork_repository(forked_from_repository_storage_path, source_path,
project.repository_storage_path, target_path)
unless result unless result
logger.error("Unable to fork project #{project_id} for repository #{source_path} -> #{target_path}") logger.error("Unable to fork project #{project_id} for repository #{source_path} -> #{target_path}")
project.mark_import_as_failed('The project could not be forked.') project.mark_import_as_failed('The project could not be forked.')
......
...@@ -60,16 +60,18 @@ module Gitlab ...@@ -60,16 +60,18 @@ module Gitlab
end end
# Fork repository to new namespace # Fork repository to new namespace
# storage - project's storage path # forked_from_storage - forked-from project's storage path
# path - project path with namespace # path - project path with namespace
# forked_to_storage - forked-to project's storage path
# fork_namespace - namespace for forked project # fork_namespace - namespace for forked project
# #
# Ex. # Ex.
# fork_repository("/path/to/storage", "gitlab/gitlab-ci", "randx") # fork_repository("/path/to/forked_from/storage", "gitlab/gitlab-ci", "/path/to/forked_to/storage", "randx")
# #
def fork_repository(storage, path, fork_namespace) def fork_repository(forked_from_storage, path, forked_to_storage, fork_namespace)
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'fork-project', Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'fork-project',
storage, "#{path}.git", fork_namespace]) forked_from_storage, "#{path}.git", forked_to_storage,
fork_namespace])
end end
# Remove repository from file system # Remove repository from file system
......
...@@ -1244,6 +1244,32 @@ describe Project, models: true do ...@@ -1244,6 +1244,32 @@ describe Project, models: true do
end end
end end
describe '#add_import_job' do
context 'forked' do
let(:forked_project_link) { create(:forked_project_link) }
let(:forked_from_project) { forked_project_link.forked_from_project }
let(:project) { forked_project_link.forked_to_project }
it 'schedules a RepositoryForkWorker job' do
expect(RepositoryForkWorker).to receive(:perform_async).
with(project.id, forked_from_project.repository_storage_path,
forked_from_project.path_with_namespace, project.namespace.path)
project.add_import_job
end
end
context 'not forked' do
let(:project) { create(:project) }
it 'schedules a RepositoryImportWorker job' do
expect(RepositoryImportWorker).to receive(:perform_async).with(project.id)
project.add_import_job
end
end
end
describe '.where_paths_in' do describe '.where_paths_in' do
context 'without any paths' do context 'without any paths' do
it 'returns an empty relation' do it 'returns an empty relation' do
......
...@@ -14,21 +14,24 @@ describe RepositoryForkWorker do ...@@ -14,21 +14,24 @@ describe RepositoryForkWorker do
describe "#perform" do describe "#perform" do
it "creates a new repository from a fork" do it "creates a new repository from a fork" do
expect(shell).to receive(:fork_repository).with( expect(shell).to receive(:fork_repository).with(
project.repository_storage_path, '/test/path',
project.path_with_namespace, project.path_with_namespace,
project.repository_storage_path,
fork_project.namespace.path fork_project.namespace.path
).and_return(true) ).and_return(true)
subject.perform( subject.perform(
project.id, project.id,
'/test/path',
project.path_with_namespace, project.path_with_namespace,
fork_project.namespace.path) fork_project.namespace.path)
end end
it 'flushes various caches' do it 'flushes various caches' do
expect(shell).to receive(:fork_repository).with( expect(shell).to receive(:fork_repository).with(
project.repository_storage_path, '/test/path',
project.path_with_namespace, project.path_with_namespace,
project.repository_storage_path,
fork_project.namespace.path fork_project.namespace.path
).and_return(true) ).and_return(true)
...@@ -38,7 +41,7 @@ describe RepositoryForkWorker do ...@@ -38,7 +41,7 @@ describe RepositoryForkWorker do
expect_any_instance_of(Repository).to receive(:expire_exists_cache). expect_any_instance_of(Repository).to receive(:expire_exists_cache).
and_call_original and_call_original
subject.perform(project.id, project.path_with_namespace, subject.perform(project.id, '/test/path', project.path_with_namespace,
fork_project.namespace.path) fork_project.namespace.path)
end end
...@@ -49,6 +52,7 @@ describe RepositoryForkWorker do ...@@ -49,6 +52,7 @@ describe RepositoryForkWorker do
subject.perform( subject.perform(
project.id, project.id,
'/test/path',
project.path_with_namespace, project.path_with_namespace,
fork_project.namespace.path) fork_project.namespace.path)
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