Re: Help with git configuration

2010-08-12 Thread Yang Zhang
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 

Re: Help with git configuration

2010-08-10 Thread Dan Savilonis
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