On Fri, Apr 19, 2013 at 2:30 PM, Felipe Contreras <felipe.contreras@xxxxxxxxx> 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 <felipe.contreras@xxxxxxxxx> (author: 100%) > Jeff King <peff@xxxxxxxx> (signer: 83%) > Max Horn <max@xxxxxxxxx> (signer: 16%) > Junio C Hamano <gitster@xxxxxxxxx> (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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html