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 match a repository. Any thoughts on what we
> could do there?
>
> As for your second problem, post-review requires a non-bare repository
> as it tries to automatically determine the diff of your current work.
> You may want to try the revision-range option to explicitly set the
> revision range. I haven't confirmed that this will work in a bare
> repository, but it should be easy to make it if it doesn't.
>
> Dan
>
> On Aug 6, 5:48 pm, Yang Zhang <yanghates...@gmail.com> wrote:
>> I'm trying to automate post-review to run on a git repository --
>> ideally on each commit (on the "client" side), but on each push (on
>> the central repo) would do too if necessary.
>>
>> In both the following I ran "git config reviewboard.urlhttps://dev/review/";.
>>
>> First I tried post-review on a client repo (also tried specifying
>> --repository-url=/var/git/web.git, which is the local URL that the
>> reviewboard web app knows):
>>
>> ~~~
>> $ post-review --revision-range=9405af7d9a75c17
>> 03b88924021fc9f2677c4776b
>> ==> HTTP Authentication Required
>> Enter username and password for "dev" at dev
>> Username: yang
>> Password:
>>
>> There was an error creating this review request.
>>
>> The repository path "ssh://dev/var/git/web.git" is not in the
>> list of known repositories on the server.
>>
>> Ask the administrator to add this repository to the Review Board server.
>> For information on adding repositories, please 
>> readhttp://www.reviewboard.org/docs/manual/dev/admin/management/repositor...
>> ~~~
>>
>> I thought about trying to set up a mirror URL in the reviewboard web
>> app, but the URL might look different to each client.
>>
>> On the server, the repository is headless, resulting in this error:
>>
>> ~~~
>> $ post-review
>> Failed to execute command: ['git', 'symbolic-ref', '-q', 'HEAD']
>> fatal: Not a git repository (or any of the parent directories): .git
>> ~~~
>>
>> After Googling I 
>> foundhttp://gitorious.org/reviewboard/rbtools/blobs/master/scripts/git-pos...
>> but it's broken & out of date.
>>
>> There are more hacks I can try (e.g. having the post-commit hook
>> temporarily munge the remote origin URL, or having the post-receive
>> hook clone the git repository so that it has a head, then
>> post-review-ing that), but surely there's a better way. Thanks in
>> advance for any hints.
>> --
>> Yang Zhanghttp://yz.mit.edu/
>
> --
> Want to help the Review Board project? Donate today at 
> http://www.reviewboard.org/donate/
> Happy user? Let us know at http://www.reviewboard.org/users/
> -~----------~----~----~----~------~----~------~--~---
> To unsubscribe from this group, send email to 
> reviewboard+unsubscr...@googlegroups.com
> For more options, visit this group at 
> http://groups.google.com/group/reviewboard?hl=en



-- 
Yang Zhang
http://yz.mit.edu/

-- 
Want to help the Review Board project? Donate today at 
http://www.reviewboard.org/donate/
Happy user? Let us know at http://www.reviewboard.org/users/
-~----------~----~----~----~------~----~------~--~---
To unsubscribe from this group, send email to 
reviewboard+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/reviewboard?hl=en

Reply via email to