Collapse large diffs by default
When rendering a list of diff files, skip those where the diff is over 10 KB and provide an endpoint to render individually instead.
This commit is contained in:
parent
2c650b6f30
commit
b6b26692ea
|
@ -32,6 +32,8 @@ v 8.10.0 (unreleased)
|
|||
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
|
||||
- PipelinesFinder uses git cache data
|
||||
- Throttle the update of `project.pushes_since_gc` to 1 minute.
|
||||
- Allow expanding and collapsing files in diff view (!4990)
|
||||
- Collapse large diffs by default (!4990)
|
||||
- Check for conflicts with existing Project's wiki path when creating a new project.
|
||||
- Show last push widget in upstream after push to fork
|
||||
- Don't instantiate a git tree on Projects show default view
|
||||
|
|
|
@ -19,7 +19,7 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
|
||||
@grouped_diff_notes = commit.notes.grouped_diff_notes
|
||||
@notes = commit.notes.non_diff_notes.fresh
|
||||
|
||||
|
||||
Banzai::NoteRenderer.render(
|
||||
@grouped_diff_notes.values.flatten + @notes,
|
||||
@project,
|
||||
|
@ -41,6 +41,24 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def diff_for_path
|
||||
return git_not_found! unless commit
|
||||
|
||||
opts = diff_options
|
||||
opts[:ignore_whitespace_change] = true if params[:format] == 'diff'
|
||||
|
||||
diffs = commit.diffs(opts.merge(paths: [params[:path]]))
|
||||
diff_refs = [commit.parent || commit, commit]
|
||||
|
||||
@comments_target = {
|
||||
noteable_type: 'Commit',
|
||||
commit_id: @commit.id
|
||||
}
|
||||
@grouped_diff_notes = {}
|
||||
|
||||
render_diff_for_path(diffs, diff_refs, @project)
|
||||
end
|
||||
|
||||
def builds
|
||||
end
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
# Authorize
|
||||
before_action :require_non_empty_project
|
||||
before_action :authorize_download_code!
|
||||
before_action :assign_ref_vars, only: [:index, :show]
|
||||
before_action :assign_ref_vars, only: [:index, :show, :diff_for_path]
|
||||
before_action :merge_request, only: [:index, :show]
|
||||
|
||||
def index
|
||||
|
@ -35,6 +35,22 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def diff_for_path
|
||||
compare = CompareService.new.
|
||||
execute(@project, @head_ref, @project, @base_ref, diff_options)
|
||||
|
||||
return render_404 unless compare
|
||||
|
||||
@commit = @project.commit(@head_ref)
|
||||
@base_commit = @project.merge_base_commit(@base_ref, @head_ref)
|
||||
diffs = compare.diffs(diff_options.merge(paths: [params[:path]]))
|
||||
|
||||
@diff_notes_disabled = true
|
||||
@grouped_diff_notes = {}
|
||||
|
||||
render_diff_for_path(diffs, [@base_commit, @commit], @project)
|
||||
end
|
||||
|
||||
def create
|
||||
redirect_to namespace_project_compare_path(@project.namespace, @project,
|
||||
params[:from], params[:to])
|
||||
|
|
|
@ -13,6 +13,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds]
|
||||
before_action :define_show_vars, only: [:show, :diffs, :commits, :builds]
|
||||
before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
|
||||
before_action :define_commit_vars, only: [:diffs]
|
||||
before_action :define_diff_comment_vars, only: [:diffs]
|
||||
before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds]
|
||||
|
||||
# Allow read any merge_request
|
||||
|
@ -58,7 +60,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
||||
|
||||
format.json do
|
||||
render json: @merge_request
|
||||
end
|
||||
|
@ -80,32 +82,32 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
def diffs
|
||||
apply_diff_view_cookie!
|
||||
|
||||
@commit = @merge_request.diff_head_commit
|
||||
@base_commit = @merge_request.diff_base_commit || @merge_request.likely_diff_base_commit
|
||||
|
||||
@comments_target = {
|
||||
noteable_type: 'MergeRequest',
|
||||
noteable_id: @merge_request.id
|
||||
}
|
||||
|
||||
@use_legacy_diff_notes = !@merge_request.support_new_diff_notes?
|
||||
@grouped_diff_notes = @merge_request.notes.grouped_diff_notes
|
||||
|
||||
Banzai::NoteRenderer.render(
|
||||
@grouped_diff_notes.values.flatten,
|
||||
@project,
|
||||
current_user,
|
||||
@path,
|
||||
@project_wiki,
|
||||
@ref
|
||||
)
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
|
||||
end
|
||||
end
|
||||
|
||||
# With an ID param, loads the MR at that ID. Otherwise, accepts the same params as #new
|
||||
# and uses that (unsaved) MR.
|
||||
#
|
||||
def diff_for_path
|
||||
if params[:id]
|
||||
merge_request
|
||||
define_diff_comment_vars
|
||||
else
|
||||
build_merge_request
|
||||
@diff_notes_disabled = true
|
||||
@grouped_diff_notes = {}
|
||||
end
|
||||
|
||||
define_commit_vars
|
||||
diffs = @merge_request.diffs(diff_options.merge(paths: [params[:path]]))
|
||||
diff_refs = @merge_request.diff_refs
|
||||
|
||||
render_diff_for_path(diffs, diff_refs, @merge_request.project)
|
||||
end
|
||||
|
||||
def commits
|
||||
respond_to do |format|
|
||||
format.html { render 'show' }
|
||||
|
@ -121,8 +123,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
|
||||
@merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
|
||||
build_merge_request
|
||||
@noteable = @merge_request
|
||||
|
||||
@target_branches = if @merge_request.target_project
|
||||
|
@ -380,6 +381,30 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
closes_issues
|
||||
end
|
||||
|
||||
def define_commit_vars
|
||||
@commit = @merge_request.diff_head_commit
|
||||
@base_commit = @merge_request.diff_base_commit || @merge_request.likely_diff_base_commit
|
||||
end
|
||||
|
||||
def define_diff_comment_vars
|
||||
@comments_target = {
|
||||
noteable_type: 'MergeRequest',
|
||||
noteable_id: @merge_request.id
|
||||
}
|
||||
|
||||
@use_legacy_diff_notes = !@merge_request.support_new_diff_notes?
|
||||
@grouped_diff_notes = @merge_request.notes.grouped_diff_notes
|
||||
|
||||
Banzai::NoteRenderer.render(
|
||||
@grouped_diff_notes.values.flatten,
|
||||
@project,
|
||||
current_user,
|
||||
@path,
|
||||
@project_wiki,
|
||||
@ref
|
||||
)
|
||||
end
|
||||
|
||||
def invalid_mr
|
||||
# Render special view for MR with removed source or target branch
|
||||
render 'invalid'
|
||||
|
@ -408,4 +433,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
params[:merge_when_build_succeeds].present? &&
|
||||
@merge_request.pipeline && @merge_request.pipeline.active?
|
||||
end
|
||||
|
||||
def build_merge_request
|
||||
params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
|
||||
@merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,6 +8,25 @@ module DiffHelper
|
|||
[marked_old_line, marked_new_line]
|
||||
end
|
||||
|
||||
def render_diff_for_path(diffs, diff_refs, project)
|
||||
diff_file = safe_diff_files(diffs, diff_refs).first
|
||||
|
||||
return render_404 unless diff_file
|
||||
|
||||
diff_commit = commit_for_diff(diff_file)
|
||||
blob = project.repository.blob_for_diff(diff_commit, diff_file)
|
||||
|
||||
locals = {
|
||||
diff_file: diff_file,
|
||||
diff_commit: diff_commit,
|
||||
diff_refs: diff_refs,
|
||||
blob: blob,
|
||||
project: project
|
||||
}
|
||||
|
||||
render json: { html: view_to_html_string('projects/diffs/_content', locals) }
|
||||
end
|
||||
|
||||
def diff_view
|
||||
diff_views = %w(inline parallel)
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ class MergeRequest < ActiveRecord::Base
|
|||
after_create :create_merge_request_diff, unless: :importing?
|
||||
after_update :update_merge_request_diff
|
||||
|
||||
delegate :commits, :diffs, :real_size, to: :merge_request_diff, prefix: nil
|
||||
delegate :commits, :real_size, to: :merge_request_diff, prefix: nil
|
||||
|
||||
# When this attribute is true some MR validation is ignored
|
||||
# It allows us to close or modify broken merge requests
|
||||
|
@ -164,6 +164,10 @@ class MergeRequest < ActiveRecord::Base
|
|||
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
|
||||
end
|
||||
|
||||
def diffs(*args)
|
||||
merge_request_diff ? merge_request_diff.diffs(*args) : compare.diffs(*args)
|
||||
end
|
||||
|
||||
def diff_size
|
||||
merge_request_diff.size
|
||||
end
|
||||
|
|
|
@ -144,6 +144,12 @@ class MergeRequestDiff < ActiveRecord::Base
|
|||
|
||||
def load_diffs(raw, options)
|
||||
if raw.respond_to?(:each)
|
||||
if options[:paths]
|
||||
raw = raw.select do |diff|
|
||||
options[:paths].include?(diff[:new_path])
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::Git::DiffCollection.new(raw, options)
|
||||
else
|
||||
Gitlab::Git::DiffCollection.new([])
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
.diff-content.diff-wrap-lines
|
||||
- # Skip all non non-supported blobs
|
||||
- return unless blob.respond_to?(:text?)
|
||||
- if diff_file.too_large?
|
||||
.nothing-here-block This diff could not be displayed because it is too large.
|
||||
- elsif blob.only_display_raw?
|
||||
.nothing-here-block This file is too large to display.
|
||||
- elsif blob_text_viewable?(blob)
|
||||
- if !project.repository.diffable?(blob)
|
||||
.nothing-here-block This diff was suppressed by a .gitattributes entry.
|
||||
- elsif diff_file.diff_lines.length > 0
|
||||
- if diff_view == 'parallel'
|
||||
= render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob
|
||||
- else
|
||||
= render "projects/diffs/text_file", diff_file: diff_file
|
||||
- else
|
||||
- if diff_file.mode_changed?
|
||||
.nothing-here-block File mode changed
|
||||
- elsif diff_file.renamed_file
|
||||
.nothing-here-block File moved
|
||||
- elsif blob.image?
|
||||
- old_blob = diff_file.old_blob(diff_commit)
|
||||
= render "projects/diffs/image", diff_file: diff_file, old_file: old_blob, file: blob
|
||||
- else
|
||||
.nothing-here-block No preview for this file type
|
|
@ -16,28 +16,9 @@
|
|||
|
||||
= view_file_btn(diff_commit.id, diff_file, project)
|
||||
|
||||
.diff-content.diff-wrap-lines
|
||||
- # Skip all non non-supported blobs
|
||||
- return unless blob.respond_to?(:text?)
|
||||
- if diff_file.too_large?
|
||||
.nothing-here-block This diff could not be displayed because it is too large.
|
||||
- elsif blob.only_display_raw?
|
||||
.nothing-here-block This file is too large to display.
|
||||
- elsif blob_text_viewable?(blob)
|
||||
- if !project.repository.diffable?(blob)
|
||||
.nothing-here-block This diff was suppressed by a .gitattributes entry.
|
||||
- elsif diff_file.diff_lines.length > 0
|
||||
- if diff_view == 'parallel'
|
||||
= render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i
|
||||
- else
|
||||
= render "projects/diffs/text_file", diff_file: diff_file, index: i
|
||||
- else
|
||||
- if diff_file.mode_changed?
|
||||
.nothing-here-block File mode changed
|
||||
- elsif diff_file.renamed_file
|
||||
.nothing-here-block File moved
|
||||
- elsif blob.image?
|
||||
- old_blob = diff_file.old_blob(diff_commit)
|
||||
= render "projects/diffs/image", diff_file: diff_file, old_file: old_blob, file: blob, index: i
|
||||
- else
|
||||
.nothing-here-block No preview for this file type
|
||||
- if diff_file.collapsed_by_default?
|
||||
- url = url_for(params.merge(action: :diff_for_path, path: diff_file.file_path, format: nil))
|
||||
.diff-content.diff-wrap-lines{data: { diff_for_path: url }}
|
||||
.nothing-here-block File hidden by default; content for this element available at #{url}
|
||||
- else
|
||||
= render 'projects/diffs/content', diff_file: diff_file, diff_commit: diff_commit, diff_refs: diff_refs, blob: blob, project: project
|
||||
|
|
|
@ -615,10 +615,18 @@ Rails.application.routes.draw do
|
|||
post :retry_builds
|
||||
post :revert
|
||||
post :cherry_pick
|
||||
get '/diffs/*path', action: :diff_for_path, constraints: { format: false }
|
||||
end
|
||||
end
|
||||
|
||||
resources :compare, only: [:index, :create]
|
||||
resources :compare, only: [:index, :create] do
|
||||
collection do
|
||||
get '/diffs/*path', action: :diff_for_path, constraints: { format: false }
|
||||
end
|
||||
end
|
||||
|
||||
get '/compare/:from...:to', to: 'compare#show', as: 'compare', constraints: { from: /.+/, to: /.+/ }
|
||||
|
||||
resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
|
||||
|
||||
resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
|
||||
|
@ -629,9 +637,6 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
get '/compare/:from...:to' => 'compare#show', :as => 'compare',
|
||||
:constraints => { from: /.+/, to: /.+/ }
|
||||
|
||||
resources :snippets, constraints: { id: /\d+/ } do
|
||||
member do
|
||||
get 'raw'
|
||||
|
@ -706,12 +711,14 @@ Rails.application.routes.draw do
|
|||
post :toggle_subscription
|
||||
post :toggle_award_emoji
|
||||
post :remove_wip
|
||||
get '/diffs/*path', action: :diff_for_path, constraints: { format: false }
|
||||
end
|
||||
|
||||
collection do
|
||||
get :branch_from
|
||||
get :branch_to
|
||||
get :update_branches
|
||||
get '/diffs/*path', action: :diff_for_path, constraints: { format: false }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -68,6 +68,10 @@ module Gitlab
|
|||
@lines ||= Gitlab::Diff::Parser.new.parse(raw_diff.each_line).to_a
|
||||
end
|
||||
|
||||
def collapsed_by_default?
|
||||
diff.diff.bytesize > 10240 # 10 KB
|
||||
end
|
||||
|
||||
def highlighted_diff_lines
|
||||
@highlighted_diff_lines ||= Gitlab::Diff::Highlight.new(self, repository: self.repository).highlight
|
||||
end
|
||||
|
|
|
@ -1,246 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Projects::CommitController do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
let(:commit) { project.commit("master") }
|
||||
let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
|
||||
let(:master_pickable_commit) { project.commit(master_pickable_sha) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
project.team << [user, :master]
|
||||
end
|
||||
|
||||
describe "#show" do
|
||||
shared_examples "export as" do |format|
|
||||
it "should generally work" do
|
||||
get(:show,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id,
|
||||
format: format)
|
||||
|
||||
expect(response).to be_success
|
||||
end
|
||||
|
||||
it "should generate it" do
|
||||
expect_any_instance_of(Commit).to receive(:"to_#{format}")
|
||||
|
||||
get(:show,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id, format: format)
|
||||
end
|
||||
|
||||
it "should render it" do
|
||||
get(:show,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id, format: format)
|
||||
|
||||
expect(response.body).to eq(commit.send(:"to_#{format}"))
|
||||
end
|
||||
|
||||
it "should not escape Html" do
|
||||
allow_any_instance_of(Commit).to receive(:"to_#{format}").
|
||||
and_return('HTML entities &<>" ')
|
||||
|
||||
get(:show,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id, format: format)
|
||||
|
||||
expect(response.body).not_to include('&')
|
||||
expect(response.body).not_to include('>')
|
||||
expect(response.body).not_to include('<')
|
||||
expect(response.body).not_to include('"')
|
||||
end
|
||||
end
|
||||
|
||||
describe "as diff" do
|
||||
include_examples "export as", :diff
|
||||
let(:format) { :diff }
|
||||
|
||||
it "should really only be a git diff" do
|
||||
get(:show,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id,
|
||||
format: format)
|
||||
|
||||
expect(response.body).to start_with("diff --git")
|
||||
end
|
||||
|
||||
it "should really only be a git diff without whitespace changes" do
|
||||
get(:show,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: '66eceea0db202bb39c4e445e8ca28689645366c5',
|
||||
# id: commit.id,
|
||||
format: format,
|
||||
w: 1)
|
||||
|
||||
expect(response.body).to start_with("diff --git")
|
||||
# without whitespace option, there are more than 2 diff_splits
|
||||
diff_splits = assigns(:diffs).first.diff.split("\n")
|
||||
expect(diff_splits.length).to be <= 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "as patch" do
|
||||
include_examples "export as", :patch
|
||||
let(:format) { :patch }
|
||||
|
||||
it "should really be a git email patch" do
|
||||
get(:show,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id,
|
||||
format: format)
|
||||
|
||||
expect(response.body).to start_with("From #{commit.id}")
|
||||
end
|
||||
|
||||
it "should contain a git diff" do
|
||||
get(:show,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id,
|
||||
format: format)
|
||||
|
||||
expect(response.body).to match(/^diff --git/)
|
||||
end
|
||||
end
|
||||
|
||||
context 'commit that removes a submodule' do
|
||||
render_views
|
||||
|
||||
let(:fork_project) { create(:forked_project_with_submodules) }
|
||||
let(:commit) { fork_project.commit('remove-submodule') }
|
||||
|
||||
before do
|
||||
fork_project.team << [user, :master]
|
||||
end
|
||||
|
||||
it 'renders it' do
|
||||
get(:show,
|
||||
namespace_id: fork_project.namespace.to_param,
|
||||
project_id: fork_project.to_param,
|
||||
id: commit.id)
|
||||
|
||||
expect(response).to be_success
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#branches" do
|
||||
it "contains branch and tags information" do
|
||||
get(:branches,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id)
|
||||
|
||||
expect(assigns(:branches)).to include("master", "feature_conflict")
|
||||
expect(assigns(:tags)).to include("v1.1.0")
|
||||
end
|
||||
end
|
||||
|
||||
describe '#revert' do
|
||||
context 'when target branch is not provided' do
|
||||
it 'should render the 404 page' do
|
||||
post(:revert,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id)
|
||||
|
||||
expect(response).not_to be_success
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the revert was successful' do
|
||||
it 'should redirect to the commits page' do
|
||||
post(:revert,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: commit.id)
|
||||
|
||||
expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master')
|
||||
expect(flash[:notice]).to eq('The commit has been successfully reverted.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the revert failed' do
|
||||
before do
|
||||
post(:revert,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: commit.id)
|
||||
end
|
||||
|
||||
it 'should redirect to the commit page' do
|
||||
# Reverting a commit that has been already reverted.
|
||||
post(:revert,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: commit.id)
|
||||
|
||||
expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, commit.id)
|
||||
expect(flash[:alert]).to match('Sorry, we cannot revert this commit automatically.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#cherry_pick' do
|
||||
context 'when target branch is not provided' do
|
||||
it 'should render the 404 page' do
|
||||
post(:cherry_pick,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: master_pickable_commit.id)
|
||||
|
||||
expect(response).not_to be_success
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the cherry-pick was successful' do
|
||||
it 'should redirect to the commits page' do
|
||||
post(:cherry_pick,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: master_pickable_commit.id)
|
||||
|
||||
expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master')
|
||||
expect(flash[:notice]).to eq('The commit has been successfully cherry-picked.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the cherry_pick failed' do
|
||||
before do
|
||||
post(:cherry_pick,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: master_pickable_commit.id)
|
||||
end
|
||||
|
||||
it 'should redirect to the commit page' do
|
||||
# Cherry-picking a commit that has been already cherry-picked.
|
||||
post(:cherry_pick,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: master_pickable_commit.id)
|
||||
|
||||
expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, master_pickable_commit.id)
|
||||
expect(flash[:alert]).to match('Sorry, we cannot cherry-pick this commit automatically.')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,9 +1,29 @@
|
|||
require 'rails_helper'
|
||||
require 'spec_helper'
|
||||
|
||||
describe Projects::CommitController do
|
||||
describe 'GET show' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
let(:commit) { project.commit("master") }
|
||||
let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
|
||||
let(:master_pickable_commit) { project.commit(master_pickable_sha) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
project.team << [user, :master]
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
render_views
|
||||
|
||||
def go(extra_params = {})
|
||||
params = {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param
|
||||
}
|
||||
|
||||
get :show, params.merge(extra_params)
|
||||
end
|
||||
|
||||
let(:project) { create(:project) }
|
||||
|
||||
before do
|
||||
|
@ -15,7 +35,7 @@ describe Projects::CommitController do
|
|||
|
||||
context 'with valid id' do
|
||||
it 'responds with 200' do
|
||||
go id: project.commit.id
|
||||
go(id: commit.id)
|
||||
|
||||
expect(response).to be_ok
|
||||
end
|
||||
|
@ -23,27 +43,274 @@ describe Projects::CommitController do
|
|||
|
||||
context 'with invalid id' do
|
||||
it 'responds with 404' do
|
||||
go id: project.commit.id.reverse
|
||||
go(id: commit.id.reverse)
|
||||
|
||||
expect(response).to be_not_found
|
||||
end
|
||||
end
|
||||
|
||||
it 'handles binary files' do
|
||||
get(:show,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: TestEnv::BRANCH_SHA['binary-encoding'],
|
||||
format: "html")
|
||||
go(id: TestEnv::BRANCH_SHA['binary-encoding'], format: 'html')
|
||||
|
||||
expect(response).to be_success
|
||||
end
|
||||
|
||||
def go(id:)
|
||||
get :show,
|
||||
shared_examples "export as" do |format|
|
||||
it "should generally work" do
|
||||
go(id: commit.id, format: format)
|
||||
|
||||
expect(response).to be_success
|
||||
end
|
||||
|
||||
it "should generate it" do
|
||||
expect_any_instance_of(Commit).to receive(:"to_#{format}")
|
||||
|
||||
go(id: commit.id, format: format)
|
||||
end
|
||||
|
||||
it "should render it" do
|
||||
go(id: commit.id, format: format)
|
||||
|
||||
expect(response.body).to eq(commit.send(:"to_#{format}"))
|
||||
end
|
||||
|
||||
it "should not escape Html" do
|
||||
allow_any_instance_of(Commit).to receive(:"to_#{format}").
|
||||
and_return('HTML entities &<>" ')
|
||||
|
||||
go(id: commit.id, format: format)
|
||||
|
||||
expect(response.body).not_to include('&')
|
||||
expect(response.body).not_to include('>')
|
||||
expect(response.body).not_to include('<')
|
||||
expect(response.body).not_to include('"')
|
||||
end
|
||||
end
|
||||
|
||||
describe "as diff" do
|
||||
include_examples "export as", :diff
|
||||
let(:format) { :diff }
|
||||
|
||||
it "should really only be a git diff" do
|
||||
go(id: commit.id, format: format)
|
||||
|
||||
expect(response.body).to start_with("diff --git")
|
||||
end
|
||||
|
||||
it "should really only be a git diff without whitespace changes" do
|
||||
go(id: '66eceea0db202bb39c4e445e8ca28689645366c5', format: format, w: 1)
|
||||
|
||||
expect(response.body).to start_with("diff --git")
|
||||
# without whitespace option, there are more than 2 diff_splits
|
||||
diff_splits = assigns(:diffs).first.diff.split("\n")
|
||||
expect(diff_splits.length).to be <= 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "as patch" do
|
||||
include_examples "export as", :patch
|
||||
let(:format) { :patch }
|
||||
|
||||
it "should really be a git email patch" do
|
||||
go(id: commit.id, format: format)
|
||||
|
||||
expect(response.body).to start_with("From #{commit.id}")
|
||||
end
|
||||
|
||||
it "should contain a git diff" do
|
||||
go(id: commit.id, format: format)
|
||||
|
||||
expect(response.body).to match(/^diff --git/)
|
||||
end
|
||||
end
|
||||
|
||||
context 'commit that removes a submodule' do
|
||||
render_views
|
||||
|
||||
let(:fork_project) { create(:forked_project_with_submodules, visibility_level: 20) }
|
||||
let(:commit) { fork_project.commit('remove-submodule') }
|
||||
|
||||
it 'renders it' do
|
||||
get(:show,
|
||||
namespace_id: fork_project.namespace.to_param,
|
||||
project_id: fork_project.to_param,
|
||||
id: commit.id)
|
||||
|
||||
expect(response).to be_success
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#branches" do
|
||||
it "contains branch and tags information" do
|
||||
get(:branches,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id)
|
||||
|
||||
expect(assigns(:branches)).to include("master", "feature_conflict")
|
||||
expect(assigns(:tags)).to include("v1.1.0")
|
||||
end
|
||||
end
|
||||
|
||||
describe '#revert' do
|
||||
context 'when target branch is not provided' do
|
||||
it 'should render the 404 page' do
|
||||
post(:revert,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: commit.id)
|
||||
|
||||
expect(response).not_to be_success
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the revert was successful' do
|
||||
it 'should redirect to the commits page' do
|
||||
post(:revert,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: commit.id)
|
||||
|
||||
expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master')
|
||||
expect(flash[:notice]).to eq('The commit has been successfully reverted.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the revert failed' do
|
||||
before do
|
||||
post(:revert,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: commit.id)
|
||||
end
|
||||
|
||||
it 'should redirect to the commit page' do
|
||||
# Reverting a commit that has been already reverted.
|
||||
post(:revert,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: commit.id)
|
||||
|
||||
expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, commit.id)
|
||||
expect(flash[:alert]).to match('Sorry, we cannot revert this commit automatically.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#cherry_pick' do
|
||||
context 'when target branch is not provided' do
|
||||
it 'should render the 404 page' do
|
||||
post(:cherry_pick,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: master_pickable_commit.id)
|
||||
|
||||
expect(response).not_to be_success
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the cherry-pick was successful' do
|
||||
it 'should redirect to the commits page' do
|
||||
post(:cherry_pick,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: master_pickable_commit.id)
|
||||
|
||||
expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master')
|
||||
expect(flash[:notice]).to eq('The commit has been successfully cherry-picked.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the cherry_pick failed' do
|
||||
before do
|
||||
post(:cherry_pick,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: master_pickable_commit.id)
|
||||
end
|
||||
|
||||
it 'should redirect to the commit page' do
|
||||
# Cherry-picking a commit that has been already cherry-picked.
|
||||
post(:cherry_pick,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
target_branch: 'master',
|
||||
id: master_pickable_commit.id)
|
||||
|
||||
expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, master_pickable_commit.id)
|
||||
expect(flash[:alert]).to match('Sorry, we cannot cherry-pick this commit automatically.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #diff_for_path' do
|
||||
def diff_for_path(extra_params = {})
|
||||
params = {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: id
|
||||
project_id: project.to_param
|
||||
}
|
||||
|
||||
get :diff_for_path, params.merge(extra_params)
|
||||
end
|
||||
|
||||
let(:existing_path) { '.gitmodules' }
|
||||
|
||||
context 'when the commit exists' do
|
||||
context 'when the user has access to the project' do
|
||||
context 'when the path exists in the diff' do
|
||||
it 'enables diff notes' do
|
||||
diff_for_path(id: commit.id, path: existing_path)
|
||||
|
||||
expect(assigns(:diff_notes_disabled)).to be_falsey
|
||||
expect(assigns(:comments_target)).to eq(noteable_type: 'Commit',
|
||||
commit_id: commit.id)
|
||||
end
|
||||
|
||||
it 'only renders the diffs for the path given' do
|
||||
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
|
||||
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
|
||||
meth.call(diffs, diff_refs, project)
|
||||
end
|
||||
|
||||
diff_for_path(id: commit.id, path: existing_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the path does not exist in the diff' do
|
||||
before { diff_for_path(id: commit.id, path: existing_path.succ) }
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user does not have access to the project' do
|
||||
before do
|
||||
project.team.truncate
|
||||
diff_for_path(id: commit.id, path: existing_path)
|
||||
end
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the commit does not exist' do
|
||||
before { diff_for_path(id: commit.id.succ, path: existing_path) }
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -64,4 +64,73 @@ describe Projects::CompareController do
|
|||
expect(assigns(:commits)).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #diff_for_path' do
|
||||
def diff_for_path(extra_params = {})
|
||||
params = {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param
|
||||
}
|
||||
|
||||
get :diff_for_path, params.merge(extra_params)
|
||||
end
|
||||
|
||||
let(:existing_path) { 'files/ruby/feature.rb' }
|
||||
|
||||
context 'when the from and to refs exist' do
|
||||
context 'when the user has access to the project' do
|
||||
context 'when the path exists in the diff' do
|
||||
it 'disables diff notes' do
|
||||
diff_for_path(from: ref_from, to: ref_to, path: existing_path)
|
||||
|
||||
expect(assigns(:diff_notes_disabled)).to be_truthy
|
||||
end
|
||||
|
||||
it 'only renders the diffs for the path given' do
|
||||
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
|
||||
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
|
||||
meth.call(diffs, diff_refs, project)
|
||||
end
|
||||
|
||||
diff_for_path(from: ref_from, to: ref_to, path: existing_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the path does not exist in the diff' do
|
||||
before { diff_for_path(from: ref_from, to: ref_to, path: existing_path.succ) }
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user does not have access to the project' do
|
||||
before do
|
||||
project.team.truncate
|
||||
diff_for_path(from: ref_from, to: ref_to, path: existing_path)
|
||||
end
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the from ref does not exist' do
|
||||
before { diff_for_path(from: ref_from.succ, to: ref_to, path: existing_path) }
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the to ref does not exist' do
|
||||
before { diff_for_path(from: ref_from, to: ref_to.succ, path: existing_path) }
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -289,101 +289,215 @@ describe Projects::MergeRequestsController do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'GET diffs' do
|
||||
def go(format: 'html')
|
||||
get :diffs,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: merge_request.iid,
|
||||
format: format
|
||||
end
|
||||
|
||||
context 'as html' do
|
||||
it 'renders the diff template' do
|
||||
go
|
||||
|
||||
expect(response).to render_template('diffs')
|
||||
end
|
||||
end
|
||||
|
||||
context 'as json' do
|
||||
it 'renders the diffs template to a string' do
|
||||
go format: 'json'
|
||||
|
||||
expect(response).to render_template('projects/merge_requests/show/_diffs')
|
||||
expect(JSON.parse(response.body)).to have_key('html')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with forked projects with submodules' do
|
||||
render_views
|
||||
|
||||
let(:project) { create(:project) }
|
||||
let(:fork_project) { create(:forked_project_with_submodules) }
|
||||
let(:merge_request) { create(:merge_request_with_diffs, source_project: fork_project, source_branch: 'add-submodule-version-bump', target_branch: 'master', target_project: project) }
|
||||
|
||||
before do
|
||||
fork_project.build_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id)
|
||||
fork_project.save
|
||||
merge_request.reload
|
||||
end
|
||||
|
||||
it 'renders' do
|
||||
go format: 'json'
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.body).to have_content('Subproject commit')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET diffs with ignore_whitespace_change' do
|
||||
def go(format: 'html')
|
||||
get :diffs,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: merge_request.iid,
|
||||
format: format,
|
||||
w: 1
|
||||
end
|
||||
|
||||
context 'as html' do
|
||||
it 'renders the diff template' do
|
||||
go
|
||||
|
||||
expect(response).to render_template('diffs')
|
||||
end
|
||||
end
|
||||
|
||||
context 'as json' do
|
||||
it 'renders the diffs template to a string' do
|
||||
go format: 'json'
|
||||
|
||||
expect(response).to render_template('projects/merge_requests/show/_diffs')
|
||||
expect(JSON.parse(response.body)).to have_key('html')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET diffs with view' do
|
||||
describe 'GET #diffs' do
|
||||
def go(extra_params = {})
|
||||
params = {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: merge_request.iid
|
||||
project_id: project.to_param,
|
||||
id: merge_request.iid
|
||||
}
|
||||
|
||||
get :diffs, params.merge(extra_params)
|
||||
end
|
||||
|
||||
it 'saves the preferred diff view in a cookie' do
|
||||
go view: 'parallel'
|
||||
context 'with default params' do
|
||||
context 'as html' do
|
||||
before { go(format: 'html') }
|
||||
|
||||
expect(response.cookies['diff_view']).to eq('parallel')
|
||||
it 'renders the diff template' do
|
||||
expect(response).to render_template('diffs')
|
||||
end
|
||||
end
|
||||
|
||||
context 'as json' do
|
||||
before { go(format: 'json') }
|
||||
|
||||
it 'renders the diffs template to a string' do
|
||||
expect(response).to render_template('projects/merge_requests/show/_diffs')
|
||||
expect(JSON.parse(response.body)).to have_key('html')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with forked projects with submodules' do
|
||||
render_views
|
||||
|
||||
let(:project) { create(:project) }
|
||||
let(:fork_project) { create(:forked_project_with_submodules) }
|
||||
let(:merge_request) { create(:merge_request_with_diffs, source_project: fork_project, source_branch: 'add-submodule-version-bump', target_branch: 'master', target_project: project) }
|
||||
|
||||
before do
|
||||
fork_project.build_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id)
|
||||
fork_project.save
|
||||
merge_request.reload
|
||||
go(format: 'json')
|
||||
end
|
||||
|
||||
it 'renders' do
|
||||
expect(response).to be_success
|
||||
expect(response.body).to have_content('Subproject commit')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with ignore_whitespace_change' do
|
||||
context 'as html' do
|
||||
before { go(format: 'html', w: 1) }
|
||||
|
||||
it 'renders the diff template' do
|
||||
expect(response).to render_template('diffs')
|
||||
end
|
||||
end
|
||||
|
||||
context 'as json' do
|
||||
before { go(format: 'json', w: 1) }
|
||||
|
||||
it 'renders the diffs template to a string' do
|
||||
expect(response).to render_template('projects/merge_requests/show/_diffs')
|
||||
expect(JSON.parse(response.body)).to have_key('html')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with view' do
|
||||
before { go(view: 'parallel') }
|
||||
|
||||
it 'saves the preferred diff view in a cookie' do
|
||||
expect(response.cookies['diff_view']).to eq('parallel')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET commits' do
|
||||
describe 'GET #diff_for_path' do
|
||||
def diff_for_path(extra_params = {})
|
||||
params = {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param
|
||||
}
|
||||
|
||||
get :diff_for_path, params.merge(extra_params)
|
||||
end
|
||||
|
||||
context 'when an ID param is passed' do
|
||||
let(:existing_path) { 'files/ruby/popen.rb' }
|
||||
|
||||
context 'when the merge request exists' do
|
||||
context 'when the user can view the merge request' do
|
||||
context 'when the path exists in the diff' do
|
||||
it 'enables diff notes' do
|
||||
diff_for_path(id: merge_request.iid, path: existing_path)
|
||||
|
||||
expect(assigns(:diff_notes_disabled)).to be_falsey
|
||||
expect(assigns(:comments_target)).to eq(noteable_type: 'MergeRequest',
|
||||
noteable_id: merge_request.id)
|
||||
end
|
||||
|
||||
it 'only renders the diffs for the path given' do
|
||||
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
|
||||
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
|
||||
meth.call(diffs, diff_refs, project)
|
||||
end
|
||||
|
||||
diff_for_path(id: merge_request.iid, path: existing_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the path does not exist in the diff' do
|
||||
before { diff_for_path(id: merge_request.iid, path: 'files/ruby/nopen.rb') }
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user cannot view the merge request' do
|
||||
before do
|
||||
project.team.truncate
|
||||
diff_for_path(id: merge_request.iid, path: existing_path)
|
||||
end
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the merge request does not exist' do
|
||||
before { diff_for_path(id: merge_request.iid.succ, path: existing_path) }
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the merge request belongs to a different project' do
|
||||
let(:other_project) { create(:empty_project) }
|
||||
|
||||
before do
|
||||
other_project.team << [user, :master]
|
||||
diff_for_path(id: merge_request.iid, path: existing_path, project_id: other_project.to_param)
|
||||
end
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when source and target params are passed' do
|
||||
let(:existing_path) { 'files/ruby/feature.rb' }
|
||||
|
||||
context 'when both branches are in the same project' do
|
||||
it 'disables diff notes' do
|
||||
diff_for_path(path: existing_path, merge_request: { source_branch: 'feature', target_branch: 'master' })
|
||||
|
||||
expect(assigns(:diff_notes_disabled)).to be_truthy
|
||||
end
|
||||
|
||||
it 'only renders the diffs for the path given' do
|
||||
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
|
||||
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
|
||||
meth.call(diffs, diff_refs, project)
|
||||
end
|
||||
|
||||
diff_for_path(path: existing_path, merge_request: { source_branch: 'feature', target_branch: 'master' })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the source branch is in a different project to the target' do
|
||||
let(:other_project) { create(:project) }
|
||||
|
||||
before { other_project.team << [user, :master] }
|
||||
|
||||
context 'when the path exists in the diff' do
|
||||
it 'disables diff notes' do
|
||||
diff_for_path(path: existing_path, merge_request: { source_project: other_project, source_branch: 'feature', target_branch: 'master' })
|
||||
|
||||
expect(assigns(:diff_notes_disabled)).to be_truthy
|
||||
end
|
||||
|
||||
it 'only renders the diffs for the path given' do
|
||||
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
|
||||
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
|
||||
meth.call(diffs, diff_refs, project)
|
||||
end
|
||||
|
||||
diff_for_path(path: existing_path, merge_request: { source_project: other_project, source_branch: 'feature', target_branch: 'master' })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the path does not exist in the diff' do
|
||||
before { diff_for_path(path: 'files/ruby/nopen.rb', merge_request: { source_project: other_project, source_branch: 'feature', target_branch: 'master' }) }
|
||||
|
||||
it 'returns a 404' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #commits' do
|
||||
def go(format: 'html')
|
||||
get :commits,
|
||||
namespace_id: project.namespace.to_param,
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe MergeRequestDiff, models: true do
|
||||
describe '#diffs' do
|
||||
let(:mr) { create(:merge_request, :with_diffs) }
|
||||
let(:mr_diff) { mr.merge_request_diff }
|
||||
|
||||
context 'when the :ignore_whitespace_change option is set' do
|
||||
it 'creates a new compare object instead of loading from the DB' do
|
||||
expect(mr_diff).not_to receive(:load_diffs)
|
||||
expect(Gitlab::Git::Compare).to receive(:new).and_call_original
|
||||
|
||||
mr_diff.diffs(ignore_whitespace_change: true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the raw diffs are empty' do
|
||||
before { mr_diff.update_attributes(st_diffs: '') }
|
||||
|
||||
it 'returns an empty DiffCollection' do
|
||||
expect(mr_diff.diffs).to be_a(Gitlab::Git::DiffCollection)
|
||||
expect(mr_diff.diffs).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the raw diffs exist' do
|
||||
it 'returns the diffs' do
|
||||
expect(mr_diff.diffs).to be_a(Gitlab::Git::DiffCollection)
|
||||
expect(mr_diff.diffs).not_to be_empty
|
||||
end
|
||||
|
||||
context 'when the :paths option is set' do
|
||||
let(:diffs) { mr_diff.diffs(paths: ['.gitignore', 'files/ruby/popen.rb', 'files/ruby/string.rb']) }
|
||||
|
||||
it 'only returns diffs that match the paths given' do
|
||||
expect(diffs.map(&:new_path)).to contain_exactly('.gitignore', 'files/ruby/popen.rb')
|
||||
end
|
||||
|
||||
it 'uses the diffs from the DB' do
|
||||
expect(mr_diff).to receive(:load_diffs)
|
||||
|
||||
diffs
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -116,6 +116,31 @@ describe MergeRequest, models: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#diffs' do
|
||||
let(:merge_request) { build(:merge_request) }
|
||||
let(:options) { { paths: ['a/b', 'b/a', 'c/*'] } }
|
||||
|
||||
context 'when there are MR diffs' do
|
||||
it 'delegates to the MR diffs' do
|
||||
merge_request.merge_request_diff = MergeRequestDiff.new
|
||||
|
||||
expect(merge_request.merge_request_diff).to receive(:diffs).with(options)
|
||||
|
||||
merge_request.diffs(options)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there are no MR diffs' do
|
||||
it 'delegates to the compare object' do
|
||||
merge_request.compare = double(:compare)
|
||||
|
||||
expect(merge_request.compare).to receive(:diffs).with(options)
|
||||
|
||||
merge_request.diffs(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#mr_and_commit_notes" do
|
||||
let!(:merge_request) { create(:merge_request) }
|
||||
|
||||
|
|
Loading…
Reference in New Issue