2 # converted from the gitrb project
5 # Matthias Lederhofer <matled@gmx.net>
6 # Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
8 # provides native ruby access to git objects and pack files
16 # class for author/committer/tagger lines
18 attr_accessor :name, :email, :date, :offset
21 m = /^(.*?) <(.*)> (\d+) ([+-])0*(\d+?)$/.match(str)
23 raise RuntimeError, "invalid %s header in commit" % key
27 @date = Time.at(Integer(m[3]))
28 @offset = (m[4] == "-" ? -1 : 1)*Integer(m[5])
32 "%s <%s> %s %+05d" % [@name, @email, @date.to_i, @offset]
36 # base class for all git objects (blob, tree, commit, tag)
38 attr_accessor :repository
40 def Object.from_raw(rawobject, repository = nil)
43 return Blob.from_raw(rawobject, repository)
45 return Tree.from_raw(rawobject, repository)
47 return Commit.from_raw(rawobject, repository)
49 return Tag.from_raw(rawobject, repository)
51 raise RuntimeError, "got invalid object-type"
56 raise NotImplemented, "abstract class"
60 raise NotImplemented, "abstract class"
64 raise NotImplemented, "abstract class"
68 Digest::SHA1.hexdigest("%s %d\0" % \
69 [self.type, self.raw_content.length] + \
75 attr_accessor :content
77 def self.from_raw(rawobject, repository)
78 new(rawobject.content)
81 def initialize(content, repository=nil)
83 @repository = repository
101 attr_accessor :mode, :name, :sha1
103 m = /^(\d+) (.*)\0(.{20})$/m.match(buf)
105 raise RuntimeError, "invalid directory entry"
108 m[1].each_byte do |i|
109 @mode = (@mode << 3) | (i-'0'[0])
112 @sha1 = m[3].unpack("H*")[0]
114 if ![S_IFLNK, S_IFDIR, S_IFREG].include?(@mode & S_IFMT)
115 raise RuntimeError, "unknown type for directory entry"
128 raise RuntimeError, "unknown type for directory entry"
135 @mode = (@mode & ~S_IFMT) | S_IFLNK
137 @mode = (@mode & ~S_IFMT) | S_IFDIR
139 @mode = (@mode & ~S_IFMT) | S_IFREG
141 raise RuntimeError, "invalid type"
161 "%o %s\0%s" % [@mode, @name, [@sha1].pack("H*")]
168 def self.from_raw(rawobject, repository=nil)
170 rawobject.content.scan(/\d+ .*?\0.{20}/m) do |raw|
171 entries << DirectoryEntry.new(raw)
173 new(entries, repository)
176 def initialize(entries=[], repository = nil)
178 @repository = repository
186 # TODO: sort correctly
187 #@entry.sort { |a,b| a.name <=> b.name }.
188 @entry.collect { |e| [[e.format_mode, e.format_type, e.sha1].join(' '), e.name].join("\t") }.join("\n")
192 class Commit < Object
193 attr_accessor :author, :committer, :tree, :parent, :message
195 def self.from_raw(rawobject, repository=nil)
197 tree = author = committer = nil
199 headers, message = rawobject.content.split(/\n\n/, 2)
200 headers = headers.split(/\n/).map { |header| header.split(/ /, 2) }
201 headers.each do |key, value|
208 author = UserInfo.new(value)
210 committer = UserInfo.new(value)
212 warn "unknown header '%s' in commit %s" % \
213 [key, rawobject.sha1.unpack("H*")[0]]
216 if not tree && author && committer
217 raise RuntimeError, "incomplete raw commit object"
219 new(tree, parent, author, committer, message, repository)
222 def initialize(tree, parent, author, committer, message, repository=nil)
226 @committer = committer
228 @repository = repository
236 "tree %s\n%sauthor %s\ncommitter %s\n\n" % [
238 @parent.collect { |i| "parent %s\n" % i }.join,
239 @author, @committer] + @message
244 attr_accessor :object, :type, :tag, :tagger, :message
246 def self.from_raw(rawobject, repository=nil)
247 headers, message = rawobject.content.split(/\n\n/, 2)
248 headers = headers.split(/\n/).map { |header| header.split(/ /, 2) }
249 headers.each do |key, value|
254 if !["blob", "tree", "commit", "tag"].include?(value)
255 raise RuntimeError, "invalid type in tag"
261 tagger = UserInfo.new(value)
263 warn "unknown header '%s' in tag" % \
264 [key, rawobject.sha1.unpack("H*")[0]]
266 if not object && type && tag && tagger
267 raise RuntimeError, "incomplete raw tag object"
270 new(object, type, tag, tagger, repository)
273 def initialize(object, type, tag, tagger, repository=nil)
278 @repository = repository
282 "object %s\ntype %s\ntag %s\ntagger %s\n\n" % \
283 [@object, @type, @tag, @tagger] + @message