Commit 1a81fcfb authored by Robert Schilling's avatar Robert Schilling

API: Ability to cherry-pick a commit

parent db9e1635
---
title: 'API: Ability to cherry pick a commit'
merge_request: 8047
author: Robert Schilling
...@@ -183,6 +183,44 @@ Example response: ...@@ -183,6 +183,44 @@ Example response:
} }
``` ```
## Cherry pick a commit
> [Introduced][ce-8047] in GitLab 8.15.
Cherry picks a commit to a given branch.
```
POST /projects/:id/repository/commits/:sha/cherry_pick
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME owned by the authenticated user
| `sha` | string | yes | The commit hash |
| `branch` | string | yes | The name of the branch |
```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "branch=master" "https://gitlab.example.com/api/v3/projects/5/repository/commits/master/cherry_pick"
```
Example response:
```json
{
"id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad",
"short_id": "8b090c1b",
"title": "Feature added",
"author_name": "Dmitriy Zaporozhets",
"author_email": "dmitriy.zaporozhets@gmail.com",
"created_at": "2016-12-12T20:10:39.000+01:00",
"committer_name": "Administrator",
"committer_email": "admin@example.com",
"message": "Feature added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n"
}
```
## Get the diff of a commit ## Get the diff of a commit
Get the diff of a commit in a project. Get the diff of a commit in a project.
...@@ -438,3 +476,4 @@ Example response: ...@@ -438,3 +476,4 @@ Example response:
``` ```
[ce-6096]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6096 "Multi-file commit" [ce-6096]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6096 "Multi-file commit"
[ce-8047]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8047
require 'mime/types' require 'mime/types'
module API module API
# Projects commits API
class Commits < Grape::API class Commits < Grape::API
include PaginationParams include PaginationParams
...@@ -121,6 +120,41 @@ module API ...@@ -121,6 +120,41 @@ module API
present paginate(notes), with: Entities::CommitNote present paginate(notes), with: Entities::CommitNote
end end
desc 'Cherry pick commit into a branch' do
detail 'This feature was introduced in GitLab 8.15'
success Entities::RepoCommit
end
params do
requires :sha, type: String, desc: 'A commit sha to be cherry picked'
requires :branch, type: String, desc: 'The name of the branch'
end
post ':id/repository/commits/:sha/cherry_pick' do
authorize! :push_code, user_project
commit = user_project.commit(params[:sha])
not_found!('Commit') unless commit
branch = user_project.repository.find_branch(params[:branch])
not_found!('Branch') unless branch
commit_params = {
commit: commit,
create_merge_request: false,
source_project: user_project,
source_branch: commit.cherry_pick_branch_name,
target_branch: params[:branch]
}
result = ::Commits::CherryPickService.new(user_project, current_user, commit_params).execute
if result[:status] == :success
branch = user_project.repository.find_branch(params[:branch])
present user_project.repository.commit(branch.dereferenced_target), with: Entities::RepoCommit
else
render_api_error!(result[:message], 400)
end
end
desc 'Post comment to commit' do desc 'Post comment to commit' do
success Entities::CommitNote success Entities::CommitNote
end end
......
...@@ -456,6 +456,76 @@ describe API::Commits, api: true do ...@@ -456,6 +456,76 @@ describe API::Commits, api: true do
end end
end end
describe 'POST :id/repository/commits/:sha/cherry_pick' do
let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
context 'authorized user' do
it 'cherry picks a commit' do
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'master'
expect(response).to have_http_status(201)
expect(json_response['title']).to eq(master_pickable_commit.title)
expect(json_response['message']).to eq(master_pickable_commit.message)
expect(json_response['author_name']).to eq(master_pickable_commit.author_name)
expect(json_response['committer_name']).to eq(user.name)
end
it 'returns 400 if commit is already included in the target branch' do
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'markdown'
expect(response).to have_http_status(400)
expect(json_response['message']).to eq('Sorry, we cannot cherry-pick this commit automatically.
It may have already been cherry-pick, or a more recent commit may have updated some of its content.')
end
it 'returns 400 if you are not allowed to push to the target branch' do
project.team << [user2, :developer]
protected_branch = create(:protected_branch, project: project, name: 'feature')
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user2), branch: 'feature'
expect(response).to have_http_status(400)
expect(json_response['message']).to eq('You are not allowed to push into this branch')
end
it 'returns 400 for missing parameters' do
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
expect(response).to have_http_status(400)
expect(json_response['error']).to eq('branch is missing')
end
it 'returns 404 if commit is not found' do
post api("/projects/#{project.id}/repository/commits/abcd0123/cherry_pick", user), branch: 'master'
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Commit Not Found')
end
it 'returns 404 if branch is not found' do
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'foo'
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Branch Not Found')
end
it 'returns 400 for missing parameters' do
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
expect(response).to have_http_status(400)
expect(json_response['error']).to eq('branch is missing')
end
end
context 'unauthorized user' do
it 'does not cherry pick the commit' do
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick"), branch: 'master'
expect(response).to have_http_status(401)
end
end
end
describe 'Post comment to commit' do describe 'Post comment to commit' do
context 'authorized user' do context 'authorized user' do
it 'returns comment' do it 'returns comment' do
......
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