FWIW, this is the post-receive hook I hacked up - maybe this will be
useful to someone else out there. On a `git push`, it will create
review requests for each (non-merge) commit. Some notes:
- It works with an unmodified postreview.py.
- It runs on bare git repositories.
- It sets the summary and description based on the commit summary and
commit message (and also mentions the relevant commit IDs).
- It extracts ticket references (currently using Redmine tracker style
references) and sets the structured field appropriately.
- It also supplies the username/password from a file, and does the log
in just once, instead of per post.
- It submits the ticket as the appropriate author. For now it simply
targets the other non-authors (probably typical for 2-4-person teams).
- It checks first to see if the repository is a registered one, and
won't generate an error if it isn't.
- It will also hide the stderr (username/password prompts) unless
there was an error, and it will also correct the URL on stdout, in
case the URL used by the script is different from users should see.
- It requires the 'git' Python package.
#!/usr/bin/env python
from rbtools.postreview import *
from cStringIO import StringIO
import cookielib, git, logging, os, sys, urllib2
log = logging.getLogger(__name__)
log.addHandler(logging.StreamHandler(sys.stderr))
#log.setLevel(logging.DEBUG)
users = 'jack john joe'.split()
# start post-receive-mailer
def get_commits(old_rev, new_rev):
p = subprocess.Popen(['git', 'log', '--pretty=format:%H', '--reverse',
'%s..%s' % (old_rev, new_rev)],
stdout=subprocess.PIPE)
return p.stdout.read().split('\n')
def parse_post_receive_line(l):
return l.split()
# end post-receive-mailer
class container(object):
def capture(self, func):
stdout, stderr = sys.stdout, sys.stderr
sys.stdout, sys.stderr = StringIO(), StringIO()
try:
try:
return func()
finally:
self.stdout, self.stderr = sys.stdout, sys.stderr
sys.stdout, sys.stderr = stdout, stderr
except:
print sys.stderr, self.stdout.getvalue()
print sys.stderr, self.stderr.getvalue()
sys.excepthook(*sys.exc_info())
raise
buf = container()
with open('/opt/git-helpers/share/review-login') as f:
user, passwd = map(str.rstrip, f.readlines())
parse_options(['--username=' + user,'--password=' + passwd])
info = RepositoryInfo(os.getcwd())
server = ReviewBoardServer('http://localhost/review/', info,
'/opt/git-helpers/share/review-cookies')
buf.capture(lambda: server.login())
log.debug(checking if %s registered % os.getcwd())
if os.getcwd() in [x['path'] for x in server.get_repositories()]:
repo = git.Repo('.')
for line in sys.stdin:
log.debug(parsing revision line + line)
old_rev, new_rev, ref_name = parse_post_receive_line(line)
for chash in get_commits(old_rev, new_rev):
c = repo.commit(chash)
cmd = 'git diff-tree -p --full-index'.split()
diff = execute(cmd + [chash])
log.debug(diff:\n + diff)
author = c.author.email.split('@')[0]
targets = ','.join(u for u in users if u != author)
bugs = ','.join(m.group(1) for m in
re.finditer(r'(?:refs|fixes|closes) #(\d+)', c.message))
osuser = os.environ['USER']
log.info('should post? author %s osuser %s' % (author, osuser))
if osuser == author and diff.strip() != '':
parse_options(['--publish',
'--bugs-closed='+bugs,
'--submit-as='+author,
'--summary='+c.summary,
'--description='+c.message + '\n\n' +
c.parents[0].id + ' ' + c.id,
'--target-people='+targets])
try:
log.info('posting')
review_url = buf.capture(lambda: tempt_fate(server, None, None,
diff_content=diff, parent_diff_content=None, submit_as=author))
except:
pass
else:
print buf.stdout.getvalue().replace('http://localhost',
'https://dev.example.com')
On Tue, Aug 10, 2010 at 10:06 AM, Dan Savilonis d...@n-cube.org wrote:
Hi Yang,
This actually brings up a good point. I don't think there currently is
a 'better' solution. I hope Christian can perhaps chime in on this,
since RB is using git itself. The conventional way to set this up is
to configure the mirror url, but this assumes that the client fetch
from a remote with the exact same path. This doesn't work well for a
number of reasons since it might not even be cloned from the same
server, or it might use implicit vs explicit ssh notation, or use a
non-fqdn, etc.
I think we need to address this somehow. On the post-review side, my
thought was to add an option for .reviewboardrc to specify the
'repository url'. However, there clearly should be some improvement on
the server side as well, as a fixed 'mirror' field just isn't good
enough to comprehensively