Commit 4c2156a6 authored by Phil Hughes's avatar Phil Hughes Committed by Igor Drozdov

Display merge conflicts message when comparing against head

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/230991
parent 2f94aec4
<script> <script>
import { mapState, mapGetters, mapActions } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
import { GlLoadingIcon, GlButtonGroup, GlButton } from '@gitlab/ui'; import { GlLoadingIcon, GlButtonGroup, GlButton, GlAlert } from '@gitlab/ui';
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import { __ } from '~/locale'; import { __ } from '~/locale';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
import PanelResizer from '~/vue_shared/components/panel_resizer.vue'; import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { isSingleViewStyle } from '~/helpers/diffs_helper'; import { isSingleViewStyle } from '~/helpers/diffs_helper';
...@@ -38,6 +39,7 @@ export default { ...@@ -38,6 +39,7 @@ export default {
PanelResizer, PanelResizer,
GlButtonGroup, GlButtonGroup,
GlButton, GlButton,
GlAlert,
}, },
mixins: [glFeatureFlagsMixin()], mixins: [glFeatureFlagsMixin()],
props: { props: {
...@@ -133,6 +135,9 @@ export default { ...@@ -133,6 +135,9 @@ export default {
'startVersion', 'startVersion',
'currentDiffFileId', 'currentDiffFileId',
'isTreeLoaded', 'isTreeLoaded',
'conflictResolutionPath',
'canMerge',
'hasConflicts',
]), ]),
...mapGetters('diffs', ['isParallelView', 'currentDiffIndex']), ...mapGetters('diffs', ['isParallelView', 'currentDiffIndex']),
...mapGetters(['isNotesFetched', 'getNoteableData']), ...mapGetters(['isNotesFetched', 'getNoteableData']),
...@@ -161,6 +166,9 @@ export default { ...@@ -161,6 +166,9 @@ export default {
isLimitedContainer() { isLimitedContainer() {
return !this.showTreeList && !this.isParallelView && !this.isFluidLayout; return !this.showTreeList && !this.isParallelView && !this.isFluidLayout;
}, },
isDiffHead() {
return parseBoolean(getParameterByName('diff_head'));
},
}, },
watch: { watch: {
commit(newCommit, oldCommit) { commit(newCommit, oldCommit) {
...@@ -422,6 +430,49 @@ export default { ...@@ -422,6 +430,49 @@ export default {
:email-patch-path="emailPatchPath" :email-patch-path="emailPatchPath"
/> />
<div
v-if="isDiffHead && hasConflicts"
:class="{
[CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
}"
>
<gl-alert
:dismissible="false"
:title="__('There are merge conflicts')"
variant="warning"
class="w-100 mb-3"
>
<p class="mb-1">
{{ __('The comparison view may be inaccurate due to merge conflicts.') }}
</p>
<p class="mb-0">
{{
__(
'Resolve these conflicts or ask someone with write access to this repository to merge it locally.',
)
}}
</p>
<template #actions>
<gl-button
v-if="conflictResolutionPath"
:href="conflictResolutionPath"
variant="info"
class="mr-3 gl-alert-action"
>
{{ __('Resolve conflicts') }}
</gl-button>
<gl-button
v-if="canMerge"
class="gl-alert-action"
data-toggle="modal"
data-target="#modal_merge_info"
>
{{ __('Merge locally') }}
</gl-button>
</template>
</gl-alert>
</div>
<div <div
:data-can-create-note="getNoteableData.current_user.can_create_note" :data-can-create-note="getNoteableData.current_user.can_create_note"
class="files d-flex" class="files d-flex"
......
...@@ -41,7 +41,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic ...@@ -41,7 +41,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
def diffs_metadata def diffs_metadata
diffs = @compare.diffs(diff_options) diffs = @compare.diffs(diff_options)
render json: DiffsMetadataSerializer.new(project: @merge_request.project) render json: DiffsMetadataSerializer.new(project: @merge_request.project, current_user: current_user)
.represent(diffs, additional_attributes) .represent(diffs, additional_attributes)
end end
......
...@@ -3,4 +3,23 @@ ...@@ -3,4 +3,23 @@
class DiffsMetadataEntity < DiffsEntity class DiffsMetadataEntity < DiffsEntity
unexpose :diff_files unexpose :diff_files
expose :raw_diff_files, as: :diff_files, using: DiffFileMetadataEntity expose :raw_diff_files, as: :diff_files, using: DiffFileMetadataEntity
expose :conflict_resolution_path do |_, options|
presenter(options[:merge_request]).conflict_resolution_path
end
expose :has_conflicts do |_, options|
options[:merge_request].cannot_be_merged?
end
expose :can_merge do |_, options|
options[:merge_request].can_be_merged_by?(request.current_user)
end
private
def presenter(merge_request)
@presenters ||= {}
@presenters[merge_request] ||= MergeRequestPresenter.new(merge_request, current_user: request.current_user) # rubocop: disable CodeReuse/Presenter
end
end end
- if @merge_request.source_branch_exists?
= render "projects/merge_requests/how_to_merge"
= javascript_tag nonce: true do = javascript_tag nonce: true do
:plain :plain
window.gl = window.gl || {}; window.gl = window.gl || {};
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
.merge-request{ data: { mr_action: mr_action, url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project), lock_version: @merge_request.lock_version } } .merge-request{ data: { mr_action: mr_action, url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project), lock_version: @merge_request.lock_version } }
= render "projects/merge_requests/mr_title" = render "projects/merge_requests/mr_title"
- if @merge_request.source_branch_exists?
= render "projects/merge_requests/how_to_merge"
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } } .merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
= render "projects/merge_requests/mr_box" = render "projects/merge_requests/mr_box"
......
...@@ -14906,6 +14906,9 @@ msgstr "" ...@@ -14906,6 +14906,9 @@ msgstr ""
msgid "Merge in progress" msgid "Merge in progress"
msgstr "" msgstr ""
msgid "Merge locally"
msgstr ""
msgid "Merge options" msgid "Merge options"
msgstr "" msgstr ""
...@@ -20729,9 +20732,15 @@ msgstr "" ...@@ -20729,9 +20732,15 @@ msgstr ""
msgid "Resolve all threads in new issue" msgid "Resolve all threads in new issue"
msgstr "" msgstr ""
msgid "Resolve conflicts"
msgstr ""
msgid "Resolve conflicts on source branch" msgid "Resolve conflicts on source branch"
msgstr "" msgstr ""
msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
msgstr ""
msgid "Resolve thread" msgid "Resolve thread"
msgstr "" msgstr ""
...@@ -24060,6 +24069,9 @@ msgstr "" ...@@ -24060,6 +24069,9 @@ msgstr ""
msgid "The commit does not exist" msgid "The commit does not exist"
msgstr "" msgstr ""
msgid "The comparison view may be inaccurate due to merge conflicts."
msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination." msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "" msgstr ""
...@@ -24377,6 +24389,9 @@ msgstr "" ...@@ -24377,6 +24389,9 @@ msgstr ""
msgid "There are currently no events." msgid "There are currently no events."
msgstr "" msgstr ""
msgid "There are merge conflicts"
msgstr ""
msgid "There are no %{replicableTypeName} to show" msgid "There are no %{replicableTypeName} to show"
msgstr "" msgstr ""
......
...@@ -30,6 +30,7 @@ RSpec.describe DiffsMetadataEntity do ...@@ -30,6 +30,7 @@ RSpec.describe DiffsMetadataEntity do
:email_patch_path, :plain_diff_path, :email_patch_path, :plain_diff_path,
:merge_request_diffs, :context_commits, :merge_request_diffs, :context_commits,
:definition_path_prefix, :source_branch_exists, :definition_path_prefix, :source_branch_exists,
:can_merge, :conflict_resolution_path, :has_conflicts,
# Attributes # Attributes
:diff_files :diff_files
) )
......
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