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)
- Fix backup restore. !5459
- Rescue Rugged::OSError (lock exists) when creating references. !5497
- 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
- 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
......
......@@ -451,7 +451,9 @@ class Project < ActiveRecord::Base
def add_import_job
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
job_id = RepositoryImportWorker.perform_async(self.id)
end
......
......@@ -4,7 +4,7 @@ class RepositoryForkWorker
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)
unless project.present?
......@@ -12,7 +12,8 @@ class RepositoryForkWorker
return
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
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.')
......
......@@ -60,16 +60,18 @@ module Gitlab
end
# Fork repository to new namespace
# storage - project's storage path
# forked_from_storage - forked-from project's storage path
# path - project path with namespace
# forked_to_storage - forked-to project's storage path
# fork_namespace - namespace for forked project
#
# 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',
storage, "#{path}.git", fork_namespace])
forked_from_storage, "#{path}.git", forked_to_storage,
fork_namespace])
end
# Remove repository from file system
......
......@@ -1244,6 +1244,32 @@ describe Project, models: true do
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
context 'without any paths' do
it 'returns an empty relation' do
......
......@@ -14,21 +14,24 @@ describe RepositoryForkWorker do
describe "#perform" do
it "creates a new repository from a fork" do
expect(shell).to receive(:fork_repository).with(
project.repository_storage_path,
'/test/path',
project.path_with_namespace,
project.repository_storage_path,
fork_project.namespace.path
).and_return(true)
subject.perform(
project.id,
'/test/path',
project.path_with_namespace,
fork_project.namespace.path)
end
it 'flushes various caches' do
expect(shell).to receive(:fork_repository).with(
project.repository_storage_path,
'/test/path',
project.path_with_namespace,
project.repository_storage_path,
fork_project.namespace.path
).and_return(true)
......@@ -38,7 +41,7 @@ describe RepositoryForkWorker do
expect_any_instance_of(Repository).to receive(:expire_exists_cache).
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)
end
......@@ -49,6 +52,7 @@ describe RepositoryForkWorker do
subject.perform(
project.id,
'/test/path',
project.path_with_namespace,
fork_project.namespace.path)
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