diff --git a/changelogs/unreleased/commits_api_with_stats.yml b/changelogs/unreleased/commits_api_with_stats.yml new file mode 100644 index 00000000000..4357f1a6305 --- /dev/null +++ b/changelogs/unreleased/commits_api_with_stats.yml @@ -0,0 +1,5 @@ +--- +title: Added with_statsoption for GET /projects/:id/repository/commits +merge_request: +author: +type: added diff --git a/doc/api/commits.md b/doc/api/commits.md index d1584cf64de..d07b9d5614a 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -16,6 +16,7 @@ GET /projects/:id/repository/commits | `until` | string | no | Only commits before or on this date will be returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ | | `path` | string | no | The file path | | `all` | boolean | no | Retrieve every commit from the repository | +| `with_stats` | boolean | no | Stats about each commit will be added to the response | ```bash diff --git a/lib/api/commits.rb b/lib/api/commits.rb index 684955a1b24..964780cba6a 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -15,19 +15,21 @@ module API end params do optional :ref_name, type: String, desc: 'The name of a repository branch or tag, if not given the default branch is used' - optional :since, type: DateTime, desc: 'Only commits after or on this date will be returned' - optional :until, type: DateTime, desc: 'Only commits before or on this date will be returned' - optional :path, type: String, desc: 'The file path' - optional :all, type: Boolean, desc: 'Every commit will be returned' + optional :since, type: DateTime, desc: 'Only commits after or on this date will be returned' + optional :until, type: DateTime, desc: 'Only commits before or on this date will be returned' + optional :path, type: String, desc: 'The file path' + optional :all, type: Boolean, desc: 'Every commit will be returned' + optional :with_stats, type: Boolean, desc: 'Stats about each commit will be added to the response' use :pagination end get ':id/repository/commits' do - path = params[:path] + path = params[:path] before = params[:until] - after = params[:since] - ref = params[:ref_name] || user_project.try(:default_branch) || 'master' unless params[:all] + after = params[:since] + ref = params[:ref_name] || user_project.try(:default_branch) || 'master' unless params[:all] offset = (params[:page] - 1) * params[:per_page] - all = params[:all] + all = params[:all] + with_stats = params[:with_stats] commits = user_project.repository.commits(ref, path: path, @@ -47,7 +49,9 @@ module API paginated_commits = Kaminari.paginate_array(commits, total_count: commit_count) - present paginate(paginated_commits), with: Entities::Commit + serializer = with_stats ? Entities::CommitWithStats : Entities::Commit + + present paginate(paginated_commits), with: serializer end desc 'Commit multiple file changes as one commit' do diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 22afcb9edf2..52e716a7686 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -308,6 +308,10 @@ module API expose :additions, :deletions, :total end + class CommitWithStats < Commit + expose :stats, using: Entities::CommitStats + end + class CommitDetail < Commit expose :stats, using: Entities::CommitStats, if: :stats expose :status diff --git a/spec/fixtures/api/schemas/public_api/v4/commit/with_stats.json b/spec/fixtures/api/schemas/public_api/v4/commit/with_stats.json new file mode 100644 index 00000000000..3b5dd547e69 --- /dev/null +++ b/spec/fixtures/api/schemas/public_api/v4/commit/with_stats.json @@ -0,0 +1,14 @@ +{ + "type": "object", + "allOf": [ + { "$ref": "basic.json" }, + { + "required" : [ + "stats" + ], + "properties": { + "stats": { "$ref": "../commit_stats.json" } + } + } + ] +} diff --git a/spec/fixtures/api/schemas/public_api/v4/commits_with_stats.json b/spec/fixtures/api/schemas/public_api/v4/commits_with_stats.json new file mode 100644 index 00000000000..23511123ce4 --- /dev/null +++ b/spec/fixtures/api/schemas/public_api/v4/commits_with_stats.json @@ -0,0 +1,4 @@ +{ + "type": "array", + "items": { "$ref": "commit/with_stats.json" } +} diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 7e3277c4cab..e73d1a252f5 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -18,14 +18,14 @@ describe API::Commits do describe 'GET /projects/:id/repository/commits' do let(:route) { "/projects/#{project_id}/repository/commits" } - shared_examples_for 'project commits' do + shared_examples_for 'project commits' do |schema: 'public_api/v4/commits'| it "returns project commits" do commit = project.repository.commit get api(route, current_user) expect(response).to have_gitlab_http_status(200) - expect(response).to match_response_schema('public_api/v4/commits') + expect(response).to match_response_schema(schema) expect(json_response.first['id']).to eq(commit.id) expect(json_response.first['committer_name']).to eq(commit.committer_name) expect(json_response.first['committer_email']).to eq(commit.committer_email) @@ -161,6 +161,23 @@ describe API::Commits do end end + context 'with_stats optional parameter' do + let(:project) { create(:project, :public, :repository) } + + it_behaves_like 'project commits', schema: 'public_api/v4/commits_with_stats' do + let(:route) { "/projects/#{project_id}/repository/commits?with_stats=true" } + + it 'include commits details' do + commit = project.repository.commit + get api(route, current_user) + + expect(json_response.first['stats']['additions']).to eq(commit.stats.additions) + expect(json_response.first['stats']['deletions']).to eq(commit.stats.deletions) + expect(json_response.first['stats']['total']).to eq(commit.stats.total) + end + end + end + context 'with pagination params' do let(:page) { 1 } let(:per_page) { 5 }