Commit 025a4ba7 authored by Abhishek Kumar's avatar Abhishek Kumar

Add 'previously merged commits' compare dropdown

parent d3e70a87
<script>
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { GlDropdown, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
GlDropdown,
GlDropdownItem,
GlDropdownDivider,
TimeAgo,
},
props: {
......@@ -24,34 +25,36 @@ export default {
<template>
<gl-dropdown :text="selectedVersionName" data-qa-selector="dropdown_content">
<gl-dropdown-item
v-for="version in versions"
:key="version.id"
:class="{
'is-active': version.selected,
}"
:is-check-item="true"
:is-checked="version.selected"
:href="version.href"
>
<div>
<strong>
{{ version.versionName }}
<template v-if="version.isHead">{{ s__('DiffsCompareBaseBranch|(HEAD)') }}</template>
<template v-else-if="version.isBase">{{ s__('DiffsCompareBaseBranch|(base)') }}</template>
</strong>
</div>
<div>
<small class="commit-sha"> {{ version.short_commit_sha }} </small>
</div>
<div>
<small>
<template v-if="version.commitsText">
{{ version.commitsText }}
</template>
<time-ago v-if="version.created_at" :time="version.created_at" class="js-timeago" />
</small>
</div>
</gl-dropdown-item>
<template v-for="version in versions">
<gl-dropdown-divider v-if="version.addDivider" :key="version.id" />
<gl-dropdown-item
:key="version.id"
:class="{
'is-active': version.selected,
}"
:is-check-item="true"
:is-checked="version.selected"
:href="version.href"
>
<div>
<strong>
{{ version.versionName }}
<template v-if="version.isHead">{{ s__('DiffsCompareBaseBranch|(HEAD)') }}</template>
<template v-else-if="version.isBase">{{ s__('DiffsCompareBaseBranch|(base)') }}</template>
</strong>
</div>
<div>
<small class="commit-sha"> {{ version.short_commit_sha }} </small>
</div>
<div>
<small>
<template v-if="version.commitsText">
{{ version.commitsText }}
</template>
<time-ago v-if="version.created_at" :time="version.created_at" class="js-timeago" />
</small>
</div>
</gl-dropdown-item>
</template>
</gl-dropdown>
</template>
......@@ -7,6 +7,10 @@ export const selectedTargetIndex = (state) =>
export const selectedSourceIndex = (state) => state.mergeRequestDiff.version_index;
export const selectedContextCommitsDiffs = (state) =>
state.contextCommitsDiff && state.contextCommitsDiff.showing_context_commits_diff;
export const diffCompareDropdownTargetVersions = (state, getters) => {
// startVersion only exists if the user has selected a version other
// than "base" so if startVersion is null then base must be selected
......@@ -58,7 +62,7 @@ export const diffCompareDropdownTargetVersions = (state, getters) => {
export const diffCompareDropdownSourceVersions = (state, getters) => {
// Appended properties here are to make the compare_dropdown_layout easier to reason about
return state.mergeRequestDiffs.map((v, i) => {
const versions = state.mergeRequestDiffs.map((v, i) => {
const isLatestVersion = i === 0;
return {
......@@ -69,7 +73,19 @@ export const diffCompareDropdownSourceVersions = (state, getters) => {
versionName: isLatestVersion
? __('latest version')
: sprintf(__(`version %{versionIndex}`), { versionIndex: v.version_index }),
selected: v.version_index === getters.selectedSourceIndex,
selected: v.version_index === getters.selectedSourceIndex && !getters.selectedContextCommitsDiffs,
};
});
const { contextCommitsDiff } = state;
if (contextCommitsDiff) {
versions.push({
href: contextCommitsDiff.diffs_path,
commitsText: n__(`%d commit`, `%d commits`, contextCommitsDiff.commits_count),
versionName: __('previously merged commits'),
selected: getters.selectedContextCommitsDiffs,
addDivider: state.mergeRequestDiffs.length > 0,
});
}
return versions;
};
......@@ -47,7 +47,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
diffs = @compare.diffs(diff_options)
render json: DiffsMetadataSerializer.new(project: @merge_request.project, current_user: current_user)
.represent(diffs, additional_attributes)
.represent(diffs, additional_attributes.merge(only_context_commits: show_only_context_commits?))
end
private
......@@ -92,7 +92,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
# rubocop: disable CodeReuse/ActiveRecord
def commit
return unless commit_id = params[:commit_id].presence
return unless @merge_request.all_commits.exists?(sha: commit_id)
return unless @merge_request.all_commits.exists?(sha: commit_id) || @merge_request.recent_context_commits.map(&:id).include?(commit_id)
@commit ||= @project.commit(commit_id)
end
......@@ -122,6 +122,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
end
end
return @merge_request.context_commits_diff if show_only_context_commits? && !@merge_request.context_commits_diff.empty?
return @merge_request.merge_head_diff if render_merge_ref_head_diff?
if @start_sha
......
......@@ -114,6 +114,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@noteable = @merge_request
@commits_count = @merge_request.commits_count + @merge_request.context_commits_count
@diffs_count = get_diffs_count
@issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar')
@current_user_data = UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestCurrentUserEntity).to_json
@show_whitespace_default = current_user.nil? || current_user.show_whitespace_in_diffs
......@@ -386,6 +387,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
private
def get_diffs_count
if show_only_context_commits?
@merge_request.context_commits_diff.raw_diffs.size
else
@merge_request.diff_size
end
end
def merge_request_update_params
merge_request_params.merge!(params.permit(:merge_request_diff_head_sha))
end
......
......@@ -23,14 +23,16 @@ module DiffHelper
end
end
def show_only_context_commits?
!!params[:only_context_commits] || @merge_request&.commits&.empty?
end
def diff_options
options = { ignore_whitespace_change: hide_whitespace?, expanded: diffs_expanded? }
if action_name == 'diff_for_path'
options[:expanded] = true
options[:paths] = params.values_at(:old_path, :new_path)
elsif action_name == 'show'
options[:include_context_commits] = true unless @project.context_commits_enabled?
end
options
......
# frozen_string_literal: true
class ContextCommitsDiff
include ActsAsPaginatedDiff
attr_reader :merge_request
def initialize(merge_request)
@merge_request = merge_request
end
def empty?
commits.empty?
end
def commits_count
merge_request.context_commits_count
end
def diffs(diff_options = nil)
Gitlab::Diff::FileCollection::Compare.new(
self,
project: merge_request.project,
diff_options: diff_options,
diff_refs: diff_refs
)
end
def raw_diffs(options = {})
compare.diffs(options.merge(paths: paths))
end
def diff_refs
Gitlab::Diff::DiffRefs.new(
base_sha: commits.last.diff_refs.base_sha,
head_sha: commits.first.diff_refs.head_sha
)
end
private
def compare
@compare ||=
Gitlab::Git::Compare.new(
merge_request.project.repository.raw_repository,
commits.last.diff_refs.base_sha,
commits.first.diff_refs.head_sha
)
end
def commits
@commits ||= merge_request.project.repository.commits_by(oids: merge_request.recent_context_commits.map(&:id))
end
def paths
merge_request.merge_request_context_commit_diff_files.map(&:path)
end
end
\ No newline at end of file
......@@ -1899,6 +1899,11 @@ class MergeRequest < ApplicationRecord
diff_stats.map(&:path).include?(project.ci_config_path_or_default)
end
def context_commits_diff
strong_memoize(:context_commits_diff) do
ContextCommitsDiff.new(self)
end
end
private
def missing_report_error(report_type)
......
......@@ -16,4 +16,8 @@ class MergeRequestContextCommitDiffFile < ApplicationRecord
def self.bulk_insert(*args)
Gitlab::Database.bulk_insert('merge_request_context_commit_diff_files', *args) # rubocop:disable Gitlab/BulkInsert
end
def path
new_path.presence || old_path
end
end
......@@ -665,10 +665,6 @@ class MergeRequestDiff < ApplicationRecord
opening_external_diff do
collection = merge_request_diff_files
if options[:include_context_commits]
collection += merge_request.merge_request_context_commit_diff_files
end
if paths = options[:paths]
collection = collection.where('old_path IN (?) OR new_path IN (?)', paths, paths)
end
......
# frozen_string_literal: true
class ContextCommitsDiffEntity < Grape::Entity
include Gitlab::Routing
expose :commits_count
expose :showing_context_commits_diff do |_, options|
options[:only_context_commits]
end
expose :diffs_path do |diff|
merge_request = diff.merge_request
project = merge_request.target_project
next unless project
diffs_project_merge_request_path(project, merge_request, only_context_commits: true)
end
end
\ No newline at end of file
......@@ -84,6 +84,15 @@ class DiffsEntity < Grape::Entity
project_blob_path(merge_request.project, merge_request.diff_head_sha)
end
expose :context_commits_diff, if: -> (_) { merge_request&.project&.context_commits_enabled? } do |diffs, options|
next unless merge_request.context_commits_diff.commits_count > 0
ContextCommitsDiffEntity.represent(
merge_request.context_commits_diff,
options
)
end
def merge_request
options[:merge_request]
end
......
......@@ -40,7 +40,7 @@
= render "projects/merge_requests/tabs/tab", name: "diffs", class: "diffs-tab", id: "diffs-tab", qa_selector: "diffs_tab" do
= tab_link_for @merge_request, :diffs do
= _("Changes")
%span.badge.badge-pill.gl-badge.badge-muted.sm= @merge_request.diff_size
%span.badge.badge-pill.gl-badge.badge-muted.sm= @diffs_count
.d-flex.flex-wrap.align-items-center.justify-content-lg-end
#js-vue-discussion-counter
......
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