#
#
# rename "MochiKit"
# to "static/MochiKit"
#
# rename "about.psp"
# to "old_version/about.psp"
#
# rename "branch.psp"
# to "old_version/branch.psp"
#
# rename "diff.psp"
# to "old_version/diff.psp"
#
# rename "error.psp"
# to "old_version/error.psp"
#
# rename "file.psp"
# to "old_version/file.psp"
#
# rename "fileinbranch.psp"
# to "old_version/fileinbranch.psp"
#
# rename "headofbranch.psp"
# to "old_version/headofbranch.psp"
#
# rename "help.psp"
# to "old_version/help.psp"
#
# rename "index.psp"
# to "old_version/index.psp"
#
# rename "manifest.psp"
# to "old_version/manifest.psp"
#
# rename "revision.psp"
# to "old_version/revision.psp"
#
# rename "rss_feed.gif"
# to "static/rss_feed.gif"
#
# rename "tags.psp"
# to "old_version/tags.psp"
#
# rename "tarofbranch.psp"
# to "old_version/tarofbranch.psp"
#
# rename "viewmtn.css"
# to "static/viewmtn.css"
#
# rename "viewmtn.js"
# to "static/viewmtn.js"
#
# add_dir "old_version"
#
# add_dir "static"
#
# patch "mtn.py"
# from [402aba6497fb89242b82920b3a3222fbf7088eaf]
# to [56f9a515d67b8516d43b1b65cadd2183166b04ad]
#
# patch "viewmtn.py"
# from [fb9d3d9fa86e7ae6b4e9ee3be5ac53fa944c6147]
# to [7728db1166843eaeee789a1c821dcc4f804c96c7]
#
============================================================
--- mtn.py 402aba6497fb89242b82920b3a3222fbf7088eaf
+++ mtn.py 56f9a515d67b8516d43b1b65cadd2183166b04ad
@@ -8,7 +8,7 @@ import web
import popen2
import web
-debug = web.debug
+from web import debug
# regular expressions that are of general use when
# validating monotone output
@@ -25,32 +25,32 @@ class Revision(str):
class Revision(str):
def __init__(self, v):
- str.__init__(v)
- if not revision_re_c.match(self):
- raise MonotoneException("Not a valid revision ID")
+ str.__init__(v)
+ if not revision_re_c.match(self):
+ raise MonotoneException("Not a valid revision ID")
def abbrev(self):
- return '[' + self[:8] + '..]'
+ return '[' + self[:8] + '..]'
def set_nonblocking(fd):
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY)
def terminate_popen3(process):
- debug("%s stopping %s" % (os.getpid(), process.pid))
+ debug("[%s] stopping process: %s" % (os.getpid(), process.pid))
try:
process.tochild.close()
process.fromchild.close()
- process.childerr.close()
+ process.childerr.close()
if process.poll() == -1:
# the process is still running, so kill it.
os.kill(process.pid, signal.SIGKILL)
process.wait()
except:
- debug("%s failed_to_stop %s" % (os.getpid(), self.process.pid))
+ debug("%s failed_to_stop %s" % (os.getpid(), self.process.pid))
class Runner:
def __init__(self, monotone, database):
- self.base_command = [monotone, "--db=%s" % pipes.quote(database)]
+ self.base_command = [monotone, "--db=%s" % pipes.quote(database)]
packet_header_re = re.compile(r'^(\d+):(\d+):([lm]):(\d+):')
import web
@@ -58,133 +58,136 @@ class Automate(Runner):
class Automate(Runner):
"""Runs commands via a particular monotone process. This
process is started the first time run() is called, and
- stopped when this class instance is deleted.
+ stopped when this class instance is deleted or the stop()
+ method is called.
If an error occurs, the monotone process may need to be
stopped and a new one created.
"""
def __init__(self, *args, **kwargs):
- Runner.__init__(*[self] + list(args), **kwargs)
- self.lock = threading.Lock()
- self.process = None
+ Runner.__init__(*[self] + list(args), **kwargs)
+ self.lock = threading.Lock()
+ self.process = None
def stop(self):
if not self.process:
- return
- terminate_popen3(self.process)
+ return
+ terminate_popen3(self.process)
def __process_required(self):
- if self.process != None:
- return
- to_run = self.base_command + ['automate', 'stdio']
- self.process = popen2.Popen3(to_run, capturestderr=True)
- map (set_nonblocking, [ self.process.fromchild,
- self.process.tochild,
- self.process.childerr ])
+ if self.process != None:
+ return
+ to_run = self.base_command + ['automate', 'stdio']
+ self.process = popen2.Popen3(to_run, capturestderr=True)
+ map (set_nonblocking, [ self.process.fromchild,
+ self.process.tochild,
+ self.process.childerr ])
def run(self, *args, **kwargs):
- if not self.lock.acquire(False):
- raise MonotoneException("Automate process can't be called: it is already locked.")
- try:
- rv = apply(self.__run, args, kwargs)
- finally:
- self.lock.release()
- return rv
+ debug(("automate is running:", args, kwargs))
+ if not self.lock.acquire(False):
+ raise MonotoneException("Automate process can't be called: it is already locked.")
+ try:
+ rv = apply(self.__run, args, kwargs)
+ finally:
+ self.lock.release()
+ return rv
def __run(self, command, args):
- self.__process_required()
+ self.__process_required()
enc = "l%d:%s" % (len(command), command)
enc += ''.join(map(lambda x: "%d:%s" % (len(x), x), args)) + 'e'
- self.process.tochild.write(enc)
- self.process.tochild.flush()
+ self.process.tochild.write(enc)
+ self.process.tochild.flush()
- import sys
- def read_result_packets():
- buffer = ""
- while True:
- r_stdin, r_stdout, r_stderr = select.select([self.process.fromchild], [], [], None)
- if not r_stdin and not r_stdout and not r_stderr:
- break
+ import sys
+ def read_result_packets():
+ buffer = ""
+ while True:
+ r_stdin, r_stdout, r_stderr = select.select([self.process.fromchild], [], [], None)
+ if not r_stdin and not r_stdout and not r_stderr:
+ break
- if self.process.fromchild in r_stdin:
- data = self.process.fromchild.read()
- if data == "":
- break
- buffer += data
+ if self.process.fromchild in r_stdin:
+ data = self.process.fromchild.read()
+ if data == "":
+ break
+ buffer += data
- # loop, trying to get complete packets out of our buffer
- complete, in_packet = False, False
- while not complete and buffer != '':
- if not in_packet:
- m = packet_header_re.match(buffer)
- if not m:
- break
- in_packet = True
- cmdnum, errnum, pstate, length = m.groups()
- errnum = int(errnum)
- length = int(length)
- header_length = m.end(m.lastindex) + 1 # the '1' is the colon
+ # loop, trying to get complete packets out of our buffer
+ complete, in_packet = False, False
+ while not complete and buffer != '':
+ if not in_packet:
+ m = packet_header_re.match(buffer)
+ if not m:
+ break
+ in_packet = True
+ cmdnum, errnum, pstate, length = m.groups()
+ errnum = int(errnum)
+ length = int(length)
+ header_length = m.end(m.lastindex) + 1 # the '1' is the colon
- if len(buffer) < length + header_length:
- # not enough data read from client yet; go round
- break
- else:
- result = buffer[header_length:header_length+length]
- buffer = buffer[header_length+length:]
- complete = pstate == 'l'
- in_packet = False
- yield errnum, complete, result
+ if len(buffer) < length + header_length:
+ # not enough data read from client yet; go round
+ break
+ else:
+ result = buffer[header_length:header_length+length]
+ buffer = buffer[header_length+length:]
+ complete = pstate == 'l'
+ in_packet = False
+ yield errnum, complete, result
- if complete:
- break
-
- # get our response, and yield() it back one line at a time
- code_max = -1
- for code, is_last, data in read_result_packets():
- if code and code > code_max:
- code_max = code
- for line in data.split('\n'):
- yield line + '\n'
- if code_max > 0:
- raise MonotoneException("error code %d in automate packet." % (code_max))
+ if complete:
+ break
+
+ # get our response, and yield() it back one line at a time
+ code_max = -1
+ for code, is_last, data in read_result_packets():
+ if code and code > code_max:
+ code_max = code
+ for line in data.split('\n'):
+ yield line + '\n'
+ if code_max > 0:
+ raise MonotoneException("error code %d in automate packet." % (code_max))
class Standalone(Runner):
"""Runs commands by running monotone. One monotone process
per command"""
def run(self, command, args):
- # as we pass popen3 as sequence, it executes monotone with these
- # arguments - and does not pass them through the shell according
- # to help(os.popen3)
- to_run = self.base_command + [command] + args
- process = popen2.Popen3(to_run, capturestderr=True)
- for line in process.fromchild:
- yield line
- stderr_data = process.childerr.read()
- if len(stderr_data) > 0:
- raise MonotoneException("data on stderr for command '%s': %s" % (command,
- stderr_data))
- terminate_popen3(process)
+ # as we pass popen3 as sequence, it executes monotone with these
+ # arguments - and does not pass them through the shell according
+ # to help(os.popen3)
+ debug(("standalone is running:", command, args))
+ to_run = self.base_command + [command] + args
+ process = popen2.Popen3(to_run, capturestderr=True)
+ for line in process.fromchild:
+ yield line
+ stderr_data = process.childerr.read()
+ if len(stderr_data) > 0:
+ raise MonotoneException("data on stderr for command '%s': %s" % (command,
+ stderr_data))
+ terminate_popen3(process)
class MtnObject:
def __init__(self, obj_type):
- self.obj_type = obj_type
+ self.obj_type = obj_type
class Tag(MtnObject):
def __init__(self, name, revision, author):
- MtnObject.__init__(self, "tag")
- self.name, self.revision, self.author = name, Revision(revision), author
+ MtnObject.__init__(self, "tag")
+ self.name, self.revision, self.author = name, Revision(revision), author
class Branch(MtnObject):
def __init__(self, name):
- MtnObject.__init__(self, "branch")
- self.name = name
+ MtnObject.__init__(self, "branch")
+ self.name = name
class File(MtnObject):
def __init__(self, name, in_revision):
- MtnObject.__init__(self, "file")
- self.name = name
- self.in_revision = in_revision
+ MtnObject.__init__(self, "file")
+ self.name = name
+ self.in_revision = in_revision
basic_io_name_tok = re.compile(r'^(\S+)')
@@ -194,113 +197,113 @@ def basic_io_from_stream(gen):
# new value of line (eg. with consumed tokens removed)
def hex_consume(line):
- m = revision_re_c.match(line[1:])
- if line[0] != '[' or not m:
- raise MonotoneException("This is not a hex token: %s" % line)
- end_of_match = m.end(m.lastindex)
- if line[end_of_match+1] != ']':
- raise MonotoneException("Hex token ends in character other than ']': %s" % line)
- return Revision(m.groups()[0]), choose_consume, line[end_of_match+2:]
+ m = revision_re_c.match(line[1:])
+ if line[0] != '[' or not m:
+ raise MonotoneException("This is not a hex token: %s" % line)
+ end_of_match = m.end(m.lastindex)
+ if line[end_of_match+1] != ']':
+ raise MonotoneException("Hex token ends in character other than ']': %s" % line)
+ return Revision(m.groups()[0]), choose_consume, line[end_of_match+2:]
def name_consume(line):
- m = name_re_c.match(line)
- if not m:
- raise MonotoneException("Not a name: %s" % line)
- end_of_match = m.end(m.lastindex)
- return m.groups()[0], choose_consume, line[end_of_match:]
+ m = name_re_c.match(line)
+ if not m:
+ raise MonotoneException("Not a name: %s" % line)
+ end_of_match = m.end(m.lastindex)
+ return m.groups()[0], choose_consume, line[end_of_match:]
def choose_consume(line):
- line = line.lstrip()
- if line == '':
- consumer = choose_consume
- elif line[0] == '[':
- consumer = hex_consume
- elif line[0] == '"':
- consumer = string_consume
- else:
- consumer = name_consume
- return None, consumer, line
+ line = line.lstrip()
+ if line == '':
+ consumer = choose_consume
+ elif line[0] == '[':
+ consumer = hex_consume
+ elif line[0] == '"':
+ consumer = string_consume
+ else:
+ consumer = name_consume
+ return None, consumer, line
class StringState:
- def __init__(self):
- self.in_escape = False
- self.has_started = False
- self.has_ended = False
- self.value = ''
+ def __init__(self):
+ self.in_escape = False
+ self.has_started = False
+ self.has_ended = False
+ self.value = ''
def string_consume(line, state=None):
- if not state:
- state = StringState()
+ if not state:
+ state = StringState()
- if not state.has_started:
- if line[0] != '"':
- raise MonotoneException("Not a string: %s" % line)
- line = line[1:]
- state.has_started = True
+ if not state.has_started:
+ if line[0] != '"':
+ raise MonotoneException("Not a string: %s" % line)
+ line = line[1:]
+ state.has_started = True
- for idx, c in enumerate(line):
- if state.in_escape:
- if c != '\\' or c != '\"':
- raise MonotoneException("Invalid escape code: %s\n" % line)
- state.value += c
- state.in_escape = False
- else:
- if c == '\\':
- state.in_escape = True
- elif c == '"':
- state.has_ended = True
- break
- else:
- state.value += c
+ for idx, c in enumerate(line):
+ if state.in_escape:
+ if c != '\\' or c != '\"':
+ raise MonotoneException("Invalid escape code: %s\n" % line)
+ state.value += c
+ state.in_escape = False
+ else:
+ if c == '\\':
+ state.in_escape = True
+ elif c == '"':
+ state.has_ended = True
+ break
+ else:
+ state.value += c
- if state.has_ended:
- return state.value, choose_consume, line[idx+1:]
- else:
- return (None,
- lambda s: string_consume(s, state),
- line[idx+1:])
+ if state.has_ended:
+ return state.value, choose_consume, line[idx+1:]
+ else:
+ return (None,
+ lambda s: string_consume(s, state),
+ line[idx+1:])
consumer = choose_consume
current_stanza = []
for line in gen:
- # if we're not in an actual consumer (which we shouldn't be, unless
- # we're parsing some sort of multi-line token) and we have a blank
- # line, it indicates the end of any current stanza
- if (consumer == choose_consume) and (line == '' or line == '\n') and current_stanza:
- yield current_stanza
- current_stanza = []
- continue
+ # if we're not in an actual consumer (which we shouldn't be, unless
+ # we're parsing some sort of multi-line token) and we have a blank
+ # line, it indicates the end of any current stanza
+ if (consumer == choose_consume) and (line == '' or line == '\n') and current_stanza:
+ yield current_stanza
+ current_stanza = []
+ continue
- while line != '' and line != '\n':
- new_token, consumer, line = consumer(line)
- if new_token != None:
- current_stanza.append(new_token)
+ while line != '' and line != '\n':
+ new_token, consumer, line = consumer(line)
+ if new_token != None:
+ current_stanza.append(new_token)
class Operations:
def __init__(self, runner_args):
- self.standalone = apply(Standalone, runner_args)
- self.automate = apply(Automate, runner_args)
+ self.standalone = apply(Standalone, runner_args)
+ self.automate = apply(Automate, runner_args)
def tags(self):
- for line in (t.strip() for t in self.standalone.run('ls', ['tags'])):
- if not line:
- continue
- yield apply(Tag, line.split(' ', 2))
+ for line in (t.strip() for t in self.standalone.run('ls', ['tags'])):
+ if not line:
+ continue
+ yield apply(Tag, line.split(' ', 2))
def branches(self):
- for line in (t.strip() for t in self.standalone.run('ls', ['branches'])):
- if not line:
- continue
- yield apply(Branch, (line,))
+ for line in (t.strip() for t in self.standalone.run('ls', ['branches'])):
+ if not line:
+ continue
+ yield apply(Branch, (line,))
def graph(self):
- for line in self.automate.run('graph', []):
- yield line
+ for line in self.automate.run('graph', []):
+ yield line
def get_revision(self, revision):
- for stanza in basic_io_from_stream(self.automate.run('get_revision', [revision])):
- yield stanza
+ for stanza in basic_io_from_stream(self.automate.run('get_revision', [revision])):
+ yield stanza
def certs(self, revision):
+ for stanza in basic_io_from_stream(self.automate.run('certs', [revision])):
+ yield stanza
- for stanza in basic_io_from_stream(self.automate.run('certs', [revision])):
- yield stanza
============================================================
--- viewmtn.py fb9d3d9fa86e7ae6b4e9ee3be5ac53fa944c6147
+++ viewmtn.py 7728db1166843eaeee789a1c821dcc4f804c96c7
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2.4
import cgi
import mtn
@@ -35,117 +35,116 @@ class Link:
class Link:
def __init__(self, description=None):
- self.relative_uri = None
- self.description = description
+ self.relative_uri = None
+ self.description = description
def html(self):
- return '%s' % (self.relative_uri,
- self.description)
+ return '%s' % (self.relative_uri,
+ self.description)
class RevisionLink(Link):
def __init__(self, revision, **kwargs):
- Link.__init__(*(self, ), **kwargs)
- self.relative_uri = 'revision/info/%s' % (revision)
- self.description = revision.abbrev()
+ Link.__init__(*(self, ), **kwargs)
+ self.relative_uri = 'revision/info/%s' % (revision)
+ self.description = revision.abbrev()
class TagLink(Link):
def __init__(self, tag, **kwargs):
- Link.__init__(*(self, ), **kwargs)
- self.relative_uri = 'revision/info/%s' % (tag.revision)
- self.description = tag.name
+ Link.__init__(*(self, ), **kwargs)
+ self.relative_uri = 'revision/info/%s' % (tag.revision)
+ self.description = tag.name
class BranchLink(Link):
def __init__(self, branch, **kwargs):
- Link.__init__(*(self, ), **kwargs)
- self.relative_uri = 'branch/changes/' + urllib.quote(branch.name)
- self.description = hq(branch.name)
+ Link.__init__(*(self, ), **kwargs)
+ self.relative_uri = 'branch/changes/' + urllib.quote(branch.name)
+ self.description = hq(branch.name)
class DiffLink(Link):
def __init__(self, diff, **kwargs):
- Link.__init__(*(self, ), **kwargs)
- self.relative_uri = 'revision/diff/' + diff.from_rev + '/with/' + diff.to_rev
- if diff.fname:
- self.relative_uri += '/'+urllib.quote(diff.fname)
- self.description = "diff"
+ Link.__init__(*(self, ), **kwargs)
+ self.relative_uri = 'revision/diff/' + diff.from_rev + '/with/' + diff.to_rev
+ if diff.fname:
+ self.relative_uri += '/'+urllib.quote(diff.fname)
+ self.description = "diff"
class FileLink(Link):
def __init__(self, file, **kwargs):
- Link.__init__(*(self, ), **kwargs)
- self.relative_uri = 'revision/file/' + file.in_revision + '/' + urllib.quote("goat")
+ Link.__init__(*(self, ), **kwargs)
+ self.relative_uri = 'revision/file/' + file.in_revision + '/' + urllib.quote("goat")
class Diff:
def __init__(self, from_rev, to_rev, fname=None):
- self.obj_type = 'diff'
- self.fname = fname
- self.from_rev = from_rev
- self.to_rev = to_rev
+ self.obj_type = 'diff'
+ self.fname = fname
+ self.from_rev = from_rev
+ self.to_rev = to_rev
def prettify(s):
return ' '.join(
- map(lambda x: hq(x[0].upper() + x[1:]),
- s.replace("_", " ").split(" ")))
+ map(lambda x: hq(x[0].upper() + x[1:]),
+ s.replace("_", " ").split(" ")))
def certs_for_template(cert_gen):
for cert in cert_gen:
- if cert[0] == 'key' and len(cert) != 10:
- raise Exception("Not a correcly formatted certificate: %s" % cert)
- if cert[3] != 'ok':
- raise Exception("Certificate failed check.")
+ if cert[0] == 'key' and len(cert) != 10:
+ raise Exception("Not a correcly formatted certificate: %s" % cert)
+ if cert[3] != 'ok':
+ raise Exception("Certificate failed check.")
- key = cert[1]
- name = cert[5]
- value = cert[7]
- if name == "branch":
- value = link(mtn.Branch(value)).html()
- else:
- value = '
'.join(map(hq, value.split('\n')))
+ key = cert[1]
+ name = cert[5]
+ value = cert[7]
+ if name == "branch":
+ value = link(mtn.Branch(value)).html()
+ else:
+ value = '
'.join(map(hq, value.split('\n')))
- yield { 'key' : key,
- 'name' : prettify(name),
- 'value' : value }
+ yield { 'key' : key,
+ 'name' : prettify(name),
+ 'value' : value }
def revisions_for_template(revision, rev_gen):
old_revisions = []
stanzas = []
grouping = None
for stanza in rev_gen:
- stanza_type = stanza[0]
- description, value = prettify(stanza_type), None
+ stanza_type = stanza[0]
+ description, value = prettify(stanza_type), None
- if grouping == None:
- grouping = description
- if description != grouping:
- if len(stanzas) > 0:
- yield grouping, stanzas
- grouping, stanzas = description, []
+ if grouping == None:
+ grouping = description
+ if description != grouping:
+ if len(stanzas) > 0:
+ yield grouping, stanzas
+ grouping, stanzas = description, []
- if stanza_type == "format_version" or \
- stanza_type == "new_manifest":
- continue
- elif stanza_type == "patch":
+ if stanza_type == "format_version" or \
+ stanza_type == "new_manifest":
+ continue
+ elif stanza_type == "patch":
fname, from_id, to_id = stanza[1], stanza[3], stanza[5]
- debug(stanza)
- # if from_id is null, this is a new file
- # since we're showing that information under "Add", so
- # skip it here
- if not from_id:
- continue
- diff_links = ','.join([link(Diff(old_revision, revision, fname)).html() for old_revision in old_revisions])
- value = "Patch file %s (%s)" % (hq(fname), diff_links)
- elif stanza_type == "old_revision":
- old_revision = mtn.Revision(stanza[1])
- old_revisions.append(old_revision)
- value = "Old revision is: %s (%s)" % (old_revision.abbrev(), link(Diff(old_revision, revision)).html())
- elif stanza_type == "add_file":
- fname = stanza
- value = "Add file: %s" % (link(mtn.File(fname, revision)))
- else:
- value = "(this stanza type is not explicitly rendered; please report this.)\n%s" % hq(str(stanza))
+ # if from_id is null, this is a new file
+ # since we're showing that information under "Add", so
+ # skip it here
+ if not from_id:
+ continue
+ diff_links = ','.join([link(Diff(old_revision, revision, fname)).html() for old_revision in old_revisions])
+ value = "Patch file %s (%s)" % (hq(fname), diff_links)
+ elif stanza_type == "old_revision":
+ old_revision = mtn.Revision(stanza[1])
+ old_revisions.append(old_revision)
+ value = "Old revision is: %s (%s)" % (old_revision.abbrev(), link(Diff(old_revision, revision)).html())
+ elif stanza_type == "add_file":
+ fname = stanza
+ value = "Add file: %s" % (link(mtn.File(fname, revision)))
+ else:
+ value = "(this stanza type is not explicitly rendered; please report this.)\n%s" % hq(str(stanza))
- if description != None:
- stanzas.append(value)
+ if description != None:
+ stanzas.append(value)
if len(stanzas) > 0:
- yield grouping, stanzas
+ yield grouping, stanzas
type_to_link_class = {
'tag' : TagLink,
@@ -157,104 +156,105 @@ def link(obj):
def link(obj):
link_class = type_to_link_class.get(obj.obj_type)
if not link_class:
- raise LinkException("Unable to link to objects of type: '%s'" % (obj.obj_type))
+ raise LinkException("Unable to link to objects of type: '%s'" % (obj.obj_type))
return link_class(obj)
class Renderer:
def __init__(self):
- # any templates that can be inherited from, should be added to the list here
- self.templates = [ ('base.html', 'base'),
- ('revision.html', 'revision'), ]
- self._templates_loaded = False
+ # any templates that can be inherited from, should be added to the list here
+ self.templates = [ ('base.html', 'base'),
+ ('revision.html', 'revision'), ]
+ self._templates_loaded = False
- # these variables will be available to any template
- self.terms = {
- 'context' : web.context, # fugly
- 'dynamic_uri_path' : config.dynamic_uri_path,
- 'dynamic_join' : lambda path: urlparse.urljoin(config.dynamic_uri_path, path),
- 'link' : link,
- 'static_uri_path' : config.static_uri_path,
- 'static_join' : lambda path: urlparse.urljoin(config.static_uri_path, path),
- }
+ # these variables will be available to any template
+ self.terms = {
+ 'context' : web.context, # fugly
+ 'dynamic_uri_path' : config.dynamic_uri_path,
+ 'dynamic_join' : lambda path: urlparse.urljoin(config.dynamic_uri_path, path),
+ 'link' : link,
+ 'static_uri_path' : config.static_uri_path,
+ 'static_join' : lambda path: urlparse.urljoin(config.static_uri_path, path),
+ }
def load_templates(self):
- if self._templates_loaded: return
- for template, mod_name in self.templates:
- web.render(template, None, True, mod_name)
- self._templates_loaded = True
+ if self._templates_loaded: return
+ for template, mod_name in self.templates:
+ web.render(template, None, True, mod_name)
+ self._templates_loaded = True
def render(self, template, **kwargs):
- self.load_templates()
- terms = self.terms.copy()
- terms.update(kwargs)
- web.render(template, terms)
+ self.load_templates()
+ terms = self.terms.copy()
+ terms.update(kwargs)
+ web.render(template, terms)
renderer = Renderer()
ops = mtn.Operations([config.monotone, config.dbfile])
class Index:
def GET(self):
- renderer.render('index.html', page_title="Branches", branches=ops.branches())
+ renderer.render('index.html', page_title="Branches", branches=ops.branches())
class About:
def GET(self):
- renderer.render('about.html', page_title="About")
+ renderer.render('about.html', page_title="About")
class Tags:
def GET(self):
- renderer.render('tags.html', page_title="Tags", tags=ops.tags())
+ renderer.render('tags.html', page_title="Tags", tags=ops.tags())
class Help:
def GET(self):
- renderer.render('help.html', page_title="Help")
+ renderer.render('help.html', page_title="Help")
class RevisionInfo:
def GET(self, revision):
- revision = mtn.Revision(revision)
- certs = ops.certs(revision)
- revisions = ops.get_revision(revision)
- renderer.render('revisioninfo.html',
- page_title="Revision %s" % revision.abbrev(),
- revision=revision,
- certs=certs_for_template(certs),
- revisions=revisions_for_template(revision, revisions))
+ revision = mtn.Revision(revision)
+ certs = ops.certs(revision)
+ revisions = ops.get_revision(revision)
+ renderer.render('revisioninfo.html',
+ page_title="Revision %s" % revision.abbrev(),
+ revision=revision,
+ certs=certs_for_template(certs),
+ revisions=revisions_for_template(revision, revisions))
class RevisionDiff:
def GET(self, revision_from, revision_to):
- revision_from = mtn.Revision(revision_from)
- revision_to = mtn.Revision(revision_to)
- renderer.render('revisiondiff.html',
- page_title="Diff from %s to %s" % (revision_from.abbrev(), revision_to.abbrev()),
- revision_from=revision_from,
- revision_to=revision_to)
+ revision_from = mtn.Revision(revision_from)
+ revision_to = mtn.Revision(revision_to)
+ renderer.render('revisiondiff.html',
+ page_title="Diff from %s to %s" % (revision_from.abbrev(), revision_to.abbrev()),
+ revision=revision_from,
+ revision_from=revision_from,
+ revision_to=revision_to)
class RevisionFile:
def GET(self, revision, file):
- revision = mtn.Revision(revision)
- print "file %s from revision %s" % (file, revision)
+ revision = mtn.Revision(revision)
+ print "file %s from revision %s" % (file, revision)
class RevisionBrowse:
def GET(self, revision, path):
- revision = mtn.Revision(revision)
- renderer.render('revisionpath.html',
- page_title=revision,
- path=path)
+ revision = mtn.Revision(revision)
+ renderer.render('revisionpath.html',
+ page_title=revision,
+ path=path)
class RevisionTar:
def GET(self, revision):
- revision = mtn.Revision(revision)
- print "not implemented"
+ revision = mtn.Revision(revision)
+ print "not implemented"
class Json:
def GET(self, method, data):
- print "Bah."
+ print "Bah."
branch_re = r''
urls = (
- '/', 'Index',
- '/about', 'About',
- '/tags', 'Tags',
- '/help', 'Help',
+ '/', 'Index', #done
+ '/about', 'About', #done
+ '/tags', 'Tags', #done
+ '/help', 'Help', #done
'/json/(A-Za-z)/(.*)', 'Json',
'/revision/browse/('+mtn.revision_re+')/(.*)', 'RevisionBrowse',