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 ...@@ -9,6 +9,7 @@ v 7.4.0
- Do not delete tmp/repositories itself during clean-up, only its contents - Do not delete tmp/repositories itself during clean-up, only its contents
- Support for backup uploads to remote storage - Support for backup uploads to remote storage
- Prevent notes polling when there are not notes - 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: Add support for forking a project via the API (Bernhard Kaindl)
- API: filter project issues by milestone (Julien Bianchi) - API: filter project issues by milestone (Julien Bianchi)
- Fail harder in the backup script - Fail harder in the backup script
......
...@@ -2,11 +2,9 @@ module Projects ...@@ -2,11 +2,9 @@ module Projects
class ForkService < BaseService class ForkService < BaseService
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
def initialize(project, user)
@from_project, @current_user = project, user
end
def execute def execute
@from_project = @project
project_params = { project_params = {
visibility_level: @from_project.visibility_level, visibility_level: @from_project.visibility_level,
description: @from_project.description, description: @from_project.description,
...@@ -15,8 +13,15 @@ module Projects ...@@ -15,8 +13,15 @@ module Projects
project = Project.new(project_params) project = Project.new(project_params)
project.name = @from_project.name project.name = @from_project.name
project.path = @from_project.path project.path = @from_project.path
project.namespace = current_user.namespace project.namespace = @current_user.namespace
project.creator = current_user 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 # 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 # as this can have the side effect of deleting a repo attached to an existing
...@@ -27,7 +32,7 @@ module Projects ...@@ -27,7 +32,7 @@ module Projects
#First save the DB entries as they can be rolled back if the repo fork fails #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) project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id)
if project.save if project.save
project.team << [current_user, :master] project.team << [@current_user, :master]
end end
#Now fork the repo #Now fork the repo
unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path) unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path)
......
...@@ -42,10 +42,54 @@ describe Projects::ForkService do ...@@ -42,10 +42,54 @@ describe Projects::ForkService do
end end
end end
def fork_project(from_project, user, fork_success = true) describe :fork_to_namespace do
context = Projects::ForkService.new(from_project, user) before do
shell = double("gitlab_shell") @group_owner = create(:user)
shell.stub(fork_repository: fork_success) @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.stub(gitlab_shell: shell)
context.execute context.execute
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