1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
module Grit
class CommitStats
attr_reader :id, :files, :additions, :deletions, :total
# Instantiate a new CommitStats
# +id+ is the id of the commit
# +files+ is an array of :
# [ [filename, adds, deletes, total],
# [filename, adds, deletes, total],
# [filename, adds, deletes, total] ]
#
# Returns Grit::CommitStats (baked)
def initialize(repo, id, files)
@repo = repo
@id = id
@files = files
@additions = files.inject(0) { |total, a| total += a[1] }
@deletions = files.inject(0) { |total, a| total += a[2] }
@total = files.inject(0) { |total, a| total += a[3] }
end
# Find all commit stats matching the given criteria.
# +repo+ is the Repo
# +ref+ is the ref from which to begin (SHA1 or name) or nil for --all
# +options+ is a Hash of optional arguments to git
# :max_count is the maximum number of commits to fetch
# :skip is the number of commits to skip
#
# Returns assoc array [sha, Grit::Commit[] (baked)]
def self.find_all(repo, ref, options = {})
allowed_options = [:max_count, :skip, :since]
default_options = {:numstat => true}
actual_options = default_options.merge(options)
if ref
output = repo.git.log(actual_options, ref)
else
output = repo.git.log(actual_options.merge(:all => true))
end
self.list_from_string(repo, output)
end
# Parse out commit information into an array of baked Commit objects
# +repo+ is the Repo
# +text+ is the text output from the git command (raw format)
#
# Returns assoc array [sha, Grit::Commit[] (baked)]
def self.list_from_string(repo, text)
lines = text.split("\n")
commits = []
while !lines.empty?
id = lines.shift.split.last
lines.shift
lines.shift
lines.shift
message_lines = []
message_lines << lines.shift[4..-1] while lines.first =~ /^ {4}/ || lines.first == ''
lines.shift while lines.first && lines.first.empty?
files = []
while lines.first =~ /^([-\d]+)\s+([-\d]+)\s+(.+)/
(additions, deletions, filename) = lines.shift.split(nil, 3)
additions = additions.to_i
deletions = deletions.to_i
total = additions + deletions
files << [filename, additions, deletions, total]
end
lines.shift while lines.first && lines.first.empty?
commits << [id, CommitStats.new(repo, id, files)]
end
commits
end
# Pretty object inspection
def inspect
%Q{#<Grit::CommitStats "#{@id}">}
end
# Convert to an easy-to-traverse structure
def to_diffstat
files.map do |metadata|
DiffStat.new(*metadata)
end
end
# private
def to_hash
{
'id' => id,
'files' => files,
'additions' => additions,
'deletions' => deletions,
'total' => total
}
end
end # CommitStats
class DiffStat
attr_reader :filename, :additions, :deletions
def initialize(filename, additions, deletions, total=nil)
@filename, @additions, @deletions = filename, additions, deletions
end
def net
additions - deletions
end
def inspect
"#{filename}: +#{additions} -#{deletions}"
end
end
end # Grit
|