Commit c44764f5 authored by Bernhard Kaindl's avatar Bernhard Kaindl

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.
parent f74dba8c
......@@ -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
......
......@@ -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)
......
......@@ -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
......
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