summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2017-06-06 16:28:06 -0500
committerDouwe Maan <douwe@selenight.nl>2017-06-14 10:12:21 -0500
commit794425456322864f37dbd862aca9bc6b6447591a (patch)
treee04869a293f434756527fcdf80505bcde12bc3f6 /lib
parent64e85fdaffcd03ef52ff74953b1a4e0caf5a23e8 (diff)
downloadgitlab-ce-794425456322864f37dbd862aca9bc6b6447591a.tar.gz
Implement diff viewers
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/diff/file.rb109
-rw-r--r--lib/gitlab/git/diff.rb2
-rw-r--r--lib/gitlab/git/diff_collection.rb2
3 files changed, 111 insertions, 2 deletions
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index 4212a0dbe2e..d2863a4da71 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -5,7 +5,20 @@ module Gitlab
delegate :new_file?, :deleted_file?, :renamed_file?,
:old_path, :new_path, :a_mode, :b_mode, :mode_changed?,
- :submodule?, :too_large?, :collapsed?, to: :diff, prefix: false
+ :submodule?, :expanded?, :too_large?, :collapsed?, :line_count, to: :diff, prefix: false
+
+ # Finding a viewer for a diff file happens based only on extension and whether the
+ # diff file blobs are binary or text, which means 1 diff file should only be matched by 1 viewer,
+ # and the order of these viewers doesn't really matter.
+ #
+ # However, when the diff file blobs are LFS pointers, we cannot know for sure whether the
+ # file being pointed to is binary or text. In this case, we match only on
+ # extension, preferring binary viewers over text ones if both exist, since the
+ # large files referred to in "Large File Storage" are much more likely to be
+ # binary than text.
+ RICH_VIEWERS = [
+ DiffViewer::Image
+ ].sort_by { |v| v.binary? ? 0 : 1 }.freeze
def initialize(diff, repository:, diff_refs: nil, fallback_diff_refs: nil)
@diff = diff
@@ -177,6 +190,100 @@ module Gitlab
def text?
!binary?
end
+
+ def external_storage_error?
+ old_blob&.external_storage_error? || new_blob&.external_storage_error?
+ end
+
+ def stored_externally?
+ old_blob&.stored_externally? || new_blob&.stored_externally?
+ end
+
+ def external_storage
+ old_blob&.external_storage || new_blob&.external_storage
+ end
+
+ def content_changed?
+ old_blob && new_blob && old_blob.id != new_blob.id
+ end
+
+ def different_type?
+ old_blob && new_blob && old_blob.binary? != new_blob.binary?
+ end
+
+ def size
+ [old_blob&.size, new_blob&.size].compact.sum
+ end
+
+ def raw_size
+ [old_blob&.raw_size, new_blob&.raw_size].compact.sum
+ end
+
+ def raw_binary?
+ old_blob&.raw_binary? || new_blob&.raw_binary?
+ end
+
+ def raw_text?
+ !raw_binary? && !different_type?
+ end
+
+ def simple_viewer
+ @simple_viewer ||= simple_viewer_class.new(self)
+ end
+
+ def rich_viewer
+ return @rich_viewer if defined?(@rich_viewer)
+
+ @rich_viewer = rich_viewer_class&.new(self)
+ end
+
+ def rendered_as_text?(ignore_errors: true)
+ simple_viewer.is_a?(DiffViewer::Text) && (ignore_errors || simple_viewer.render_error.nil?)
+ end
+
+ private
+
+ def simple_viewer_class
+ return DiffViewer::NotDiffable unless diffable?
+
+ if content_changed?
+ if raw_text?
+ DiffViewer::Text
+ else
+ DiffViewer::NoPreview
+ end
+ elsif new_file?
+ if raw_text?
+ DiffViewer::Text
+ else
+ DiffViewer::Added
+ end
+ elsif deleted_file?
+ if raw_text?
+ DiffViewer::Text
+ else
+ DiffViewer::Deleted
+ end
+ elsif renamed_file?
+ DiffViewer::Renamed
+ elsif mode_changed?
+ DiffViewer::ModeChanged
+ end
+ end
+
+ def rich_viewer_class
+ viewer_class_from(RICH_VIEWERS)
+ end
+
+ def viewer_class_from(classes)
+ return unless diffable?
+ return if different_type? || external_storage_error?
+ return unless new_file? || deleted_file? || content_changed?
+
+ verify_binary = !stored_externally?
+
+ classes.find { |viewer_class| viewer_class.can_render?(self, verify_binary: verify_binary) }
+ end
end
end
end
diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb
index 88ad760bea3..4b689f0e94f 100644
--- a/lib/gitlab/git/diff.rb
+++ b/lib/gitlab/git/diff.rb
@@ -17,6 +17,8 @@ module Gitlab
attr_accessor :expanded
+ alias_method :expanded?, :expanded
+
# We need this accessor because of `to_hash` and `init_from_hash`
attr_accessor :too_large
diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb
index 334e06a6eca..555894907cc 100644
--- a/lib/gitlab/git/diff_collection.rb
+++ b/lib/gitlab/git/diff_collection.rb
@@ -97,7 +97,7 @@ module Gitlab
diff = Gitlab::Git::Diff.new(raw, expanded: expanded)
- if !expanded && over_safe_limits?(i)
+ if !expanded && over_safe_limits?(i) && diff.line_count > 0
diff.collapse!
end