Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services/merge_requests/create_ref_service_spec.rb')
-rw-r--r--spec/services/merge_requests/create_ref_service_spec.rb183
1 files changed, 144 insertions, 39 deletions
diff --git a/spec/services/merge_requests/create_ref_service_spec.rb b/spec/services/merge_requests/create_ref_service_spec.rb
index 85ac651c1fa..5f7b9430416 100644
--- a/spec/services/merge_requests/create_ref_service_spec.rb
+++ b/spec/services/merge_requests/create_ref_service_spec.rb
@@ -6,13 +6,14 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains
using RSpec::Parameterized::TableSyntax
describe '#execute' do
- let_it_be(:project) { create(:project, :empty_repo) }
+ let_it_be_with_reload(:project) { create(:project, :empty_repo) }
let_it_be(:user) { project.creator }
let_it_be(:first_parent_ref) { project.default_branch_or_main }
let_it_be(:source_branch) { 'branch' }
let(:target_ref) { "refs/merge-requests/#{merge_request.iid}/train" }
let(:source_sha) { project.commit(source_branch).sha }
let(:squash) { false }
+ let(:default_commit_message) { merge_request.default_merge_commit_message(user: user) }
let(:merge_request) do
create(
@@ -84,36 +85,40 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains
)
end
- it 'writes the merged result into target_ref', :aggregate_failures do
- expect(result[:status]).to eq :success
- expect(result[:commit_sha]).to eq(project.repository.commit(target_ref).sha)
- expect(result[:source_sha]).to eq(project.repository.commit(target_ref).parents[1].sha)
- expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha)
- expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to(
- match(
- [
- a_string_matching(/Merge branch '#{source_branch}' into '#{first_parent_ref}'/),
- 'Feature branch commit 2',
- 'Feature branch commit 1',
- 'Base parent commit 2',
- 'Base parent commit 1'
- ]
+ shared_examples_for 'writing with a merge commit' do
+ it 'merges with a merge commit', :aggregate_failures do
+ expect(result[:status]).to eq :success
+ expect(result[:commit_sha]).to eq(project.repository.commit(target_ref).sha)
+ expect(result[:source_sha]).to eq(project.repository.commit(source_branch).sha)
+ expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha)
+ expect(result[:merge_commit_sha]).to be_present
+ expect(result[:squash_commit_sha]).not_to be_present
+ expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to(
+ match(
+ [
+ expected_merge_commit,
+ 'Feature branch commit 2',
+ 'Feature branch commit 1',
+ 'Base parent commit 2',
+ 'Base parent commit 1'
+ ]
+ )
)
- )
+ end
end
- context 'when squash is requested' do
- let(:squash) { true }
-
+ shared_examples_for 'writing with a squash and merge commit' do
it 'writes the squashed result', :aggregate_failures do
expect(result[:status]).to eq :success
expect(result[:commit_sha]).to eq(project.repository.commit(target_ref).sha)
- expect(result[:source_sha]).to eq(project.repository.commit(target_ref).parents[1].sha)
+ expect(result[:source_sha]).to eq(project.repository.commit(source_branch).sha)
expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha)
+ expect(result[:merge_commit_sha]).to be_present
+ expect(result[:squash_commit_sha]).to be_present
expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to(
match(
[
- a_string_matching(/Merge branch '#{source_branch}' into '#{first_parent_ref}'/),
+ expected_merge_commit,
"#{merge_request.title}\n",
'Base parent commit 2',
'Base parent commit 1'
@@ -123,23 +128,18 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains
end
end
- context 'when semi-linear merges are enabled' do
- before do
- project.merge_method = :rebase_merge
- project.save!
- end
-
- it 'writes the semi-linear merged result', :aggregate_failures do
+ shared_examples_for 'writing with a squash and no merge commit' do
+ it 'writes the squashed result without a merge commit', :aggregate_failures do
expect(result[:status]).to eq :success
expect(result[:commit_sha]).to eq(project.repository.commit(target_ref).sha)
- expect(result[:source_sha]).to eq(project.repository.commit(target_ref).parents[1].sha)
+ expect(result[:source_sha]).to eq(project.repository.commit(source_branch).sha)
expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha)
+ expect(result[:merge_commit_sha]).not_to be_present
+ expect(result[:squash_commit_sha]).to be_present
expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to(
match(
[
- a_string_matching(/Merge branch '#{source_branch}' into '#{first_parent_ref}'/),
- 'Feature branch commit 2',
- 'Feature branch commit 1',
+ "#{merge_request.title}\n",
'Base parent commit 2',
'Base parent commit 1'
]
@@ -148,17 +148,14 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains
end
end
- context 'when fast-forward merges are enabled' do
- before do
- project.merge_method = :ff
- project.save!
- end
-
+ shared_examples_for 'writing without a merge commit' do
it 'writes the rebased merged result', :aggregate_failures do
expect(result[:status]).to eq :success
expect(result[:commit_sha]).to eq(project.repository.commit(target_ref).sha)
- expect(result[:source_sha]).to eq(project.repository.commit(target_ref).sha)
+ expect(result[:source_sha]).to eq(project.repository.commit(source_branch).sha)
expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha)
+ expect(result[:merge_commit_sha]).not_to be_present
+ expect(result[:squash_commit_sha]).not_to be_present
expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to(
eq(
[
@@ -171,6 +168,114 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains
)
end
end
+
+ shared_examples 'merge commits without squash' do
+ context 'with a custom template' do
+ let(:expected_merge_commit) { 'This is the merge commit' } # could also be default_commit_message
+
+ before do
+ project.project_setting.update!(merge_commit_template: expected_merge_commit)
+ end
+
+ it_behaves_like 'writing with a merge commit'
+ end
+
+ context 'with no custom template' do
+ let(:expected_merge_commit) { default_commit_message }
+
+ before do
+ project.project_setting.update!(merge_commit_template: nil)
+ end
+
+ it_behaves_like 'writing with a merge commit'
+ end
+ end
+
+ shared_examples 'merge commits with squash' do
+ context 'when squash set' do
+ let(:squash) { true }
+ let(:expected_merge_commit) { merge_request.default_merge_commit_message(user: user) }
+
+ before do
+ project.project_setting.update!(merge_commit_template: 'This is the merge commit')
+ end
+
+ it_behaves_like 'writing with a squash and merge commit'
+ end
+ end
+
+ context 'when the merge commit message is provided at time of merge' do
+ let(:expected_merge_commit) { 'something custom' }
+
+ before do
+ merge_request.merge_params['commit_message'] = expected_merge_commit
+ end
+
+ it 'writes the merged result', :aggregate_failures do
+ expect(result[:status]).to eq :success
+ expect(project.repository.commits(target_ref, limit: 1, order: 'topo').map(&:message)).to(
+ match([expected_merge_commit])
+ )
+ end
+
+ context 'when squash set' do
+ let(:squash) { true }
+
+ it_behaves_like 'writing with a squash and merge commit'
+ end
+ end
+
+ context 'when merged commit strategy' do
+ include_examples 'merge commits without squash'
+ include_examples 'merge commits with squash'
+ end
+
+ context 'when semi-linear merge strategy' do
+ before do
+ project.merge_method = :rebase_merge
+ project.save!
+ end
+
+ include_examples 'merge commits without squash'
+ include_examples 'merge commits with squash'
+
+ context 'when the target ref changes between rebase and merge' do
+ # this tests internal handling of expected_old_oid
+
+ it 'returns an error', :aggregate_failures do
+ expect_next_instance_of(described_class) do |instance|
+ original = instance.method(:maybe_merge!)
+
+ expect(instance).to receive(:maybe_merge!) do |*args|
+ # Corrupt target_ref before the merge, simulating a race with
+ # another instance of the service for the same MR. source_sha is
+ # just an arbitrary valid commit that differs from what was just
+ # written.
+ project.repository.write_ref(target_ref, source_sha)
+ original.call(*args)
+ end
+ end
+
+ expect(result[:status]).to eq :error
+ expect(result[:message]).to eq "9:Could not update #{target_ref}. Please refresh and try again."
+ end
+ end
+ end
+
+ context 'when fast-forward merge strategy' do
+ before do
+ project.merge_method = :ff
+ project.save!
+ end
+
+ it_behaves_like 'writing without a merge commit'
+
+ context 'when squash set' do
+ let(:squash) { true }
+
+ it_behaves_like 'writing with a squash and no merge commit'
+ end
+ end
end
end
end