Skip to content

Instantly share code, notes, and snippets.

@felipec
Last active June 19, 2021 21:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felipec/f1289a48e31195ee1f36c28ca6e482db to your computer and use it in GitHub Desktop.
Save felipec/f1289a48e31195ee1f36c28ca6e482db to your computer and use it in GitHub Desktop.
git-reviewers
#!/usr/bin/env ruby
require 'notmuch'
$skip = <<EOF.split("\n")
xmqqsgg7u3js.fsf@gitster.c.googlers.com
CAPig+cRqvd=_n9huD_txEr6EXVrWZx0onReL5bh_mCKy3M3LOg@mail.gmail.com
xmqqy2g08o0r.fsf@gitster.c.googlers.com
20190930153741.GA6124@chatter.i7.local
53844AEF.1080502@alum.mit.edu
xmqq8uslu1bi.fsf@gitster.dls.corp.google.com
CALKQrgdJ6d2SVWNQGa6d-eLYPAL-C21=tCyJczCDExLQRfq=jA@mail.gmail.com
EOF
$db = Notmuch::Database.new(ENV['HOME'] + '/mail')
def get_content(id)
`notmuch show --part=1 id:#{id} | grep --text -v -E '^>'`.scrub.sub(/--* (>8|8<) --.*/, '').sub(/^From: .*/m, '')
end
def check_msg(msg)
return false unless msg['subject'].start_with?('Re: ')
get_content(msg.message_id) =~ /^\s*Reviewed-by: /
end
def get_all_replies(msg)
all = []
msg.replies.each do |reply|
all << reply
all += get_all_replies(reply)
end
all
end
$cached_threads = {}
def check_explicit(subject)
query = $db.query('tag:git subject:"%s"' % subject)
query.search_messages.each do |msg|
next if $skip.include?(msg.message_id)
return true if check_msg(msg)
end
query.search_threads.each do |thread|
thread.toplevel_messages.each do |msg|
return true if $cached_threads[thread.thread_id]
get_all_replies(msg).each do |reply|
if check_msg(reply)
$cached_threads[thread.thread_id] = true
return true
end
end
end
end
return false
end
ROLES_REGEX = /^([^ \t\n\[\]\(\):]+): ([^<>]+) <(\S+?)>$/
$reviewers = Hash.new(0)
log_args = [ '--no-merges', '--since=10-years-ago', '--format=%h%n%s%n%aN%n%aE%n%as%n%b%x00', '--', ':!po/' ]
IO.popen(%w[git log] + log_args + ARGV) do |pipe|
pipe.each("\0\n", chomp: true) do |commit|
id, subject, name, email, date, body = commit.scrub.split("\n", 6)
trailer = body.split("\n\n").last
next unless trailer
trailer.scan(ROLES_REGEX) do
role = $1.downcase
if role == 'reviewed-by'
explicit = check_explicit(subject)
puts '%s: %s: %s%s' % [id, date, $2, explicit ? ' *' : '']
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment