diff options
-rw-r--r-- | app/models/repository.rb | 10 | ||||
-rw-r--r-- | changelogs/unreleased/bvl-merge-base-multiple-revisions.yml | 5 | ||||
-rw-r--r-- | doc/api/repositories.md | 2 | ||||
-rw-r--r-- | lib/api/repositories.rb | 9 | ||||
-rw-r--r-- | lib/gitlab/git/repository.rb | 4 | ||||
-rw-r--r-- | spec/models/repository_spec.rb | 11 | ||||
-rw-r--r-- | spec/requests/api/repositories_spec.rb | 4 |
7 files changed, 29 insertions, 16 deletions
diff --git a/app/models/repository.rb b/app/models/repository.rb index a3a3ce179fc..2c28ea64066 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -881,10 +881,12 @@ class Repository delegate :merged_branch_names, to: :raw_repository - def merge_base(first_commit_id, second_commit_id) - first_commit_id = commit(first_commit_id).try(:id) || first_commit_id - second_commit_id = commit(second_commit_id).try(:id) || second_commit_id - raw_repository.merge_base(first_commit_id, second_commit_id) + def merge_base(*commits_or_ids) + commit_ids = commits_or_ids.map do |commit_or_id| + commit_or_id.is_a?(::Commit) ? commit_or_id.id : commit_or_id + end + + raw_repository.merge_base(*commit_ids) end def ancestor?(ancestor_id, descendant_id) diff --git a/changelogs/unreleased/bvl-merge-base-multiple-revisions.yml b/changelogs/unreleased/bvl-merge-base-multiple-revisions.yml new file mode 100644 index 00000000000..4075e35fce9 --- /dev/null +++ b/changelogs/unreleased/bvl-merge-base-multiple-revisions.yml @@ -0,0 +1,5 @@ +--- +title: Allow finding the common ancestor for multiple revisions through the API +merge_request: 22295 +author: +type: changed diff --git a/doc/api/repositories.md b/doc/api/repositories.md index a4fdeca162e..f5ac3816fe5 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -216,7 +216,7 @@ GET /projects/:id/repository/merge_base | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | -| `refs` | array | yes | The refs to find the common ancestor of, for now only 2 refs are supported | +| `refs` | array | yes | The refs to find the common ancestor of, multiple refs can be passed | ```bash curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/merge_base?refs[]=304d257dcb821665ab5110318fc58a007bd104ed&refs[]=0031876facac3f2b2702a0e53a26e89939a42209" diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 5125f302fbb..dc844c0bd27 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -130,18 +130,13 @@ module API success Entities::Commit end params do - # For now we just support 2 refs passed, but `merge-base` supports - # multiple defining this as an Array instead of 2 separate params will - # make sure we don't need to deprecate this API in favor of one - # supporting multiple commits when this functionality gets added to - # Gitaly requires :refs, type: Array[String] end get ':id/repository/merge_base' do refs = params[:refs] - unless refs.size == 2 - render_api_error!('Provide exactly 2 refs', 400) + if refs.size < 2 + render_api_error!('Provide at least 2 refs', 400) end merge_base = Gitlab::Git::MergeBase.new(user_project.repository, refs) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 4218e812146..9df04372cc2 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -382,9 +382,9 @@ module Gitlab end # Returns the SHA of the most recent common ancestor of +from+ and +to+ - def merge_base(from, to) + def merge_base(*commits) wrapped_gitaly_errors do - gitaly_repository_client.find_merge_base(from, to) + gitaly_repository_client.find_merge_base(*commits) end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index aed8e02cc23..6f5a4118b95 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -2386,4 +2386,15 @@ describe Repository do end end end + + describe '#merge_base' do + set(:project) { create(:project, :repository) } + subject(:repository) { project.repository } + + it 'only makes one gitaly call' do + expect(Gitlab::GitalyClient).to receive(:call).once.and_call_original + + repository.merge_base('master', 'fix') + end + end end diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index 519638ebb82..fa38751fe58 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -468,7 +468,7 @@ describe API::Repositories do describe 'GET :id/repository/merge_base' do let(:refs) do - %w(304d257dcb821665ab5110318fc58a007bd104ed 0031876facac3f2b2702a0e53a26e89939a42209) + %w(304d257dcb821665ab5110318fc58a007bd104ed 0031876facac3f2b2702a0e53a26e89939a42209 570e7b2abdd848b95f2f578043fc23bd6f6fd24d) end subject(:request) do @@ -534,7 +534,7 @@ describe API::Repositories do request expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response['message']).to eq('Provide exactly 2 refs') + expect(json_response['message']).to eq('Provide at least 2 refs') end end end |