Commit e1bdb165d147ee65e89d9dacd442d4467d29a86c
Exists in
master
and in
4 other branches
Merge pull request #5014 from bladealslayer/feature/big-commit-improvements
Improved large commit handling.
Showing
11 changed files
with
108 additions
and
9 deletions
Show diff stats
app/assets/javascripts/merge_requests.js.coffee
@@ -11,7 +11,7 @@ class MergeRequest | @@ -11,7 +11,7 @@ class MergeRequest | ||
11 | 11 | ||
12 | constructor: (@opts) -> | 12 | constructor: (@opts) -> |
13 | this.$el = $('.merge-request') | 13 | this.$el = $('.merge-request') |
14 | - @diffs_loaded = false | 14 | + @diffs_loaded = if @opts.action == 'diffs' then true else false |
15 | @commits_loaded = false | 15 | @commits_loaded = false |
16 | 16 | ||
17 | this.activateTab(@opts.action) | 17 | this.activateTab(@opts.action) |
app/contexts/commit_load_context.rb
@@ -20,7 +20,8 @@ class CommitLoadContext < BaseContext | @@ -20,7 +20,8 @@ class CommitLoadContext < BaseContext | ||
20 | result[:notes_count] = project.notes.for_commit_id(commit.id).count | 20 | result[:notes_count] = project.notes.for_commit_id(commit.id).count |
21 | 21 | ||
22 | begin | 22 | begin |
23 | - result[:suppress_diff] = true if commit.diffs.size > Commit::DIFF_SAFE_SIZE && !params[:force_show_diff] | 23 | + result[:suppress_diff] = true if commit.diff_suppress? && !params[:force_show_diff] |
24 | + result[:force_suppress_diff] = commit.diff_force_suppress? | ||
24 | rescue Grit::Git::GitTimeout | 25 | rescue Grit::Git::GitTimeout |
25 | result[:suppress_diff] = true | 26 | result[:suppress_diff] = true |
26 | result[:status] = :huge_commit | 27 | result[:status] = :huge_commit |
app/controllers/projects/commit_controller.rb
@@ -18,6 +18,7 @@ class Projects::CommitController < Projects::ApplicationController | @@ -18,6 +18,7 @@ class Projects::CommitController < Projects::ApplicationController | ||
18 | end | 18 | end |
19 | 19 | ||
20 | @suppress_diff = result[:suppress_diff] | 20 | @suppress_diff = result[:suppress_diff] |
21 | + @force_suppress_diff = result[:force_suppress_diff] | ||
21 | 22 | ||
22 | @note = result[:note] | 23 | @note = result[:note] |
23 | @line_notes = result[:line_notes] | 24 | @line_notes = result[:line_notes] |
app/controllers/projects/compare_controller.rb
@@ -15,6 +15,10 @@ class Projects::CompareController < Projects::ApplicationController | @@ -15,6 +15,10 @@ class Projects::CompareController < Projects::ApplicationController | ||
15 | @diffs = compare.diffs | 15 | @diffs = compare.diffs |
16 | @refs_are_same = compare.same | 16 | @refs_are_same = compare.same |
17 | @line_notes = [] | 17 | @line_notes = [] |
18 | + | ||
19 | + diff_line_count = Commit::diff_line_count(@diffs) | ||
20 | + @suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count) && !params[:force_show_diff] | ||
21 | + @force_suppress_diff = Commit::diff_force_suppress?(@diffs, diff_line_count) | ||
18 | end | 22 | end |
19 | 23 | ||
20 | def create | 24 | def create |
app/controllers/projects/merge_requests_controller.rb
@@ -40,6 +40,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController | @@ -40,6 +40,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController | ||
40 | @comments_target = {noteable_type: 'MergeRequest', | 40 | @comments_target = {noteable_type: 'MergeRequest', |
41 | noteable_id: @merge_request.id} | 41 | noteable_id: @merge_request.id} |
42 | @line_notes = @merge_request.notes.where("line_code is not null") | 42 | @line_notes = @merge_request.notes.where("line_code is not null") |
43 | + | ||
44 | + diff_line_count = Commit::diff_line_count(@merge_request.diffs) | ||
45 | + @suppress_diff = Commit::diff_suppress?(@merge_request.diffs, diff_line_count) && !params[:force_show_diff] | ||
46 | + @force_suppress_diff = Commit::diff_force_suppress?(@merge_request.diffs, diff_line_count) | ||
43 | end | 47 | end |
44 | 48 | ||
45 | def new | 49 | def new |
app/models/commit.rb
@@ -6,15 +6,41 @@ class Commit | @@ -6,15 +6,41 @@ class Commit | ||
6 | 6 | ||
7 | attr_mentionable :safe_message | 7 | attr_mentionable :safe_message |
8 | 8 | ||
9 | - # Safe amount of files with diffs in one commit to render | 9 | + # Safe amount of changes (files and lines) in one commit to render |
10 | # Used to prevent 500 error on huge commits by suppressing diff | 10 | # Used to prevent 500 error on huge commits by suppressing diff |
11 | # | 11 | # |
12 | - DIFF_SAFE_SIZE = 100 | 12 | + # User can force display of diff above this size |
13 | + DIFF_SAFE_FILES = 100 | ||
14 | + DIFF_SAFE_LINES = 5000 | ||
15 | + # Commits above this size will not be rendered in HTML | ||
16 | + DIFF_HARD_LIMIT_FILES = 500 | ||
17 | + DIFF_HARD_LIMIT_LINES = 10000 | ||
13 | 18 | ||
14 | def self.decorate(commits) | 19 | def self.decorate(commits) |
15 | commits.map { |c| self.new(c) } | 20 | commits.map { |c| self.new(c) } |
16 | end | 21 | end |
17 | 22 | ||
23 | + # Calculate number of lines to render for diffs | ||
24 | + def self.diff_line_count(diffs) | ||
25 | + diffs.reduce(0){|sum, d| sum + d.diff.lines.count} | ||
26 | + end | ||
27 | + | ||
28 | + def self.diff_suppress?(diffs, line_count = nil) | ||
29 | + # optimize - check file count first | ||
30 | + return true if diffs.size > DIFF_SAFE_FILES | ||
31 | + | ||
32 | + line_count ||= Commit::diff_line_count(diffs) | ||
33 | + line_count > DIFF_SAFE_LINES | ||
34 | + end | ||
35 | + | ||
36 | + def self.diff_force_suppress?(diffs, line_count = nil) | ||
37 | + # optimize - check file count first | ||
38 | + return true if diffs.size > DIFF_HARD_LIMIT_FILES | ||
39 | + | ||
40 | + line_count ||= Commit::diff_line_count(diffs) | ||
41 | + line_count > DIFF_HARD_LIMIT_LINES | ||
42 | + end | ||
43 | + | ||
18 | attr_accessor :raw | 44 | attr_accessor :raw |
19 | 45 | ||
20 | def initialize(raw_commit) | 46 | def initialize(raw_commit) |
@@ -27,6 +53,19 @@ class Commit | @@ -27,6 +53,19 @@ class Commit | ||
27 | @raw.id | 53 | @raw.id |
28 | end | 54 | end |
29 | 55 | ||
56 | + def diff_line_count | ||
57 | + @diff_line_count ||= Commit::diff_line_count(self.diffs) | ||
58 | + @diff_line_count | ||
59 | + end | ||
60 | + | ||
61 | + def diff_suppress? | ||
62 | + Commit::diff_suppress?(self.diffs, diff_line_count) | ||
63 | + end | ||
64 | + | ||
65 | + def diff_force_suppress? | ||
66 | + Commit::diff_force_suppress?(self.diffs, diff_line_count) | ||
67 | + end | ||
68 | + | ||
30 | # Returns a string describing the commit for use in a link title | 69 | # Returns a string describing the commit for use in a link title |
31 | # | 70 | # |
32 | # Example | 71 | # Example |
app/views/projects/commits/_diffs.html.haml
1 | +- @suppress_diff ||= @suppress_diff || @force_suppress_diff | ||
1 | - if @suppress_diff | 2 | - if @suppress_diff |
2 | .alert.alert-block | 3 | .alert.alert-block |
3 | %p | 4 | %p |
4 | - %strong Warning! Large commit with more than #{Commit::DIFF_SAFE_SIZE} files changed. | ||
5 | - %p To preserve performance the diff is not shown. | 5 | + %strong Warning! This is a large diff. |
6 | %p | 6 | %p |
7 | - But if you still want to see the diff | ||
8 | - = link_to "click this link", project_commit_path(project, @commit, force_show_diff: true), class: "underlined_link" | 7 | + To preserve performance the diff is not shown. |
8 | + - if current_controller?(:commit) or current_controller?(:merge_requests) | ||
9 | + Please, download the diff as | ||
10 | + - if current_controller?(:commit) | ||
11 | + = link_to "plain diff", project_commit_path(@project, @commit, format: :diff), class: "underlined_link" | ||
12 | + or | ||
13 | + = link_to "email patch", project_commit_path(@project, @commit, format: :patch), class: "underlined_link" | ||
14 | + - else | ||
15 | + = link_to "plain diff", project_merge_request_path(@project, @merge_request, format: :diff), class: "underlined_link" | ||
16 | + or | ||
17 | + = link_to "email patch", project_merge_request_path(@project, @merge_request, format: :patch), class: "underlined_link" | ||
18 | + instead. | ||
19 | + - unless @force_suppress_diff | ||
20 | + %p | ||
21 | + If you still want to see the diff | ||
22 | + = link_to "click this link", url_for(force_show_diff: true), class: "underlined_link" | ||
9 | 23 | ||
10 | %p.commit-stat-summary | 24 | %p.commit-stat-summary |
11 | Showing | 25 | Showing |
features/project/commits/commits.feature
@@ -27,3 +27,11 @@ Feature: Project Browse commits | @@ -27,3 +27,11 @@ Feature: Project Browse commits | ||
27 | Scenario: I browse commits stats | 27 | Scenario: I browse commits stats |
28 | Given I visit my project's commits stats page | 28 | Given I visit my project's commits stats page |
29 | Then I see commits stats | 29 | Then I see commits stats |
30 | + | ||
31 | + Scenario: I browse big commit | ||
32 | + Given I visit big commit page | ||
33 | + Then I see big commit warning | ||
34 | + | ||
35 | + Scenario: I browse huge commit | ||
36 | + Given I visit huge commit page | ||
37 | + Then I see huge commit message |
features/steps/project/project_browse_commits.rb
@@ -58,4 +58,24 @@ class ProjectBrowseCommits < Spinach::FeatureSteps | @@ -58,4 +58,24 @@ class ProjectBrowseCommits < Spinach::FeatureSteps | ||
58 | page.should have_content 'Total commits' | 58 | page.should have_content 'Total commits' |
59 | page.should have_content 'Authors' | 59 | page.should have_content 'Authors' |
60 | end | 60 | end |
61 | + | ||
62 | + Given 'I visit big commit page' do | ||
63 | + visit project_commit_path(@project, BigCommits::BIG_COMMIT_ID) | ||
64 | + end | ||
65 | + | ||
66 | + Then 'I see big commit warning' do | ||
67 | + page.should have_content BigCommits::BIG_COMMIT_MESSAGE | ||
68 | + page.should have_content "Warning! This is a large diff" | ||
69 | + page.should have_content "If you still want to see the diff" | ||
70 | + end | ||
71 | + | ||
72 | + Given 'I visit huge commit page' do | ||
73 | + visit project_commit_path(@project, BigCommits::HUGE_COMMIT_ID) | ||
74 | + end | ||
75 | + | ||
76 | + Then 'I see huge commit message' do | ||
77 | + page.should have_content BigCommits::HUGE_COMMIT_MESSAGE | ||
78 | + page.should have_content "Warning! This is a large diff" | ||
79 | + page.should_not have_content "If you still want to see the diff" | ||
80 | + end | ||
61 | end | 81 | end |
features/support/env.rb
@@ -14,7 +14,7 @@ require 'spinach/capybara' | @@ -14,7 +14,7 @@ require 'spinach/capybara' | ||
14 | require 'sidekiq/testing/inline' | 14 | require 'sidekiq/testing/inline' |
15 | 15 | ||
16 | 16 | ||
17 | -%w(valid_commit select2_helper chosen_helper test_env).each do |f| | 17 | +%w(valid_commit big_commits select2_helper chosen_helper test_env).each do |f| |
18 | require Rails.root.join('spec', 'support', f) | 18 | require Rails.root.join('spec', 'support', f) |
19 | end | 19 | end |
20 | 20 |
@@ -0,0 +1,8 @@ | @@ -0,0 +1,8 @@ | ||
1 | +module BigCommits | ||
2 | + HUGE_COMMIT_ID = "7f92534f767fa20357a11c63f973ae3b79cc5b85" | ||
3 | + HUGE_COMMIT_MESSAGE = "pybments.rb version up. gitignore improved" | ||
4 | + | ||
5 | + BIG_COMMIT_ID = "d62200cad430565bd9f80befaf329297120330b5" | ||
6 | + BIG_COMMIT_MESSAGE = "clean-up code" | ||
7 | +end | ||
8 | + |