lib/gitlab_git/diff.rb in gitlab_git-10.6.3 vs lib/gitlab_git/diff.rb in gitlab_git-10.6.4
- old
+ new
@@ -11,10 +11,16 @@
# Stats properties
attr_accessor :new_file, :renamed_file, :deleted_file
attr_accessor :too_large
+ # The maximum size of a diff to display.
+ DIFF_SIZE_LIMIT = 102400 # 100 KB
+
+ # The maximum size before a diff is collapsed.
+ DIFF_COLLAPSE_LIMIT = 10240 # 10 KB
+
class << self
def between(repo, head, base, options = {}, *paths)
# Only show what is new in the source branch compared to the target branch, not the other way around.
# The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
# From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
@@ -156,16 +162,16 @@
filtered_opts
end
end
- def initialize(raw_diff)
+ def initialize(raw_diff, collapse: false)
case raw_diff
when Hash
- init_from_hash(raw_diff)
+ init_from_hash(raw_diff, collapse: collapse)
when Rugged::Patch, Rugged::Diff::Delta
- init_from_rugged(raw_diff)
+ init_from_rugged(raw_diff, collapse: collapse)
when nil
raise "Nil as raw diff passed"
else
raise "Invalid raw diff type: #{raw_diff.class}"
end
@@ -195,16 +201,20 @@
@line_count ||= Util.count_lines(@diff)
end
def too_large?
if @too_large.nil?
- @too_large = @diff.bytesize >= 102400 # 100 KB
+ @too_large = @diff.bytesize >= DIFF_SIZE_LIMIT
else
@too_large
end
end
+ def collapsible?
+ @diff.bytesize >= DIFF_COLLAPSE_LIMIT
+ end
+
def prune_large_diff!
@diff = ''
@line_count = 0
@too_large = true
end
@@ -212,25 +222,21 @@
def collapsed?
return @collapsed if defined?(@collapsed)
false
end
- def collapsible?
- @diff.bytesize >= 10240 # 10 KB
- end
-
def prune_collapsed_diff!
@diff = ''
@line_count = 0
@collapsed = true
end
private
- def init_from_rugged(rugged)
+ def init_from_rugged(rugged, collapse: false)
if rugged.is_a?(Rugged::Patch)
- @diff = encode!(strip_diff_headers(rugged.to_s))
+ init_from_rugged_patch(rugged, collapse: collapse)
d = rugged.delta
else
d = rugged
end
@@ -241,15 +247,49 @@
@new_file = d.added?
@renamed_file = d.renamed?
@deleted_file = d.deleted?
end
- def init_from_hash(hash)
+ def init_from_rugged_patch(patch, collapse: false)
+ # Don't bother initializing diffs that are too large. If a diff is
+ # binary we're not going to display anything so we skip the size check.
+ unless patch.delta.binary?
+ diff_size = patch_size(patch)
+
+ if diff_size >= DIFF_SIZE_LIMIT
+ prune_large_diff!
+ return
+ elsif collapse && diff_size >= DIFF_COLLAPSE_LIMIT
+ prune_collapsed_diff!
+ return
+ end
+ end
+
+ @diff = encode!(strip_diff_headers(patch.to_s))
+ end
+
+ def init_from_hash(hash, collapse: false)
raw_diff = hash.symbolize_keys
serialize_keys.each do |key|
send(:"#{key}=", raw_diff[key.to_sym])
end
+
+ prune_large_diff! if too_large?
+ prune_collapsed_diff! if collapse && collapsible?
+ end
+
+ # Returns the size of a diff without taking any diff markers into account.
+ def patch_size(patch)
+ size = 0
+
+ patch.each_hunk do |hunk|
+ hunk.each_line do |line|
+ size += line.content.bytesize
+ end
+ end
+
+ size
end
# Strip out the information at the beginning of the patch's text to match
# Grit's output
def strip_diff_headers(diff_text)