diff --git a/CHANGELOG b/CHANGELOG index 432d251dfc6b953e04b29edae9cd9f11ea355334..6266161a3a85a1a79670aca35be0992c874790c8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,6 +21,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 diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index 944880fa15e85084780c290b929924d3f8b6085f..e4604e3afd0dd7b7ebf8a8064658da22c365f6ef 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -3.2.0 +3.2.1 diff --git a/app/models/project.rb b/app/models/project.rb index 023b1dc37254bf7a32bc07e935856c532e3f7b86..1616175709f840444029abe9b2a9708d1fdba8ce 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -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 diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index f7604e48f8320778277c4140d3d10629502f20a4..d69d6037053d3da556ab1b80fde4a75a529706b9 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -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.') diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index 34e0143a82ee793bce189617e36fd9cce4ff4306..839a4fa30d5de358fc17b7f1ac53ec712a424f02 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -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 diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 9b0172884886046d594b74bf3605c07f1dc561a2..c884bb31199302e93b0d6195a5c7139f6da5250a 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -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 diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb index 5f762282b5ea7ddae6a61adc14e006fe1c8780e3..60605460adbebde182e448888bf0a1ee41f09651 100644 --- a/spec/workers/repository_fork_worker_spec.rb +++ b/spec/workers/repository_fork_worker_spec.rb @@ -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