summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Kaindl <bkl@use.startmail.com>2014-10-03 10:12:44 +0200
committerBernhard Kaindl <bkl@use.startmail.com>2014-10-03 11:52:29 +0200
commitc44764f523cea756f1f2efdc4db954f4f19df440 (patch)
tree217fa86abf6bcc5b4d5a301a47d93f92c66f0dae
parentf74dba8c42ba5466945085bca137cc3a3a39ee87 (diff)
downloadgitlab-ce-c44764f523cea756f1f2efdc4db954f4f19df440.tar.gz
Prepare ForkService to support forking projects to given namespaces
Remove overload of BaseService.initialize, so initialize gains params, which is used to pass the namespace (like e.g. in TransferService). The namespace is checked for permission to create projects in it.
-rw-r--r--CHANGELOG1
-rw-r--r--app/services/projects/fork_service.rb19
-rw-r--r--spec/services/projects/fork_service_spec.rb52
3 files changed, 61 insertions, 11 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 0250b4a23c0..410863d3f99 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,7 @@ v 7.4.0
- Do not delete tmp/repositories itself during clean-up, only its contents
- Support for backup uploads to remote storage
- Prevent notes polling when there are not notes
+ - Internal ForkService: Prepare support for fork to a given namespace
- API: Add support for forking a project via the API (Bernhard Kaindl)
- API: filter project issues by milestone (Julien Bianchi)
- Fail harder in the backup script
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index a59311bf942..c4f2d08efe9 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -2,11 +2,9 @@ module Projects
class ForkService < BaseService
include Gitlab::ShellAdapter
- def initialize(project, user)
- @from_project, @current_user = project, user
- end
-
def execute
+ @from_project = @project
+
project_params = {
visibility_level: @from_project.visibility_level,
description: @from_project.description,
@@ -15,8 +13,15 @@ module Projects
project = Project.new(project_params)
project.name = @from_project.name
project.path = @from_project.path
- project.namespace = current_user.namespace
- project.creator = current_user
+ project.namespace = @current_user.namespace
+ if namespace = @params[:namespace]
+ project.namespace = namespace
+ end
+ project.creator = @current_user
+ unless @current_user.can?(:create_projects, project.namespace)
+ project.errors.add(:namespace, 'insufficient access rights')
+ return project
+ end
# If the project cannot save, we do not want to trigger the project destroy
# as this can have the side effect of deleting a repo attached to an existing
@@ -27,7 +32,7 @@ module Projects
#First save the DB entries as they can be rolled back if the repo fork fails
project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id)
if project.save
- project.team << [current_user, :master]
+ project.team << [@current_user, :master]
end
#Now fork the repo
unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path)
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 0edc3a8e807..5c80345c2b3 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -42,10 +42,54 @@ describe Projects::ForkService do
end
end
- def fork_project(from_project, user, fork_success = true)
- context = Projects::ForkService.new(from_project, user)
- shell = double("gitlab_shell")
- shell.stub(fork_repository: fork_success)
+ describe :fork_to_namespace do
+ before do
+ @group_owner = create(:user)
+ @developer = create(:user)
+ @project = create(:project, creator_id: @group_owner.id,
+ star_count: 777,
+ description: 'Wow, such a cool project!')
+ @group = create(:group)
+ @group.add_user(@group_owner, GroupMember::OWNER)
+ @group.add_user(@developer, GroupMember::DEVELOPER)
+ @opts = { namespace: @group }
+ end
+
+ context 'fork project for group' do
+ it 'group owner successfully forks project into the group' do
+ to_project = fork_project(@project, @group_owner, true, @opts)
+ to_project.owner.should == @group
+ to_project.namespace.should == @group
+ to_project.name.should == @project.name
+ to_project.path.should == @project.path
+ to_project.description.should == @project.description
+ to_project.star_count.should be_zero
+ end
+ end
+
+ context 'fork project for group when user not owner' do
+ it 'group developer should fail to fork project into the group' do
+ to_project = fork_project(@project, @developer, true, @opts)
+ to_project.errors[:namespace].should == ['insufficient access rights']
+ end
+ end
+
+ context 'project already exists in group' do
+ it 'should fail due to validation, not transaction failure' do
+ existing_project = create(:project, name: @project.name,
+ namespace: @group)
+ to_project = fork_project(@project, @group_owner, true, @opts)
+ existing_project.persisted?.should be_true
+ to_project.errors[:base].should == ['Invalid fork destination']
+ to_project.errors[:name].should == ['has already been taken']
+ to_project.errors[:path].should == ['has already been taken']
+ end
+ end
+ end
+
+ def fork_project(from_project, user, fork_success = true, params = {})
+ context = Projects::ForkService.new(from_project, user, params)
+ shell = double('gitlab_shell').stub(fork_repository: fork_success)
context.stub(gitlab_shell: shell)
context.execute
end