Skip to content

Commit

Permalink
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce
Browse files Browse the repository at this point in the history
  • Loading branch information
dzaporozhets committed Oct 1, 2014
2 parents b10774e + aab2b0b commit 1099468
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Expand Up @@ -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
- API: Add support for forking a project via the API (Bernhard Kaindl)
- API: filter project issues by milestone (Julien Bianchi)

v 7.3.2
Expand Down
12 changes: 12 additions & 0 deletions doc/api/projects.md
Expand Up @@ -281,6 +281,18 @@ Parameters:
- `visibility_level` (optional)
- `import_url` (optional)

### Fork project

Forks a project into the user namespace of the authenticated user.

```
POST /projects/fork/:id
```

Parameters:

- `id` (required) - The ID of the project to be forked

### Remove project

Removes a project including all associated resources (issues, merge requests etc.)
Expand Down
2 changes: 2 additions & 0 deletions doc/workflow/gitlab_flow.md
@@ -1,3 +1,5 @@
![GitLab Flow](gitlab_flow.png)

# Introduction

Version management with git makes branching and merging much easier than older versioning systems such as SVN.
Expand Down
Binary file added doc/workflow/gitlab_flow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions lib/api/projects.rb
Expand Up @@ -153,6 +153,23 @@ def map_public_to_visibility_level(attrs)
end
end

# Fork new project for the current user.
#
# Parameters:
# id (required) - The ID of a project
# Example Request
# POST /projects/fork/:id
post 'fork/:id' do
@forked_project =
::Projects::ForkService.new(user_project,
current_user).execute
if @forked_project.errors.any?
conflict!(@forked_project.errors.messages)
else
present @forked_project, with: Entities::Project
end
end

# Remove project
#
# Parameters:
Expand Down
73 changes: 73 additions & 0 deletions spec/requests/api/fork_spec.rb
@@ -0,0 +1,73 @@
require 'spec_helper'

describe API::API, api: true do
include ApiHelpers
let(:user) { create(:user) }
let(:user2) { create(:user) }
let(:user3) { create(:user) }
let(:admin) { create(:admin) }
let(:project) {
create(:project, creator_id: user.id,
namespace: user.namespace)
}
let(:project_user2) {
create(:project_member, user: user2,
project: project,
access_level: ProjectMember::GUEST)
}

describe 'POST /projects/fork/:id' do
before { project_user2 }
before { user3 }

context 'when authenticated' do
it 'should fork if user has sufficient access to project' do
post api("/projects/fork/#{project.id}", user2)
response.status.should == 201
json_response['name'].should == project.name
json_response['path'].should == project.path
json_response['owner']['id'].should == user2.id
json_response['namespace']['id'].should == user2.namespace.id
json_response['forked_from_project']['id'].should == project.id
end

it 'should fork if user is admin' do
post api("/projects/fork/#{project.id}", admin)
response.status.should == 201
json_response['name'].should == project.name
json_response['path'].should == project.path
json_response['owner']['id'].should == admin.id
json_response['namespace']['id'].should == admin.namespace.id
json_response['forked_from_project']['id'].should == project.id
end

it 'should fail on missing project access for the project to fork' do
post api("/projects/fork/#{project.id}", user3)
response.status.should == 404
json_response['message'].should == '404 Not Found'
end

it 'should fail if forked project exists in the user namespace' do
post api("/projects/fork/#{project.id}", user)
response.status.should == 409
json_response['message']['base'].should == ['Invalid fork destination']
json_response['message']['name'].should == ['has already been taken']
json_response['message']['path'].should == ['has already been taken']
end

it 'should fail if project to fork from does not exist' do
post api('/projects/fork/424242', user)
response.status.should == 404
json_response['message'].should == '404 Not Found'
end
end

context 'when unauthenticated' do
it 'should return authentication error' do
post api("/projects/fork/#{project.id}")
response.status.should == 401
json_response['message'].should == '401 Unauthorized'
end
end
end
end

0 comments on commit 1099468

Please sign in to comment.