Class: Grit::GitRuby::Internal::LooseStorage

Inherits:
Object
  • Object
show all
Defined in:
lib/grit/git-ruby/internal/loose.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(directory) ⇒ LooseStorage

Returns a new instance of LooseStorage.


24
25
26
# File 'lib/grit/git-ruby/internal/loose.rb', line 24

def initialize(directory)
  @directory = directory
end

Class Method Details

.calculate_sha(content, type) ⇒ Object

simply figure out the sha


109
110
111
112
113
114
115
116
# File 'lib/grit/git-ruby/internal/loose.rb', line 109

def self.calculate_sha(content, type)
  size = content.bytesize.to_s
  verify_header(type, size)
  header = "#{type} #{size}\0"
  store = header + content

  Digest::SHA1.hexdigest(store)
end

.verify_header(type, size) ⇒ Object


118
119
120
121
122
# File 'lib/grit/git-ruby/internal/loose.rb', line 118

def self.verify_header(type, size)
  if !%w(blob tree commit tag).include?(type) || size !~ /^\d+$/
    raise LooseObjectError, "invalid object header"
  end
end

Instance Method Details

#[](sha1) ⇒ Object


28
29
30
31
32
33
34
35
36
37
# File 'lib/grit/git-ruby/internal/loose.rb', line 28

def [](sha1)
  sha1 = sha1.unpack("H*")[0]
  begin
    return nil unless sha1[0...2] && sha1[2..39]
    path = @directory + '/' + sha1[0...2] + '/' + sha1[2..39]
    get_raw_object(open(path, 'rb') { |f| f.read })
  rescue Errno::ENOENT
    nil
  end
end

#get_raw_object(buf) ⇒ Object

Raises:


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/grit/git-ruby/internal/loose.rb', line 39

def get_raw_object(buf)
  if buf.bytesize < 2
    raise LooseObjectError, "object file too small"
  end

  if legacy_loose_object?(buf)
    content = Zlib::Inflate.inflate(buf)
    header, content = content.split(/\0/, 2)
    if !header || !content
      raise LooseObjectError, "invalid object header"
    end
    type, size = header.split(/ /, 2)
    if !%w(blob tree commit tag).include?(type) || size !~ /^\d+$/
      raise LooseObjectError, "invalid object header"
    end
    type = type.to_sym
    size = size.to_i
  else
    type, size, used = unpack_object_header_gently(buf)
    content = Zlib::Inflate.inflate(buf[used..-1])
  end
  raise LooseObjectError, "size mismatch" if content.bytesize != size
  return RawObject.new(type, content)
end

#put_raw_object(content, type) ⇒ Object

currently, I'm using the legacy format because it's easier to do this function takes content and a type and writes out the loose object and returns a sha


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/grit/git-ruby/internal/loose.rb', line 89

def put_raw_object(content, type)
  size = content.bytesize.to_s
  LooseStorage.verify_header(type, size)

  header = "#{type} #{size}\0"
  store = header + content

  sha1 = Digest::SHA1.hexdigest(store)
  path = @directory+'/'+sha1[0...2]+'/'+sha1[2..40]

  if !File.exists?(path)
    content = Zlib::Deflate.deflate(store)

    FileUtils.mkdir_p(@directory+'/'+sha1[0...2])
    safe_write(path, content)
  end
  return sha1
end

#safe_write(path, content) ⇒ Object

write an object to a temporary file, then atomically rename it into place; this ensures readers never see a half-written file


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/grit/git-ruby/internal/loose.rb', line 66

def safe_write(path, content)
  f =
    if RUBY_VERSION >= '1.9'
      Tempfile.open("tmp_obj_", File.dirname(path), :opt => "wb")
    else
      Tempfile.open("tmp_obj_", File.dirname(path))
    end
  begin
    f.write content
    f.fsync
    File.link(f.path, path)
  rescue Errno::EEXIST    # The path already exists; we raced with another process,
    # but it's OK, because by definition the content is the
    # same. So we can just ignore the error.

  ensure
    f.unlink
    f.close
  end
end