On Fri, Apr 19, 2013 at 2:30 PM, Felipe Contreras
<[email protected]> wrote:
> This script find people that might be interesting in a patch, by going
> back through the history for each single hunk modified, and finding
> people that reviewed, acknowledge, signed, or authored the code the
> patch is modifying.
>
> It does this by running 'git blame' incrementally on each hunk, and then
> parsing the commit message. After gathering all the relevant people, it
> groups them to show what exactly was their role when the participated in
> the development of the relevant commit, and on how many relevant commits
> they participated. They are only displayed if they pass a minimum
> threshold of participation.
>
> For example:
>
> % git cc-cmd 0001-remote-hg-trivial-cleanups.patch
> Felipe Contreras <[email protected]> (author: 100%)
> Jeff King <[email protected]> (signer: 83%)
> Max Horn <[email protected]> (signer: 16%)
> Junio C Hamano <[email protected]> (signer: 16%)
>
> Thus it can be used for 'git send-email' as a cc-cmd.
Here's the interdiff with the previous one:
diff --git a/contrib/cc-cmd/git-cc-cmd b/contrib/cc-cmd/git-cc-cmd
index c7ecf79..aa83a1a 100755
--- a/contrib/cc-cmd/git-cc-cmd
+++ b/contrib/cc-cmd/git-cc-cmd
@@ -5,40 +5,35 @@ $min_percent = 5
class Commit
- attr_reader :id
- attr_accessor :roles
+ attr_reader :id, :roles
def initialize(id)
@id = id
@roles = []
end
- def self.parse(data)
- id = author = msg = nil
+ def parse(data)
+ author = msg = nil
roles = {}
data.each_line do |line|
if not msg
case line
- when /^commit (.+)$/
- id = $1
when /^author ([^<>]+) <(\S+)>$/
author = $1, $2
- roles[author] = 'author'
+ roles[author] = :author
when /^$/
msg = true
end
else
if line =~ /^(Signed-off|Reviewed|Acked)-by: ([^<>]+) <(\S+?)>$/
person = $2, $3
- roles[person] = 'signer' if person != author
+ roles[person] = :signer if person != author
end
end
end
- roles = roles.map do |person, role|
- address = "%s <%s>" % person
+ @roles = roles.map do |person, role|
[person, role]
end
- [id, roles]
end
end
@@ -57,22 +52,15 @@ class Commits
def import
return if @items.empty?
- format = [ 'commit %H', 'author %an <%ae>', '', '%B' ].join('%n')
- File.popen(['git', 'show', '-z', '-s', '--format=format:' +
format] + @items.keys) do |p|
- p.each("\0") do |data|
- next if data == "\0" # bug in git show?
- id, roles = Commit.parse(data)
- commit = @items[id]
- commit.roles = roles
- end
- end
- end
-
- def each_person_role
- commit_roles = @items.values.map { |commit| commit.roles }.flatten(1)
- commit_roles.group_by { |person, role| person }.each do |person,
commit_roles|
- commit_roles.group_by { |person, role| role }.each do |role,
commit_roles|
- yield person, role, commit_roles.size
+ File.popen(%w[git cat-file --batch], 'r+') do |p|
+ p.write(@items.keys.join("\n"))
+ p.close_write
+ p.each do |l|
+ if l =~ /^(\h{40}) commit (\d+)/
+ id, len = $1, $2
+ data = p.read($2.to_i)
+ @items[id].parse(data)
+ end
end
end
end
@@ -107,34 +95,37 @@ class Commits
end
end
end
- import
end
end
exit 1 if ARGV.size != 1
-commits = Commits.new()
+commits = Commits.new
commits.from_patch(ARGV[0])
+commits.import
# hash of hashes
persons = Hash.new { |hash, key| hash[key] = {} }
-commits.each_person_role do |person, role, count|
- persons[person][role] = count
+commits.items.values.each do |commit|
+ commit.roles.each do |person, role|
+ persons[person][role] ||= 0
+ persons[person][role] += 1
+ end
end
persons.each do |person, roles|
roles = roles.map do |role, count|
percent = count.to_f * 100 / commits.size
next if percent < $min_percent
- "%s: %u%%" % [role, percent]
+ '%s: %u%%' % [role, percent]
end.compact
next if roles.empty?
name, email = person
# must quote chars?
name = '"%s"' % name if name =~ /[^\w \-]/i
- person = name ? "%s <%s>" % [name, email] : email
- puts "%s (%s)" % [person, roles.join(', ')]
+ person = name ? '%s <%s>' % [name, email] : email
+ puts '%s (%s)' % [person, roles.join(', ')]
end
--
Felipe Contreras
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html