Skip to content

Commit

Permalink
Merge remote branch 'origin/github'
Browse files Browse the repository at this point in the history
  • Loading branch information
rtomayko committed Jun 8, 2011
2 parents e4d4461 + 087676c commit 9042243
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 12 deletions.
15 changes: 15 additions & 0 deletions lib/grit/commit.rb
Expand Up @@ -252,6 +252,21 @@ def notes
ret
end

# Calculates the commit's Patch ID. The Patch ID is essentially the SHA1
# of the diff that the commit is introducing.
#
# Returns the 40 character hex String if a patch-id could be calculated
# or nil otherwise.
def patch_id
show = @repo.git.show({}, @id)
patch_line = @repo.git.native(:patch_id, :input => show)
if patch_line =~ /^([0-9a-f]{40}) [0-9a-f]{40}\n$/
$1
else
nil
end
end

# Pretty object inspection
def inspect
%Q{#<Grit::Commit "#{@id}">}
Expand Down
4 changes: 4 additions & 0 deletions lib/grit/git.rb
Expand Up @@ -52,6 +52,10 @@ def put_raw_object(content, type)
ruby_git.put_raw_object(content, type)
end

def get_raw_object(object_id)
ruby_git.get_raw_object_by_sha1(object_id).content
end

def object_exists?(object_id)
ruby_git.object_exists?(object_id)
end
Expand Down
43 changes: 34 additions & 9 deletions lib/grit/index.rb
Expand Up @@ -12,6 +12,10 @@ class Index
# which the next commit will be based.
attr_accessor :current_tree

# Public: if a tree or commit is written, this stores the size of that object
attr_reader :last_tree_size
attr_reader :last_commit_size

# Initialize a new Index object.
#
# repo - The Grit::Repo to which the index belongs.
Expand Down Expand Up @@ -71,16 +75,16 @@ def read_tree(tree)
# :parents - Array of String commit SHA1s or Grit::Commit
# objects to attach this commit to to form a
# new head (default: nil).
# :actor - The Grit::Actor details of the user making
# :actor - The Grit::Actor details of the user making
# the commit (default: nil).
# :last_tree - The String SHA1 of a tree to compare with
# in order to avoid making empty commits
# in order to avoid making empty commits
# (default: nil).
# :head - The String branch name to write this head to
# (default: "master").
# :committed_date - The Time that the commit was made.
# (default: nil).
# :committed_date - The Time that the commit was made.
# (Default: Time.now)
# :authored_date - The Time that the commit was authored.
# :authored_date - The Time that the commit was authored.
# (Default: committed_date)
#
# The legacy argument style looks like:
Expand All @@ -97,7 +101,9 @@ def read_tree(tree)
#
# Returns a String of the SHA1 of the new commit.
def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master')
commit_tree_sha = nil
if parents.is_a?(Hash)
commit_tree_sha = parents[:commit_tree_sha]
actor = parents[:actor]
committer = parents[:committer]
author = parents[:author]
Expand All @@ -111,7 +117,11 @@ def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master'
committer ||= actor
author ||= committer

tree_sha1 = write_tree(self.tree, self.current_tree)
if commit_tree_sha
tree_sha1 = commit_tree_sha
else
tree_sha1 = write_tree(self.tree, self.current_tree)
end

# don't write identical commits
return false if tree_sha1 == last_tree
Expand All @@ -135,9 +145,12 @@ def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master'
contents << ''
contents << message

commit_sha1 = self.repo.git.put_raw_object(contents.join("\n"), 'commit')
contents = contents.join("\n")
@last_commit_size = contents.size
commit_sha1 = self.repo.git.put_raw_object(contents, 'commit')

self.repo.update_ref(head, commit_sha1)
self.repo.update_ref(head, commit_sha1) if head
commit_sha1
end

# Recursively write a tree to the index.
Expand All @@ -149,10 +162,12 @@ def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master'
# this tree will be based (default: nil).
#
# Returns the String SHA1 String of the tree.
def write_tree(tree, now_tree = nil)
def write_tree(tree = nil, now_tree = nil)
tree = self.tree if !tree
tree_contents = {}

# fill in original tree
now_tree = read_tree(now_tree) if(now_tree && now_tree.is_a?(String))
now_tree.contents.each do |obj|
sha = [obj.id].pack("H*")
k = obj.name
Expand All @@ -164,6 +179,15 @@ def write_tree(tree, now_tree = nil)
# overwrite with new tree contents
tree.each do |k, v|
case v
when Array
sha, mode = v
if sha.size == 40 # must be a sha
sha = [sha].pack("H*")
mode = mode.to_i.to_s # leading 0s not allowed
k = k.split('/').last # slashes not allowed
str = "%s %s\0%s" % [mode, k, sha]
tree_contents[k] = str
end
when String
sha = write_blob(v)
sha = [sha].pack("H*")
Expand All @@ -181,6 +205,7 @@ def write_tree(tree, now_tree = nil)
end

tr = tree_contents.sort.map { |k, v| v }.join('')
@last_tree_size = tr.size
self.repo.git.put_raw_object(tr, 'tree')
end

Expand Down
49 changes: 49 additions & 0 deletions lib/grit/repo.rb
Expand Up @@ -346,6 +346,21 @@ def refs
[ Head.find_all(self), Tag.find_all(self), Remote.find_all(self) ].flatten
end

# returns an array of hashes representing all references
def refs_list
refs = self.git.for_each_ref
refarr = refs.split("\n").map do |line|
shatype, ref = line.split("\t")
sha, type = shatype.split(' ')
[ref, sha, type]
end
refarr
end

def delete_ref(ref)
self.git.native(:update_ref, {:d => true}, ref)
end

def commit_stats(start = 'master', max_count = 10, skip = 0)
options = {:max_count => max_count,
:skip => skip}
Expand Down Expand Up @@ -376,6 +391,11 @@ def commits_between(from, to)
Commit.find_all(self, "#{from}..#{to}").reverse
end

def fast_forwardable?(to, from)
mb = self.git.native(:merge_base, {}, [to, from]).strip
mb == from
end

# The Commits objects that are newer than the specified date.
# Commits are returned in chronological order.
# +start+ is the branch/commit name (default 'master')
Expand Down Expand Up @@ -470,6 +490,35 @@ def tree(treeish = 'master', paths = [])
Tree.construct(self, treeish, paths)
end

# quick way to get a simple array of hashes of the entries
# of a single tree or recursive tree listing from a given
# sha or reference
# +treeish+ is the reference (default 'master')
# +options+ is a hash or options - currently only takes :recursive
#
# Examples
# repo.lstree('master', :recursive => true)
#
# Returns array of hashes - one per tree entry
def lstree(treeish = 'master', options = {})
# check recursive option
opts = {:timeout => false, :l => true, :t => true}
if options[:recursive]
opts[:r] = true
end
# mode, type, sha, size, path
revs = self.git.native(:ls_tree, opts, treeish)
lines = revs.split("\n")
revs = lines.map do |a|
stuff, path = a.split("\t")
mode, type, sha, size = stuff.split(" ")
entry = {:mode => mode, :type => type, :sha => sha, :path => path}
entry[:size] = size.strip.to_i if size.strip != '-'
entry
end
revs
end

# The Blob object for the given id
# +id+ is the SHA1 id of the blob
#
Expand Down
37 changes: 34 additions & 3 deletions lib/grit/tag.rb
Expand Up @@ -18,6 +18,32 @@ def self.find_all(repo, options = {})
end
end

# Writes a new tag object from a hash
# +repo+ is a Grit repo
# +hash+ is the hash of tag values
#
# Returns a hash with +sha+ and +size+ of the created object
def self.create_tag_object(repo, hash, default_actor = nil)
tagger = hash[:tagger]
if !tagger
tagger = default_actor ? default_actor : Actor.new("none", "none@none")
tagger_date = Time.now
else
tagger_date = tagger[:date] ? Time.parse(tagger[:date]) : Time.now
tagger = Actor.new(tagger[:name], tagger[:email])
end
data = []
data << "object #{hash[:object]}"
data << "type #{hash[:type]}"
data << "tag #{hash[:tag]}"
data << "tagger #{tagger.output(tagger_date)}"
data << ""
data << hash[:message]
data = data.join("\n")
sha = repo.git.put_raw_object(data, 'tag')
{ :sha => sha, :size => data.size }
end

# Parses the results from `cat-file -p`
#
# data - String tag object data. Example:
Expand All @@ -34,9 +60,9 @@ def self.parse_tag_data(data)
return unless data =~ /^object/
parsed = {}
lines = data.split("\n")
lines.shift # type commit
lines.shift # tag name
lines.shift
parsed[:object] = lines.shift.sub(/^object /, '')
parsed[:type] = lines.shift.sub(/^type /, '')
parsed[:tag] = lines.shift.sub(/^tag /, '')
author_line = lines.shift
parsed[:tagger], parsed[:tag_date] = Commit.actor(author_line)
if !parsed[:tagger] || !parsed[:tagger].name
Expand All @@ -49,6 +75,11 @@ def self.parse_tag_data(data)
parsed[:message] << lines.shift
end
parsed[:message] = parsed[:message] * "\n"
parsed[:pgp] = []
while lines.first
parsed[:pgp] << lines.shift
end
parsed[:pgp] = parsed[:pgp] * "\n"
parsed
end

Expand Down
7 changes: 7 additions & 0 deletions test/test_commit.rb
Expand Up @@ -193,6 +193,13 @@ def test_to_patch
assert patch.include?("1.7.")
end

# patch_id

def test_patch_id
@c = Commit.create(@r, :id => '80f136f500dfdb8c3e8abf4ae716f875f0a1b57f')
assert_equal '9450b04e4f83ad0067199c9e9e338197d1835cbb', @c.patch_id
end

# inspect

def test_inspect
Expand Down

0 comments on commit 9042243

Please sign in to comment.