class Bringit::Blob

Constants

MAX_DATA_DISPLAY_SIZE

This number is the maximum amount of data that we want to display to the user. We load as much as we can for encoding detection (Linguist) and LFS pointer parsing. All other cases where we need full blob data should use load_all_data!.

Attributes

binary[RW]
commit_id[RW]
data[RW]
id[RW]
loaded_size[RW]
mode[RW]
name[RW]
path[RW]
repository[R]
size[RW]

Public Class Methods

find(repository, sha, path) click to toggle source
# File lib/bringit/blob.rb, line 16
def find(repository, sha, path)
  path = path&.sub(%r{\A/*}, '')
  commit = repository.lookup(sha)
  root_tree = commit.tree

  blob_entry = find_entry_by_path(repository, root_tree.oid, path)

  return nil unless blob_entry

  if blob_entry[:type] == :commit
    submodule_blob(repository, blob_entry, path, sha)
  else
    blob = repository.lookup(blob_entry[:oid])

    if blob
      new(repository,
        id: blob.oid,
        name: blob_entry[:name],
        size: blob.size,
        data: blob.content(MAX_DATA_DISPLAY_SIZE),
        mode: blob_entry[:filemode].to_s(8),
        path: Bringit::PathHelper.normalize_path(path).to_s,
        commit_id: sha,
        binary: blob.binary?
      )
    end
  end
end
find_entry_by_path(repository, root_id, path) click to toggle source

Recursive search of blob id by path

Ex.

blog/            # oid: 1a
  app/           # oid: 2a
    models/      # oid: 3a
    file.rb      # oid: 4a

Blob.find_entry_by_path(repo, '1a', 'app/file.rb') # => '4a'

# File lib/bringit/blob.rb, line 67
def find_entry_by_path(repository, root_id, path)
  root_tree = repository.lookup(root_id)
  # Strip leading slashes
  path = path.sub(%r{\A/*}, '')
  path_arr = path.split('/')

  entry = root_tree.find do |entry|
    entry[:name] == path_arr[0]
  end

  return nil unless entry

  if path_arr.size > 1
    return nil unless entry[:type] == :tree
    path_arr.shift
    find_entry_by_path(repository, entry[:oid], path_arr.join('/'))
  else
    [:blob, :commit].include?(entry[:type]) ? entry : nil
  end
end
new(repository, options) click to toggle source
# File lib/bringit/blob.rb, line 100
def initialize(repository, options)
  @repository = repository
  %w(id name path size data mode commit_id binary).each do |key|
    self.send("#{key}=", options[key.to_sym])
  end

  @loaded_all_data = false
  # Retain the actual size before it is encoded
  @loaded_size = @data.bytesize if @data
end
raw(repository, sha) click to toggle source
# File lib/bringit/blob.rb, line 45
def raw(repository, sha)
  blob = repository.lookup(sha)

  new(repository,
    id: blob.oid,
    size: blob.size,
    data: blob.content(MAX_DATA_DISPLAY_SIZE),
    binary: blob.binary?
  )
end
submodule_blob(repository, blob_entry, path, sha) click to toggle source
# File lib/bringit/blob.rb, line 88
def submodule_blob(repository, blob_entry, path, sha)
  path = path&.sub(%r{\A/*}, '')
  new(repository,
    id: blob_entry[:oid],
    name: blob_entry[:name],
    data: '',
    path: path,
    commit_id: sha,
  )
end

Public Instance Methods

binary?() click to toggle source
Calls superclass method
# File lib/bringit/blob.rb, line 111
def binary?
  @binary.nil? ? super : @binary == true
end
empty?() click to toggle source
# File lib/bringit/blob.rb, line 115
def empty?
  !data || data == ''
end
lfs_oid() click to toggle source
# File lib/bringit/blob.rb, line 147
def lfs_oid
  if has_lfs_version_key?
    oid = data.match(/(?<=sha256:)([0-9a-f]{64})/)
    return oid[1] if oid
  end

  nil
end
lfs_pointer?() click to toggle source

Valid LFS object pointer is a text file consisting of version oid size see github.com/github/git-lfs/blob/v1.1.0/docs/spec.md#the-pointer

# File lib/bringit/blob.rb, line 143
def lfs_pointer?
  has_lfs_version_key? && lfs_oid.present? && lfs_size.present?
end
lfs_size() click to toggle source
# File lib/bringit/blob.rb, line 156
def lfs_size
  if has_lfs_version_key?
    size = data.match(/(?<=size )([0-9]+)/)
    return size[1] if size
  end

  nil
end
load_all_data!() click to toggle source

Load all blob data (not just the first MAX_DATA_DISPLAY_SIZE bytes) into memory as a Ruby string.

# File lib/bringit/blob.rb, line 125
def load_all_data!
  return if @data == '' # don't mess with submodule blobs
  return @data if @loaded_all_data

  @loaded_all_data = true
  @data = repository.lookup(id).content
  @loaded_size = @data.bytesize
end
truncated?() click to toggle source
# File lib/bringit/blob.rb, line 165
def truncated?
  size && (size > loaded_size)
end

Private Instance Methods

has_lfs_version_key?() click to toggle source
# File lib/bringit/blob.rb, line 171
def has_lfs_version_key?
  !empty? && text? && data.start_with?("version https://git-lfs.github.com/spec")
end