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'- MODE_TREE =
'40000'- 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.
.stlfiles, for example, exist in both binary and text forms, and are handled by different viewers (BinarySTLandTextSTL) depending on blob type. LFS pointers to.stlfiles are assumed to always be the binary kind, and use theBinarySTLviewer. [ BlobViewer::CSV, BlobViewer::Markup, BlobViewer::Notebook, BlobViewer::SVG, BlobViewer::OpenApi, BlobViewer::GeoJson, BlobViewer::Graph, 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_hash ⇒ Object
- #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
- #tree? ⇒ 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.
108 109 110 111 112 |
# File 'app/models/blob.rb', line 108 def initialize(blob, container = nil) @container = container super(blob) end |
Instance Attribute Details
#container ⇒ Object (readonly)
Returns the value of attribute container.
76 77 78 |
# File 'app/models/blob.rb', line 76 def container @container end |
#ref_type ⇒ Object
Returns the value of attribute ref_type.
77 78 79 |
# File 'app/models/blob.rb', line 77 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
92 93 94 95 96 |
# File 'app/models/blob.rb', line 92 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
98 99 100 101 102 103 104 105 106 |
# File 'app/models/blob.rb', line 98 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
212 213 214 |
# File 'app/models/blob.rb', line 212 def audio? UploaderHelper::SAFE_AUDIO_EXT.include?(extension) end |
#auxiliary_viewer ⇒ Object
230 231 232 233 234 |
# File 'app/models/blob.rb', line 230 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.
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'app/models/blob.rb', line 170 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.
122 123 124 125 126 127 128 |
# File 'app/models/blob.rb', line 122 def data if binary_in_repo? super else @data ||= super.encode(Encoding::UTF_8, invalid: :replace, undef: :replace) end end |
#empty? ⇒ Boolean
137 138 139 |
# File 'app/models/blob.rb', line 137 def empty? raw_size == 0 end |
#executable? ⇒ Boolean
190 191 192 |
# File 'app/models/blob.rb', line 190 def executable? mode == MODE_EXECUTABLE end |
#expand! ⇒ Object
248 249 250 |
# File 'app/models/blob.rb', line 248 def = true end |
#expanded? ⇒ Boolean
244 245 246 |
# File 'app/models/blob.rb', line 244 def !! end |
#extension ⇒ Object
198 199 200 |
# File 'app/models/blob.rb', line 198 def extension @extension ||= extname.downcase.delete('.') end |
#external_storage_error? ⇒ Boolean
141 142 143 144 145 146 147 |
# File 'app/models/blob.rb', line 141 def external_storage_error? if external_storage == :lfs !repository.lfs_enabled? else false end end |
#file_hash ⇒ Object
252 253 254 |
# File 'app/models/blob.rb', line 252 def file_hash OpenSSL::Digest::SHA256.hexdigest(path) end |
#file_type ⇒ Object
202 203 204 205 206 |
# File 'app/models/blob.rb', line 202 def file_type name = File.basename(path) Gitlab::FileDetector.type_of(path) || Gitlab::FileDetector.type_of(name) end |
#inspect ⇒ Object
114 115 116 |
# File 'app/models/blob.rb', line 114 def inspect "#<#{self.class.name} oid:#{id[0..8]} commit:#{commit_id[0..8]} path:#{path}>" end |
#load_all_data! ⇒ Object
130 131 132 133 134 135 |
# File 'app/models/blob.rb', line 130 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.
158 159 160 161 162 163 164 |
# File 'app/models/blob.rb', line 158 def raw_size if stored_externally? external_size else size end end |
#readable_text? ⇒ Boolean
216 217 218 |
# File 'app/models/blob.rb', line 216 def readable_text? text_in_repo? && !stored_externally? && !truncated? end |
#rendered_as_text?(ignore_errors: true) ⇒ Boolean
236 237 238 |
# File 'app/models/blob.rb', line 236 def rendered_as_text?(ignore_errors: true) simple_viewer.is_a?(BlobViewer::Text) && (ignore_errors || simple_viewer.render_error.nil?) end |
#rich_viewer ⇒ Object
224 225 226 227 228 |
# File 'app/models/blob.rb', line 224 def rich_viewer return @rich_viewer if defined?(@rich_viewer) @rich_viewer = rich_viewer_class&.new(self) end |
#show_viewer_switcher? ⇒ Boolean
240 241 242 |
# File 'app/models/blob.rb', line 240 def show_viewer_switcher? rendered_as_text? && rich_viewer end |
#simple_viewer ⇒ Object
220 221 222 |
# File 'app/models/blob.rb', line 220 def simple_viewer @simple_viewer ||= simple_viewer_class.new(self) end |
#stored_externally? ⇒ Boolean
149 150 151 152 153 |
# File 'app/models/blob.rb', line 149 def stored_externally? return @stored_externally if defined?(@stored_externally) @stored_externally = external_storage && !external_storage_error? end |
#symlink? ⇒ Boolean
186 187 188 |
# File 'app/models/blob.rb', line 186 def symlink? mode == MODE_SYMLINK end |
#tree? ⇒ Boolean
194 195 196 |
# File 'app/models/blob.rb', line 194 def tree? mode == MODE_TREE end |
#video? ⇒ Boolean
208 209 210 |
# File 'app/models/blob.rb', line 208 def video? UploaderHelper::SAFE_VIDEO_EXT.include?(extension) end |