author |
Steve Losh <steve@stevelosh.com> |
date |
Tue, 02 Mar 2010 19:04:41 -0500 |
parents |
d22951120189 |
children |
36b37712c670 |
"""The review extension's web UI."""
from __future__ import with_statement
import sys, os
import api
from mercurial import cmdutil, hg
package_path = os.path.split(os.path.realpath(__file__))[0]
template_path = os.path.join(package_path, 'web_templates')
media_path = os.path.join(package_path, 'web_media')
top_path = os.path.split(package_path)[0]
bundled_path = os.path.join(top_path, 'bundled')
webpy_path = os.path.join(bundled_path, 'webpy')
sys.path.insert(0, webpy_path)
import web
_rd = None
urls = (
'/', 'index',
'/media/([^/]*)', 'media',
'/review/([\da-f]{12})/?', 'review',
'/push/', 'push',
'/pull/', 'pull',
)
from mercurial.node import short
from mercurial.util import email
from mercurial import templatefilters
from hashlib import md5
g = {
'node_short': short,
'basename': os.path.basename,
'md5': md5,
'email': email,
'templatefilters': templatefilters,
}
render = web.template.render(template_path, globals=g)
LOG_PAGE_LEN = 25
def render_in_base(fn):
def _fn(*args, **kwargs):
title, content = fn(*args, **kwargs)
return render.base(_rd, content, title)
return _fn
class index:
@render_in_base
def GET(self):
rev_max = _rd.target['tip'].rev()
rev_min = rev_max - LOG_PAGE_LEN if rev_max >= LOG_PAGE_LEN else 0
revs = (_rd.target[r] for r in xrange(rev_max, rev_min, -1))
return ('', render.index(_rd, revs))
class review:
@render_in_base
def GET(self, node_short):
title = '/ %s:%s – %s' % (
_rd[node_short].target[node_short].rev(),
node_short,
_rd[node_short].target[node_short].description().splitlines()[0])
return (title, render.review(_rd, _rd[node_short]))
def POST(self, node_short):
i = web.input()
body = i['body']
filename = i['filename'] if 'filename' in i else ''
lines = i['lines'].split(',') if 'lines' in i else ''
print filename, lines
if body:
rcset = _rd[node_short]
rcset.add_comment(body, filename, lines)
raise web.seeother('/review/%s/' % node_short)
class push:
def GET(self):
path = web.input()['path']
dest, revs, checkout = hg.parseurl(_rd.repo.ui.expandpath(path, path), None)
other = hg.repository(cmdutil.remoteui(_rd.repo, {}), dest)
_rd.repo.push(other, True, revs=revs)
raise web.seeother('/')
class pull:
def GET(self):
path = web.input()['path']
source, revs, checkout = hg.parseurl(_rd.repo.ui.expandpath(path, path), None)
other = hg.repository(cmdutil.remoteui(_rd.repo, {}), source)
modheads = _rd.repo.pull(other, heads=revs, force=True)
if modheads:
hg.update(_rd.repo, 'tip')
raise web.seeother('/')
class media:
def GET(self, fname):
if '..' in fname:
return ''
else:
with open(os.path.join(media_path, fname)) as f:
content = f.read()
return content
def load_interface(ui, repo, open=False):
global _rd
_rd = api.ReviewDatastore(ui, repo)
sys.argv = sys.argv[:1] # Seriously, web.py? This is such a hack.
app = web.application(urls, globals())
if open:
import webbrowser
webbrowser.open(app.browser().url)
app.run()