Commit de8df1be authored by Angus MacArthur's avatar Angus MacArthur

Fix bug for repeated fork requests

When asking to fork a project and a project with the same name
already exists (likely from a previous fork), the recovery from
the fork failure would inadvertantly delete the repo of the
existing destination project.
parent ae33fdf2
...@@ -12,10 +12,15 @@ module Projects ...@@ -12,10 +12,15 @@ module Projects
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 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
# project with the same name and namespace
if project.valid?
begin
Project.transaction do Project.transaction do
#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.creator = current_user
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.users_projects.create(project_access: UsersProject::MASTER, user: current_user) project.users_projects.create(project_access: UsersProject::MASTER, user: current_user)
...@@ -25,13 +30,16 @@ module Projects ...@@ -25,13 +30,16 @@ module Projects
raise "forking failed in gitlab-shell" raise "forking failed in gitlab-shell"
end end
project.ensure_satellite_exists project.ensure_satellite_exists
end end
project
rescue => ex rescue => ex
project.errors.add(:base, "Can't fork project. Please try again later") project.errors.add(:base, "Fork transaction failed.")
project.destroy project.destroy
end end
else
project.errors.add(:base, "Invalid fork destination")
end
project
end end
end
end end
...@@ -3,29 +3,45 @@ require 'spec_helper' ...@@ -3,29 +3,45 @@ require 'spec_helper'
describe Projects::ForkContext do describe Projects::ForkContext do
describe :fork_by_user do describe :fork_by_user do
before do before do
@from_user = create :user @from_namespace = create(:namespace)
@from_project = create(:project, creator_id: @from_user.id) @from_user = create(:user, namespace: @from_namespace )
@to_user = create :user @from_project = create(:project, creator_id: @from_user.id, namespace: @from_namespace)
@to_namespace = create(:namespace)
@to_user = create(:user, namespace: @to_namespace)
end end
context 'fork project' do context 'fork project' do
before do
it "successfully creates project in the user namespace" do
@to_project = fork_project(@from_project, @to_user) @to_project = fork_project(@from_project, @to_user)
end
it { @to_project.owner.should == @to_user } @to_project.owner.should == @to_user
it { @to_project.namespace.should == @to_user.namespace } @to_project.namespace.should == @to_user.namespace
end
end end
context 'fork project failure' do context 'fork project failure' do
before do
#corrupt the project so the attempt to fork will fail it "fails due to transaction failure" do
@from_project = create(:project, path: "empty") # make the mock gitlab-shell fail
@to_project = fork_project(@from_project, @to_user, false) @to_project = fork_project(@from_project, @to_user, false)
@to_project.errors.should_not be_empty
@to_project.errors[:base].should include("Fork transaction failed.")
end end
it {@to_project.errors.should_not be_empty} end
it {@to_project.errors[:base].should include("Can't fork project. Please try again later") }
context 'project already exists' do
it "should fail due to validation, not transaction failure" do
@existing_project = create(:project, creator_id: @to_user.id, name: @from_project.name, namespace: @to_namespace)
@to_project = fork_project(@from_project, @to_user)
@existing_project.persisted?.should be_true
@to_project.errors[:base].should include("Invalid fork destination")
@to_project.errors[:base].should_not include("Fork transaction failed.")
end
end end
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