summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelogs/unreleased/api-refs-for-commit.yml5
-rw-r--r--doc/api/commits.md36
-rw-r--r--lib/api/commits.rb23
-rw-r--r--lib/api/entities.rb4
-rw-r--r--spec/requests/api/commits_spec.rb66
5 files changed, 133 insertions, 1 deletions
diff --git a/changelogs/unreleased/api-refs-for-commit.yml b/changelogs/unreleased/api-refs-for-commit.yml
new file mode 100644
index 00000000000..df8a2b0eccc
--- /dev/null
+++ b/changelogs/unreleased/api-refs-for-commit.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Get references a commit is pushed to'
+merge_request: 15026
+author: Robert Schilling
+type: added
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 63554c63057..2c745d00887 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -198,6 +198,41 @@ Example response:
}
```
+## Get references a commit is pushed to
+
+> [Introduced][ce-15026] in GitLab 10.6
+
+Get all references (from branches or tags) a commit is pushed to.
+The pagination parameters `page` and `per_page` can be used to restrict the list of references.
+
+```
+GET /projects/:id/repository/commits/:sha/refs
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+| `sha` | string | yes | The commit hash |
+| `type` | string | no | The scope of commits. Possible values `branch`, `tag`, `all`. Default is `all`. |
+
+```bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/5937ac0a7beb003549fc5fd26fc247adbce4a52e/refs?type=all"
+```
+
+Example response:
+
+```json
+[
+ {"type": "branch", "name": "'test'"},
+ {"type": "branch", "name": "add-balsamiq-file"},
+ {"type": "branch", "name": "wip"},
+ {"type": "tag", "name": "v1.1.0"}
+ ]
+
+```
+
## Cherry pick a commit
> [Introduced][ce-8047] in GitLab 8.15.
@@ -500,3 +535,4 @@ Example response:
[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
+[ce-15026]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15026
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index d8fd6a6eb06..d83c43ee49b 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -156,6 +156,27 @@ module API
end
end
+ desc 'Get all references a commit is pushed to' do
+ detail 'This feature was introduced in GitLab 10.6'
+ success Entities::BasicRef
+ end
+ params do
+ requires :sha, type: String, desc: 'A commit sha'
+ optional :type, type: String, values: %w[branch tag all], default: 'all', desc: 'Scope'
+ use :pagination
+ end
+ get ':id/repository/commits/:sha/refs', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
+ commit = user_project.commit(params[:sha])
+ not_found!('Commit') unless commit
+
+ refs = []
+ refs.concat(user_project.repository.branch_names_contains(commit.id).map {|name| { type: 'branch', name: name }}) unless params[:type] == 'tag'
+ refs.concat(user_project.repository.tag_names_contains(commit.id).map {|name| { type: 'tag', name: name }}) unless params[:type] == 'branch'
+ refs = Kaminari.paginate_array(refs)
+
+ present paginate(refs), with: Entities::BasicRef
+ end
+
desc 'Post comment to commit' do
success Entities::CommitNote
end
@@ -165,7 +186,7 @@ module API
optional :path, type: String, desc: 'The file path'
given :path do
requires :line, type: Integer, desc: 'The line number'
- requires :line_type, type: String, values: %w(new old), default: 'new', desc: 'The type of the line'
+ requires :line_type, type: String, values: %w[new old], default: 'new', desc: 'The type of the line'
end
end
post ':id/repository/commits/:sha/comments', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 7838de13c56..c8cda85b170 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -276,6 +276,10 @@ module API
expose :last_pipeline, using: 'API::Entities::PipelineBasic'
end
+ class BasicRef < Grape::Entity
+ expose :type, :name
+ end
+
class Branch < Grape::Entity
expose :name
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index ff5f207487b..31959d28fee 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -465,6 +465,72 @@ describe API::Commits do
end
end
+ describe 'GET /projects/:id/repository/commits/:sha/refs' do
+ let(:project) { create(:project, :public, :repository) }
+ let(:tag) { project.repository.find_tag('v1.1.0') }
+ let(:commit_id) { tag.dereferenced_target.id }
+ let(:route) { "/projects/#{project_id}/repository/commits/#{commit_id}/refs" }
+
+ context 'when ref does not exist' do
+ let(:commit_id) { 'unknown' }
+
+ it_behaves_like '404 response' do
+ let(:request) { get api(route, current_user) }
+ let(:message) { '404 Commit Not Found' }
+ end
+ end
+
+ context 'when repository is disabled' do
+ include_context 'disabled repository'
+
+ it_behaves_like '403 response' do
+ let(:request) { get api(route, current_user) }
+ end
+ end
+
+ context 'for a valid commit' do
+ it 'returns all refs with no scope' do
+ get api(route, current_user), per_page: 100
+
+ refs = project.repository.branch_names_contains(commit_id).map {|name| ['branch', name]}
+ refs.concat(project.repository.tag_names_contains(commit_id).map {|name| ['tag', name]})
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
+ end
+
+ it 'returns all refs' do
+ get api(route, current_user), type: 'all', per_page: 100
+
+ refs = project.repository.branch_names_contains(commit_id).map {|name| ['branch', name]}
+ refs.concat(project.repository.tag_names_contains(commit_id).map {|name| ['tag', name]})
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
+ end
+
+ it 'returns the branch refs' do
+ get api(route, current_user), type: 'branch', per_page: 100
+
+ refs = project.repository.branch_names_contains(commit_id).map {|name| ['branch', name]}
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
+ end
+
+ it 'returns the tag refs' do
+ get api(route, current_user), type: 'tag', per_page: 100
+
+ refs = project.repository.tag_names_contains(commit_id).map {|name| ['tag', name]}
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
+ end
+ end
+ end
+
describe 'GET /projects/:id/repository/commits/:sha' do
let(:commit) { project.repository.commit }
let(:commit_id) { commit.id }