Class: Blob
- Inherits:
-
SimpleDelegator
- Object
- SimpleDelegator
- Blob
- Includes:
- BlobActiveModel, BlobLanguageFromGitAttributes, GlobalID::Identification, Presentable
- Defined in:
- app/models/blob.rb
Overview
Blob is a Rails-specific wrapper around Gitlab::Git::Blob, SnippetBlob and Ci::ArtifactBlob
Direct Known Subclasses
Constant Summary collapse
- MODE_SYMLINK =
The STRING 120000 is the git-reported octal filemode for a symlink
'120000'
- MODE_EXECUTABLE =
The STRING 100755 is the git-reported octal filemode for an executable file
'100755'
- CACHE_TIME =
Cache raw blobs referred to by a (mutable) ref for 1 minute
60
- CACHE_TIME_IMMUTABLE =
Cache blobs referred to by an immutable reference for 1 hour
3600
- RICH_VIEWERS =
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.
[ BlobViewer::CSV, BlobViewer::Markup, BlobViewer::Notebook, BlobViewer::SVG, BlobViewer::OpenApi, BlobViewer::GeoJson, BlobViewer::Image, BlobViewer::Sketch, BlobViewer::Video, BlobViewer::Audio, BlobViewer::PDF, BlobViewer::BinarySTL, BlobViewer::TextSTL ].sort_by { |v| v.binary? ? 0 : 1 }.freeze
- AUXILIARY_VIEWERS =
[ BlobViewer::GitlabCiYml, BlobViewer::RouteMap, BlobViewer::Readme, BlobViewer::License, BlobViewer::Contributing, BlobViewer::Changelog, BlobViewer::CargoToml, BlobViewer::Cartfile, BlobViewer::ComposerJson, BlobViewer::Gemfile, BlobViewer::Gemspec, BlobViewer::GodepsJson, BlobViewer::GoMod, BlobViewer::PackageJson, BlobViewer::Podfile, BlobViewer::Podspec, BlobViewer::PodspecJson, BlobViewer::RequirementsTxt, BlobViewer::YarnLock ].freeze
Instance Attribute Summary collapse
-
#container ⇒ Object
readonly
Returns the value of attribute container.
-
#ref_type ⇒ Object
Returns the value of attribute ref_type.
Class Method Summary collapse
-
.decorate(blob, container = nil) ⇒ Object
Wrap a Gitlab::Git::Blob object, or return nil when given nil.
- .lazy(repository, commit_id, path, blob_size_limit: Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE) ⇒ Object
Instance Method Summary collapse
- #audio? ⇒ Boolean
- #auxiliary_viewer ⇒ Object
-
#binary? ⇒ Boolean
Returns whether the file that this blob represents is binary.
-
#data ⇒ Object
Returns the data of the blob.
- #empty? ⇒ Boolean
- #executable? ⇒ Boolean
- #expand! ⇒ Object
- #expanded? ⇒ Boolean
- #extension ⇒ Object
- #external_storage_error? ⇒ Boolean
- #file_type ⇒ Object
-
#initialize(blob, container = nil) ⇒ Blob
constructor
A new instance of Blob.
- #inspect ⇒ Object
- #load_all_data! ⇒ Object
-
#raw_size ⇒ Object
Returns the size of the file that this blob represents.
- #readable_text? ⇒ Boolean
- #rendered_as_text?(ignore_errors: true) ⇒ Boolean
- #rich_viewer ⇒ Object
- #show_viewer_switcher? ⇒ Boolean
- #simple_viewer ⇒ Object
- #stored_externally? ⇒ Boolean
- #symlink? ⇒ Boolean
- #video? ⇒ Boolean
Methods included from BlobActiveModel
Methods included from BlobLanguageFromGitAttributes
Methods included from Presentable
Constructor Details
#initialize(blob, container = nil) ⇒ Blob
Returns a new instance of Blob.
106 107 108 109 110 |
# File 'app/models/blob.rb', line 106 def initialize(blob, container = nil) @container = container super(blob) end |
Instance Attribute Details
#container ⇒ Object (readonly)
Returns the value of attribute container.
74 75 76 |
# File 'app/models/blob.rb', line 74 def container @container end |
#ref_type ⇒ Object
Returns the value of attribute ref_type.
75 76 77 |
# File 'app/models/blob.rb', line 75 def ref_type @ref_type end |
Class Method Details
.decorate(blob, container = nil) ⇒ Object
Wrap a Gitlab::Git::Blob object, or return nil when given nil
This method prevents the decorated object from evaluating to “truthy” when given a nil value. For example:
blob = Blob.new(nil)
puts "truthy" if blob # => "truthy"
blob = Blob.decorate(nil)
puts "truthy" if blob # No output
90 91 92 93 94 |
# File 'app/models/blob.rb', line 90 def self.decorate(blob, container = nil) return if blob.nil? new(blob, container) end |
.lazy(repository, commit_id, path, blob_size_limit: Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE) ⇒ Object
96 97 98 99 100 101 102 103 104 |
# File 'app/models/blob.rb', line 96 def self.lazy(repository, commit_id, path, blob_size_limit: Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE) key = [:repository_blobs, repository, blob_size_limit] BatchLoader.for([commit_id, path]).batch(key: key) do |items, loader, args| args[:key].second.blobs_at(items, blob_size_limit: blob_size_limit).each do |blob| loader.call([blob.commit_id, blob.path], blob) if blob end end end |
Instance Method Details
#audio? ⇒ Boolean
206 207 208 |
# File 'app/models/blob.rb', line 206 def audio? UploaderHelper::SAFE_AUDIO_EXT.include?(extension) end |
#auxiliary_viewer ⇒ Object
224 225 226 227 228 |
# File 'app/models/blob.rb', line 224 def auxiliary_viewer return @auxiliary_viewer if defined?(@auxiliary_viewer) @auxiliary_viewer = auxiliary_viewer_class&.new(self) end |
#binary? ⇒ Boolean
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.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'app/models/blob.rb', line 168 def binary? if stored_externally? if rich_viewer rich_viewer.binary? elsif known_extension? false elsif _mime_type _mime_type.binary? else true end else binary_in_repo? end end |
#data ⇒ Object
Returns the data of the blob.
If the blob is a text based blob the content is converted to UTF-8 and any invalid byte sequences are replaced.
120 121 122 123 124 125 126 |
# File 'app/models/blob.rb', line 120 def data if binary_in_repo? super else @data ||= super.encode(Encoding::UTF_8, invalid: :replace, undef: :replace) end end |
#empty? ⇒ Boolean
135 136 137 |
# File 'app/models/blob.rb', line 135 def empty? raw_size == 0 end |
#executable? ⇒ Boolean
188 189 190 |
# File 'app/models/blob.rb', line 188 def executable? mode == MODE_EXECUTABLE end |
#expand! ⇒ Object
242 243 244 |
# File 'app/models/blob.rb', line 242 def = true end |
#expanded? ⇒ Boolean
238 239 240 |
# File 'app/models/blob.rb', line 238 def !! end |
#extension ⇒ Object
192 193 194 |
# File 'app/models/blob.rb', line 192 def extension @extension ||= extname.downcase.delete('.') end |
#external_storage_error? ⇒ Boolean
139 140 141 142 143 144 145 |
# File 'app/models/blob.rb', line 139 def external_storage_error? if external_storage == :lfs !repository.lfs_enabled? else false end end |
#file_type ⇒ Object
196 197 198 199 200 |
# File 'app/models/blob.rb', line 196 def file_type name = File.basename(path) Gitlab::FileDetector.type_of(path) || Gitlab::FileDetector.type_of(name) end |
#inspect ⇒ Object
112 113 114 |
# File 'app/models/blob.rb', line 112 def inspect "#<#{self.class.name} oid:#{id[0..8]} commit:#{commit_id[0..8]} path:#{path}>" end |
#load_all_data! ⇒ Object
128 129 130 131 132 133 |
# File 'app/models/blob.rb', line 128 def load_all_data! # Endpoint needed: https://gitlab.com/gitlab-org/gitaly/issues/756 Gitlab::GitalyClient.allow_n_plus_1_calls do super(repository) if container end end |
#raw_size ⇒ Object
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.
156 157 158 159 160 161 162 |
# File 'app/models/blob.rb', line 156 def raw_size if stored_externally? external_size else size end end |
#readable_text? ⇒ Boolean
210 211 212 |
# File 'app/models/blob.rb', line 210 def readable_text? text_in_repo? && !stored_externally? && !truncated? end |
#rendered_as_text?(ignore_errors: true) ⇒ Boolean
230 231 232 |
# File 'app/models/blob.rb', line 230 def rendered_as_text?(ignore_errors: true) simple_viewer.is_a?(BlobViewer::Text) && (ignore_errors || simple_viewer.render_error.nil?) end |
#rich_viewer ⇒ Object
218 219 220 221 222 |
# File 'app/models/blob.rb', line 218 def rich_viewer return @rich_viewer if defined?(@rich_viewer) @rich_viewer = rich_viewer_class&.new(self) end |
#show_viewer_switcher? ⇒ Boolean
234 235 236 |
# File 'app/models/blob.rb', line 234 def show_viewer_switcher? rendered_as_text? && rich_viewer end |
#simple_viewer ⇒ Object
214 215 216 |
# File 'app/models/blob.rb', line 214 def simple_viewer @simple_viewer ||= simple_viewer_class.new(self) end |
#stored_externally? ⇒ Boolean
147 148 149 150 151 |
# File 'app/models/blob.rb', line 147 def stored_externally? return @stored_externally if defined?(@stored_externally) @stored_externally = external_storage && !external_storage_error? end |
#symlink? ⇒ Boolean
184 185 186 |
# File 'app/models/blob.rb', line 184 def symlink? mode == MODE_SYMLINK end |
#video? ⇒ Boolean
202 203 204 |
# File 'app/models/blob.rb', line 202 def video? UploaderHelper::SAFE_VIDEO_EXT.include?(extension) end |