summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/git/diff.rb2
-rw-r--r--lib/gitlab/git/diff_collection.rb74
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb6
-rw-r--r--lib/gitlab/gitaly_client/diff.rb2
4 files changed, 60 insertions, 24 deletions
diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb
index cf95f673667..9e00abefd02 100644
--- a/lib/gitlab/git/diff.rb
+++ b/lib/gitlab/git/diff.rb
@@ -234,6 +234,8 @@ module Gitlab
@new_file = diff.from_id == BLANK_SHA
@renamed_file = diff.from_path != diff.to_path
@deleted_file = diff.to_id == BLANK_SHA
+
+ collapse! if diff.respond_to?(:collapsed) && diff.collapsed
end
def prune_diff_if_eligible
diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb
index 0d8fe185ac5..87ed9c3ea26 100644
--- a/lib/gitlab/git/diff_collection.rb
+++ b/lib/gitlab/git/diff_collection.rb
@@ -7,16 +7,28 @@ module Gitlab
DEFAULT_LIMITS = { max_files: 100, max_lines: 5000 }.freeze
+ attr_reader :limits
+
+ delegate :max_files, :max_lines, :max_bytes, :safe_max_files, :safe_max_lines, :safe_max_bytes, to: :limits
+
+ def self.collection_limits(options = {})
+ limits = {}
+ limits[:max_files] = options.fetch(:max_files, DEFAULT_LIMITS[:max_files])
+ limits[:max_lines] = options.fetch(:max_lines, DEFAULT_LIMITS[:max_lines])
+ limits[:max_bytes] = limits[:max_files] * 5.kilobytes # Average 5 KB per file
+ limits[:safe_max_files] = [limits[:max_files], DEFAULT_LIMITS[:max_files]].min
+ limits[:safe_max_lines] = [limits[:max_lines], DEFAULT_LIMITS[:max_lines]].min
+ limits[:safe_max_bytes] = limits[:safe_max_files] * 5.kilobytes # Average 5 KB per file
+
+ OpenStruct.new(limits)
+ end
+
def initialize(iterator, options = {})
@iterator = iterator
- @max_files = options.fetch(:max_files, DEFAULT_LIMITS[:max_files])
- @max_lines = options.fetch(:max_lines, DEFAULT_LIMITS[:max_lines])
- @max_bytes = @max_files * 5.kilobytes # Average 5 KB per file
- @safe_max_files = [@max_files, DEFAULT_LIMITS[:max_files]].min
- @safe_max_lines = [@max_lines, DEFAULT_LIMITS[:max_lines]].min
- @safe_max_bytes = @safe_max_files * 5.kilobytes # Average 5 KB per file
+ @limits = self.class.collection_limits(options)
@enforce_limits = !!options.fetch(:limits, true)
@expanded = !!options.fetch(:expanded, true)
+ @from_gitaly = options.fetch(:from_gitaly, false)
@line_count = 0
@byte_count = 0
@@ -26,9 +38,23 @@ module Gitlab
end
def each(&block)
- Gitlab::GitalyClient.migrate(:commit_raw_diffs) do
- each_patch(&block)
+ @array.each(&block)
+
+ return if @overflow
+ return if @iterator.nil?
+
+ Gitlab::GitalyClient.migrate(:commit_raw_diffs) do |is_enabled|
+ if is_enabled && @from_gitaly
+ each_gitaly_patch(&block)
+ else
+ each_rugged_patch(&block)
+ end
end
+
+ @populated = true
+
+ # Allow iterator to be garbage-collected. It cannot be reused anyway.
+ @iterator = nil
end
def empty?
@@ -74,23 +100,32 @@ module Gitlab
end
def over_safe_limits?(files)
- files >= @safe_max_files || @line_count > @safe_max_lines || @byte_count >= @safe_max_bytes
+ files >= safe_max_files || @line_count > safe_max_lines || @byte_count >= safe_max_bytes
end
- def each_patch
- i = 0
- @array.each do |diff|
- yield diff
+ def each_gitaly_patch
+ i = @array.length
+
+ @iterator.each do |raw|
+ diff = Gitlab::Git::Diff.new(raw, expanded: !@enforce_limits || @expanded)
+
+ if raw.overflow_marker
+ @overflow = true
+ break
+ end
+
+ yield @array[i] = diff
i += 1
end
+ end
- return if @overflow
- return if @iterator.nil?
+ def each_rugged_patch
+ i = @array.length
@iterator.each do |raw|
@empty = false
- if @enforce_limits && i >= @max_files
+ if @enforce_limits && i >= max_files
@overflow = true
break
end
@@ -106,7 +141,7 @@ module Gitlab
@line_count += diff.line_count
@byte_count += diff.diff.bytesize
- if @enforce_limits && (@line_count >= @max_lines || @byte_count >= @max_bytes)
+ if @enforce_limits && (@line_count >= max_lines || @byte_count >= max_bytes)
# This last Diff instance pushes us over the lines limit. We stop and
# discard it.
@overflow = true
@@ -116,11 +151,6 @@ module Gitlab
yield @array[i] = diff
i += 1
end
-
- @populated = true
-
- # Allow iterator to be garbage-collected. It cannot be reused anyway.
- @iterator = nil
end
end
end
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 8f5738fed06..b749955cddc 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -23,9 +23,13 @@ module Gitlab
def diff_from_parent(commit, options = {})
request_params = commit_diff_request_params(commit, options)
request_params[:ignore_whitespace_change] = options.fetch(:ignore_whitespace_change, false)
+ request_params[:enforce_limits] = options.fetch(:limits, true)
+ request_params[:collapse_diffs] = request_params[:enforce_limits] || !options.fetch(:expanded, true)
+ request_params.merge!(Gitlab::Git::DiffCollection.collection_limits(options).to_h)
+
request = Gitaly::CommitDiffRequest.new(request_params)
response = GitalyClient.call(@repository.storage, :diff_service, :commit_diff, request)
- Gitlab::Git::DiffCollection.new(GitalyClient::DiffStitcher.new(response), options)
+ Gitlab::Git::DiffCollection.new(GitalyClient::DiffStitcher.new(response), options.merge(from_gitaly: true))
end
def commit_deltas(commit)
diff --git a/lib/gitlab/gitaly_client/diff.rb b/lib/gitlab/gitaly_client/diff.rb
index 1e117b7e74a..d459c9a88fb 100644
--- a/lib/gitlab/gitaly_client/diff.rb
+++ b/lib/gitlab/gitaly_client/diff.rb
@@ -1,7 +1,7 @@
module Gitlab
module GitalyClient
class Diff
- FIELDS = %i(from_path to_path old_mode new_mode from_id to_id patch).freeze
+ FIELDS = %i(from_path to_path old_mode new_mode from_id to_id patch overflow_marker collapsed).freeze
attr_accessor(*FIELDS)