diff options
author | Luke "Jared" Bennett <lbennett@gitlab.com> | 2017-04-28 11:32:40 +0100 |
---|---|---|
committer | Luke "Jared" Bennett <lbennett@gitlab.com> | 2017-04-28 11:32:40 +0100 |
commit | cde3760bb4aa4c9abe45aad301d4334936be74ba (patch) | |
tree | 4e3673ca4fcf40525d136a8d8eb3ae002488b419 /app/models/blob.rb | |
parent | f74d0ba195079260d3b3217cd72b2fd9b0483c00 (diff) | |
parent | ef518df28adc1366d868cb990952e87f60e8b0eb (diff) | |
download | gitlab-ce-cde3760bb4aa4c9abe45aad301d4334936be74ba.tar.gz |
Merge branch 'master' into balsalmiq-support
Diffstat (limited to 'app/models/blob.rb')
-rw-r--r-- | app/models/blob.rb | 178 |
1 files changed, 118 insertions, 60 deletions
diff --git a/app/models/blob.rb b/app/models/blob.rb index 82333b6f369..1694f4e6dc9 100644 --- a/app/models/blob.rb +++ b/app/models/blob.rb @@ -3,8 +3,41 @@ class Blob < SimpleDelegator CACHE_TIME = 60 # Cache raw blobs referred to by a (mutable) ref for 1 minute CACHE_TIME_IMMUTABLE = 3600 # Cache blobs referred to by an immutable reference for 1 hour - # The maximum size of an SVG that can be displayed. - MAXIMUM_SVG_SIZE = 2.megabytes + MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte + + # Finding a viewer for a blob happens based only on extension and whether the + # blob is binary or text, which means 1 blob should only be matched by 1 viewer, + # and the order of these viewers doesn't really matter. + # + # However, when the blob is an LFS pointer, 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. + # + # `.stl` files, for example, exist in both binary and text forms, and are + # handled by different viewers (`BinarySTL` and `TextSTL`) depending on blob + # type. LFS pointers to `.stl` files are assumed to always be the binary kind, + # and use the `BinarySTL` viewer. + RICH_VIEWERS = [ + BlobViewer::Markup, + BlobViewer::Notebook, + BlobViewer::SVG, + + BlobViewer::Image, + BlobViewer::Sketch, + BlobViewer::Balsamiq, + + BlobViewer::PDF, + + BlobViewer::BinarySTL, + BlobViewer::TextSTL, + ].freeze + + BINARY_VIEWERS = RICH_VIEWERS.select(&:binary?).freeze + TEXT_VIEWERS = RICH_VIEWERS.select(&:text?).freeze + + attr_reader :project # Wrap a Gitlab::Git::Blob object, or return nil when given nil # @@ -16,10 +49,16 @@ class Blob < SimpleDelegator # # blob = Blob.decorate(nil) # puts "truthy" if blob # No output - def self.decorate(blob) + def self.decorate(blob, project = nil) return if blob.nil? - new(blob) + new(blob, project) + end + + def initialize(blob, project = nil) + @project = project + + super(blob) end # Returns the data of the blob. @@ -35,88 +74,107 @@ class Blob < SimpleDelegator end def no_highlighting? - size && size > 1.megabyte + size && size > MAXIMUM_TEXT_HIGHLIGHT_SIZE end - def only_display_raw? + def too_large? size && truncated? end + # Returns the size of the file that this blob represents. If this blob is an + # LFS pointer, this is the size of the file stored in LFS. Otherwise, this is + # the size of the blob itself. + def raw_size + if valid_lfs_pointer? + lfs_size + else + size + end + end + + # Returns whether the file that this blob represents is binary. If this blob is + # an LFS pointer, we assume the file stored in LFS is binary, unless a + # text-based rich blob viewer matched on the file's extension. Otherwise, this + # depends on the type of the blob itself. + def raw_binary? + if valid_lfs_pointer? + if rich_viewer + rich_viewer.binary? + else + true + end + else + binary? + end + end + def extension - extname.downcase.delete('.') + @extension ||= extname.downcase.delete('.') end - def svg? - text? && language && language.name == 'SVG' + def video? + UploaderHelper::VIDEO_EXT.include?(extension) end - def pdf? - extension == 'pdf' + def readable_text? + text? && !valid_lfs_pointer? && !too_large? end - def ipython_notebook? - text? && language&.name == 'Jupyter Notebook' + def valid_lfs_pointer? + lfs_pointer? && project&.lfs_enabled? end - def sketch? - binary? && extension == 'sketch' + def invalid_lfs_pointer? + lfs_pointer? && !project&.lfs_enabled? end - def balsamiq? - binary? && extension == 'bmpr' + def simple_viewer + @simple_viewer ||= simple_viewer_class.new(self) end - def stl? - extension == 'stl' + def rich_viewer + return @rich_viewer if defined?(@rich_viewer) + + @rich_viewer = rich_viewer_class&.new(self) end - def markup? - text? && Gitlab::MarkupHelper.markup?(name) + def rendered_as_text?(ignore_errors: true) + simple_viewer.text? && (ignore_errors || simple_viewer.render_error.nil?) end - def size_within_svg_limits? - size <= MAXIMUM_SVG_SIZE + def show_viewer_switcher? + rendered_as_text? && rich_viewer end - def video? - UploaderHelper::VIDEO_EXT.include?(extname.downcase.delete('.')) + def override_max_size! + simple_viewer&.override_max_size = true + rich_viewer&.override_max_size = true end - def to_partial_path(project) - if lfs_pointer? - if project.lfs_enabled? - 'download' - else - 'text' - end - elsif image? - 'image' - elsif svg? - 'svg' - elsif pdf? - 'pdf' - elsif ipython_notebook? - 'notebook' - elsif sketch? - 'sketch' - elsif stl? - 'stl' - elsif balsamiq? - 'bmpr' - elsif markup? - if only_display_raw? - 'too_large' - else - 'markup' - end - elsif text? - if only_display_raw? - 'too_large' - else - 'text' - end - else - 'download' + private + + def simple_viewer_class + if empty? + BlobViewer::Empty + elsif raw_binary? + BlobViewer::Download + else # text + BlobViewer::Text end end + + def rich_viewer_class + return if invalid_lfs_pointer? || empty? + + classes = + if valid_lfs_pointer? + BINARY_VIEWERS + TEXT_VIEWERS + elsif binary? + BINARY_VIEWERS + else # text + TEXT_VIEWERS + end + + classes.find { |viewer_class| viewer_class.can_render?(self) } + end end |