Commit 7a3aeebb authored by Douwe Maan's avatar Douwe Maan

Merge branch 'dz-mr-version-compare' into 'master'

Allow compare merge request versions

## What does this MR do?

Add new functionality to the merge request page. It allows you easily compare merge request versions in one click.  

## Are there points in the code the reviewer needs to double check?

## Why was this MR needed?

To improve code review experience. 

## Screenshots (if relevant)

See discussion

## Does this MR meet the acceptance criteria?

- [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added
- [x] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
- [x] ~~API support added~~
- Tests
  - [x] Added for this feature/bug
  - [x] All builds are passing
- [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [x] Branch has no merge conflicts with `master` (if you do - rebase it please)
- [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)

## What are the relevant issue numbers?

https://gitlab.com/gitlab-org/gitlab-ce/issues/13570

See merge request !6127
parents d1dbc496 d41fc61f
...@@ -132,6 +132,7 @@ v 8.11.4 ...@@ -132,6 +132,7 @@ v 8.11.4
- Fix issue boards leak private label names and descriptions - Fix issue boards leak private label names and descriptions
- Fix broken gitlab:backup:restore because of bad permissions on repo storage !6098 (Dirk Hörner) - Fix broken gitlab:backup:restore because of bad permissions on repo storage !6098 (Dirk Hörner)
- Remove gitorious. !5866 - Remove gitorious. !5866
- Allow compare merge request versions
v 8.11.3 v 8.11.3
- Allow system info page to handle case where info is unavailable - Allow system info page to handle case where info is unavailable
......
...@@ -375,7 +375,7 @@ ...@@ -375,7 +375,7 @@
} }
} }
.mr-version-switch { .mr-version-controls {
background: $background-color; background: $background-color;
padding: $gl-btn-padding; padding: $gl-btn-padding;
color: $gl-placeholder-color; color: $gl-placeholder-color;
......
...@@ -90,16 +90,27 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -90,16 +90,27 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request.merge_request_diff @merge_request.merge_request_diff
end end
@merge_request_diffs = @merge_request.merge_request_diffs.select_without_diff
@comparable_diffs = @merge_request_diffs.select { |diff| diff.id < @merge_request_diff.id }
if params[:start_sha].present?
@start_sha = params[:start_sha]
@start_version = @comparable_diffs.find { |diff| diff.head_commit_sha == @start_sha }
unless @start_version
render_404
end
end
respond_to do |format| respond_to do |format|
format.html { define_discussion_vars } format.html { define_discussion_vars }
format.json do format.json do
unless @merge_request_diff.latest? if @start_sha
# Disable comments if browsing older version of the diff compared_diff_version
@diff_notes_disabled = true else
original_diff_version
end end
@diffs = @merge_request_diff.diffs(diff_options)
render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") }
end end
end end
...@@ -529,4 +540,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -529,4 +540,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params[:merge_request] ||= ActionController::Parameters.new(source_project: @project) params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
@merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute @merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
end end
def compared_diff_version
@diff_notes_disabled = true
@diffs = @merge_request_diff.compare_with(@start_sha).diffs(diff_options)
end
def original_diff_version
@diff_notes_disabled = !@merge_request_diff.latest?
@diffs = @merge_request_diff.diffs(diff_options)
end
end end
...@@ -2,4 +2,8 @@ module GitHelper ...@@ -2,4 +2,8 @@ module GitHelper
def strip_gpg_signature(text) def strip_gpg_signature(text)
text.gsub(/-----BEGIN PGP SIGNATURE-----(.*)-----END PGP SIGNATURE-----/m, "") text.gsub(/-----BEGIN PGP SIGNATURE-----(.*)-----END PGP SIGNATURE-----/m, "")
end end
def short_sha(text)
Commit.truncate_sha(text)
end
end end
...@@ -100,4 +100,14 @@ module MergeRequestsHelper ...@@ -100,4 +100,14 @@ module MergeRequestsHelper
def merge_request_button_visibility(merge_request, closed) def merge_request_button_visibility(merge_request, closed)
return 'hidden' if merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?) || merge_request.closed_without_fork? return 'hidden' if merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?) || merge_request.closed_without_fork?
end end
def merge_request_version_path(project, merge_request, merge_request_diff, start_sha = nil)
diffs_namespace_project_merge_request_path(
project.namespace, project, merge_request,
diff_id: merge_request_diff.id, start_sha: start_sha)
end
def version_index(merge_request_diff)
@merge_request_diffs.size - @merge_request_diffs.index(merge_request_diff)
end
end end
...@@ -152,6 +152,10 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -152,6 +152,10 @@ class MergeRequestDiff < ActiveRecord::Base
self == merge_request.merge_request_diff self == merge_request.merge_request_diff
end end
def compare_with(sha)
CompareService.new.execute(project, head_commit_sha, project, sha)
end
private private
def dump_commits(commits) def dump_commits(commits)
......
- merge_request_diffs = @merge_request.merge_request_diffs.select_without_diff - if @merge_request_diffs.size > 1
.mr-version-controls
- if merge_request_diffs.size > 1 Changes between
.mr-version-switch %span.dropdown.inline.mr-version-dropdown
Version:
%span.dropdown.inline
%a.btn-link.dropdown-toggle{ data: {toggle: :dropdown} } %a.btn-link.dropdown-toggle{ data: {toggle: :dropdown} }
%strong.monospace< %strong
- if @merge_request_diff.latest? - if @merge_request_diff.latest?
#{"latest"} latest version
- else - else
#{@merge_request_diff.head_commit.short_id} version #{version_index(@merge_request_diff)}
%span.caret %span.caret
%ul.dropdown-menu.dropdown-menu-selectable %ul.dropdown-menu.dropdown-menu-selectable
- merge_request_diffs.each do |merge_request_diff| - @merge_request_diffs.each do |merge_request_diff|
%li %li
= link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request, diff_id: merge_request_diff.id), class: ('is-active' if merge_request_diff == @merge_request_diff) do = link_to merge_request_version_path(@project, @merge_request, merge_request_diff), class: ('is-active' if merge_request_diff == @merge_request_diff) do
%strong.monospace %strong
#{merge_request_diff.head_commit.short_id} - if merge_request_diff.latest?
%br latest version
- else
version #{version_index(merge_request_diff)}
.monospace #{short_sha(merge_request_diff.head_commit_sha)}
%small %small
#{number_with_delimiter(merge_request_diff.commits.count)} #{'commit'.pluralize(merge_request_diff.commits.count)}, #{number_with_delimiter(merge_request_diff.commits.count)} #{'commit'.pluralize(merge_request_diff.commits.count)},
= time_ago_with_tooltip(merge_request_diff.created_at) = time_ago_with_tooltip(merge_request_diff.created_at)
- unless @merge_request_diff.latest? - if @merge_request_diff.base_commit_sha
%span.prepend-left-default and
%span.dropdown.inline.mr-version-compare-dropdown
%a.btn-link.dropdown-toggle{ data: {toggle: :dropdown} }
%strong
- if @start_sha
version #{version_index(@start_version)}
- else
#{@merge_request.target_branch}
%span.caret
%ul.dropdown-menu.dropdown-menu-selectable
- @comparable_diffs.each do |merge_request_diff|
%li
= link_to merge_request_version_path(@project, @merge_request, @merge_request_diff, merge_request_diff.head_commit_sha), class: ('is-active' if merge_request_diff == @start_version) do
%strong
- if merge_request_diff.latest?
latest version
- else
version #{version_index(merge_request_diff)}
.monospace #{short_sha(merge_request_diff.head_commit_sha)}
%small
= time_ago_with_tooltip(merge_request_diff.created_at)
%li
= link_to merge_request_version_path(@project, @merge_request, @merge_request_diff), class: ('is-active' unless @start_sha) do
%strong
#{@merge_request.target_branch} (base)
.monospace #{short_sha(@merge_request_diff.base_commit_sha)}
- unless @merge_request_diff.latest? && !@start_sha
.prepend-top-10
= icon('info-circle') = icon('info-circle')
This version is not the latest one. Comments are disabled - if @start_sha
.pull-right Comments are disabled because you're comparing two versions of this merge request.
%span.monospace - else
#{@merge_request_diff.base_commit.short_id}..#{@merge_request_diff.head_commit.short_id} Comments are disabled because you're viewing an old version of this merge request.
...@@ -12,6 +12,12 @@ can select an older one from version dropdown. ...@@ -12,6 +12,12 @@ can select an older one from version dropdown.
![Merge Request Versions](img/versions.png) ![Merge Request Versions](img/versions.png)
You can also compare the merge request version with older one to see what is
changed since then.
Please note that comments are disabled while viewing outdated merge versions
or comparing to versions other than base.
--- ---
>**Note:** >**Note:**
......
...@@ -11,8 +11,8 @@ feature 'Merge Request versions', js: true, feature: true do ...@@ -11,8 +11,8 @@ feature 'Merge Request versions', js: true, feature: true do
end end
it 'show the latest version of the diff' do it 'show the latest version of the diff' do
page.within '.mr-version-switch' do page.within '.mr-version-dropdown' do
expect(page).to have_content 'Version: latest' expect(page).to have_content 'latest version'
end end
expect(page).to have_content '8 changed files' expect(page).to have_content '8 changed files'
...@@ -20,18 +20,49 @@ feature 'Merge Request versions', js: true, feature: true do ...@@ -20,18 +20,49 @@ feature 'Merge Request versions', js: true, feature: true do
describe 'switch between versions' do describe 'switch between versions' do
before do before do
page.within '.mr-version-switch' do page.within '.mr-version-dropdown' do
find('.btn-link').click find('.btn-link').click
click_link '6f6d7e7e' click_link 'version 1'
end end
end end
it 'should show older version' do it 'should show older version' do
page.within '.mr-version-switch' do page.within '.mr-version-dropdown' do
expect(page).to have_content 'Version: 6f6d7e7e' expect(page).to have_content 'version 1'
end end
expect(page).to have_content '5 changed files' expect(page).to have_content '5 changed files'
end end
it 'show the message about disabled comments' do
expect(page).to have_content 'Comments are disabled'
end
end
describe 'compare with older version' do
before do
page.within '.mr-version-compare-dropdown' do
find('.btn-link').click
click_link 'version 1'
end
end
it 'should has correct value in the compare dropdown' do
page.within '.mr-version-compare-dropdown' do
expect(page).to have_content 'version 1'
end
end
it 'show the message about disabled comments' do
expect(page).to have_content 'Comments are disabled'
end
it 'show diff between new and old version' do
expect(page).to have_content '4 changed files with 15 additions and 6 deletions'
end
it 'show diff between new and old version' do
expect(page).to have_content '4 changed files with 15 additions and 6 deletions'
end
end end
end end
require 'spec_helper'
describe GitHelper do
describe '#short_sha' do
let(:short_sha) { helper.short_sha('d4e043f6c20749a3ab3f4b8e23f2a8979f4b9100') }
it { expect(short_sha).to eq('d4e043f6') }
end
end
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