# # # patch "common.py" # from [e2aff7e9041faa757e75fb6e705d525d24332e4c] # to [1bbdf3b52720be34cf84c878bc04cd35ac0a6b28] # # patch "mtn.py" # from [ff9253965f0803b9121a160d9b6ec0b9630c03ee] # to [8c6acc980241b776980561ea90b7b4d87f01db76] # # patch "templates/tags.html" # from [51d40e8786b2cdfb99d956a28583be36c49cc078] # to [613f14c73a648a769f178af4ebeecd51b237a746] # # patch "viewmtn.py" # from [276ac9117571c5c478d6e64b66b85fc6f3e0f414] # to [f1159d02c5375dbe85c16b9b1ae9e99eac615dc7] # ============================================================ --- common.py e2aff7e9041faa757e75fb6e705d525d24332e4c +++ common.py 1bbdf3b52720be34cf84c878bc04cd35ac0a6b28 @@ -1,22 +1,10 @@ import datetime import datetime -import urllib -import pydoc import time import fcntl import os from web import debug -escape_function = pydoc.HTMLRepr().escape - -def type_wrapper(e, x): - if x == None: - return "" - elif type(x) == type([]): - return '
'.join(map(e, x)) - else: - return e(x) - def parse_timecert(value): return apply(datetime.datetime, time.strptime(value, "%Y-%m-%dT%H:%M:%S")[:6]) @@ -37,38 +25,6 @@ def terminate_popen3(process): except: debug("%s failed_to_stop %s" % (os.getpid(), process.pid)) -def get_branch_links(mt, branches): - if len(branches) > 1: - branch_links = "branches " - else: - branch_links = "branch " - links = [] - for branch in branches: - links.append(link(mt, "branch", branch)) - return branch_links + ', '.join(links) - -def extract_cert_from_certs(certs, certname, as_list=False): - rv = [] - for cert in certs: - name, value = None, None - for k, v in cert: - if k == "name": name = v - elif k == "value": value = v - if name == None or value == None: continue - if name == certname: - if not as_list: - return value - else: - rv.append(value) - return rv - -def determine_date(certs): - dateval = extract_cert_from_certs(certs, "date") - if dateval == None: - return None - else: - return parse_timecert(dateval) - def quicklog(value): hq = html_escape() rv = hq(value.strip().split('\n')[0]) @@ -76,7 +32,7 @@ def quicklog(value): rv = rv[1:].strip() return rv -def ago_string(event, now): +def ago(event): def plural(v, singular, plural): if v == 1: return "%d %s" % (v, singular) @@ -99,89 +55,6 @@ def ago_string(event, now): plural(seconds, "second", "seconds")) return rv -def link(mt, link_type, link_to, description = None, no_quote = False): - hq = html_escape() - if not no_quote and description != None: description = hq(description) - if link_type == "revision": - rv = '' % (urllib.quote(link_to)) - if description != None: rv += description - else: rv += hq(link_to[:8]) + ".." - rv += '' - if description == None: rv = '[' + rv + ']' - elif link_type == "diff" or link_type == "download_diff": - link_to = map(urllib.quote, filter(lambda x: x != None, link_to)) - if link_type == "diff": - handler = "diff.psp" - else: - handler = "getdiff.py" - uri = '%s?id1=%s&id2=%s' % (handler, link_to[0], link_to[1]) - if len(link_to) == 3: - uri += '&fname=%s' % (link_to[2]) - rv = '' - if description != None: rv += description - else: rv += "diff" - rv += '' - elif link_type == "download": - if type(link_to) == type([]): - rv = '' % (urllib.quote(link_to[0]), - urllib.quote(link_to[1])) - link_id = link_to[0] - else: - rv = '' % (urllib.quote(link_to)) - link_id = link_to - if description != None: rv += description + "" - else: rv = "[" + rv + hq(link_id[:8]) + ".." + "]" - elif link_type == "file": - revision_id, path = link_to - rv = '' % (urllib.quote(revision_id), - urllib.quote(path)) - if description != None: rv += description + "" - else: rv = "[" + rv + hq(path + '@' + revision_id[:8]) + ".." + "]" - elif link_type == "fileinbranch": - branch, path = link_to - rv = '' % (urllib.quote(branch), - urllib.quote(path)) - if description != None: rv += description + "" - else: rv = "[" + rv + hq(path + '@' + branch) + "]" - elif link_type == "branch": - rv = '' % (urllib.quote(link_to)) - if description != None: rv += description - else: rv += hq(link_to) - rv += '' - elif link_type == "tar": - rv = '' % (urllib.quote(link_to)) - if description != None: rv += description - else: rv = "tar of [" + rv + hq(link_to[:8]) + "..]" + "]" - rv += '' - elif link_type == "headofbranch": - rv = '' % (urllib.quote(link_to)) - if description != None: rv += description - else: rv += "head of " + hq(link_to) - rv += '' - elif link_type == "manifest": - if type(link_to) == type([]): - link_to, path = link_to - rv = '' % (urllib.quote(link_to), urllib.quote(path)) - else: - rv = '' % (urllib.quote(link_to)) - if description != None: rv += description - else: rv += hq(link_to[:8]) + ".." - rv += '' - if description == None: rv = '[' + rv + ']' - else: - rv = 'Unknown link type: %s' % (hq(link_type)) - return '%s' % (hq(link_type+'Link'), rv) - -def html_escape(): - "returns a function stolen from pydoc that can be used to escape HTML" - return lambda x: type_wrapper(escape_function, x) - -from enscriptlangs import enscript_langs -from utility import run_command -import mimetypes -import config -import pipes - # is it binary? def is_binary(str): nontext_chars = "\x01\x02\x03\x04\x05\x06\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1c\x1d\x1e\x1f" @@ -191,69 +64,3 @@ def is_binary(str): for i in str: if check.has_key(i): return True return False - -# hm, later on might make this be some javascript that does an call back to the server. -# then could have a pull down to let people choose which enscript encoding to use, and -# just update the DOM with the new data. -def colourise_code(req, hq, path, contents, filter=None): - mime_type = mimetypes.guess_type(path)[0] - if mime_type == None: mime_type = 'text/plain' - if mime_type == 'image/png' or mime_type == 'image/jpeg' or mime_type == 'image/gif': - display_as_image = True - else: display_as_image = False - - # okay; can we guess a valid enscript filter to run this through? - tsp = mime_type.split('/', 1) - if filter == None and tsp[0] == 'text': - candidate = tsp[1] - if candidate.startswith('x-'): candidate = candidate[2:] - if candidate.endswith('src'): candidate = candidate[:-3] - if candidate.endswith('hdr'): candidate = candidate[:-3] - if candidate == 'c++': candidate = 'cpp' # ugly - if candidate in enscript_langs: filter = candidate - if filter == None: - # heh, will at least work for lua files - last_dot = path.rfind('.') - if last_dot == -1: last_dot = 0 - candidate = path[last_dot:] - if candidate in enscript_langs: filter = candidate - - # if no filter then let's check if it's binary or not; if not binary - # we'll just treat it as text; otherwise display a warning and a download - # link - if filter == None and not is_binary(contents): - filter = 'text' - - req.write('''
''') - if display_as_image: - req.write('''') - def stop_code(): - req.write('') - def text(): - start_code() - req.write(hq(contents)) - stop_code() - def enscript(): - command = config.enscript_path + ' -o - --color --language=html' - command += ' --highlight=%s' % (pipes.quote(filter)) - result = run_command(command, to_child=contents) - if result['exitcode'] != 0: - raise Exception('Error running enscript (%s) : "%s".' % (hq(command), hq(result['childerr']))) - in_contents = False - for line in result['fromchild'].split('\n'): - if line.startswith('
'):
-                    in_contents = True
-                    start_code()
-                elif line.startswith('
'): - in_contents = False - stop_code() - elif in_contents: - req.write(line + '\r\n') - if filter == "text": text() - else: enscript() - else: - req.write('''

This file seems to binary and not suitable for display in the browser. You must %s the file and use a suitable viewer.

''' % (link("download", [matching_file_id, path], "download"))) - req.write('''
''') ============================================================ --- mtn.py ff9253965f0803b9121a160d9b6ec0b9630c03ee +++ mtn.py 8c6acc980241b776980561ea90b7b4d87f01db76 @@ -58,6 +58,7 @@ class Automate(Runner): if not self.process: return terminate_popen3(self.process) + self.process = None def __process_required(self): if self.process != None: @@ -69,7 +70,7 @@ class Automate(Runner): self.process.childerr ]) def run(self, *args, **kwargs): - debug(("automate is running:", args, kwargs)) +# 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: @@ -79,12 +80,23 @@ class Automate(Runner): return rv def __run(self, command, args): - 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() + # number of tries to get a working mtn going.. + for i in xrange(2): + self.__process_required() + try: + self.process.tochild.write(enc) + self.process.tochild.flush() + break + except: + # mtn has died underneath the automate; restart it + debug("exception... stop") + import traceback + debug(traceback.format_exc()) + self.stop() + import sys def read_result_packets(): buffer = "" @@ -143,9 +155,8 @@ class Standalone(Runner): # 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)) +# debug(("standalone is running:", command, args)) to_run = self.base_command + [command] + args - debug(to_run) process = popen2.Popen3(to_run, capturestderr=True) for line in process.fromchild: yield line @@ -229,8 +240,8 @@ def basic_io_from_stream(gen): for idx, c in enumerate(line): if state.in_escape: - if c != '\\' or c != '\"': - raise MonotoneException("Invalid escape code: %s\n" % line) + if c != '\\' and c != '"': + raise MonotoneException("Invalid escape code: %s in %s\n" % (c, line)) state.value += c state.in_escape = False else: ============================================================ --- templates/tags.html 51d40e8786b2cdfb99d956a28583be36c49cc078 +++ templates/tags.html 613f14c73a648a769f178af4ebeecd51b237a746 @@ -8,7 +8,7 @@ To view a particular tag, select it from

- + #for tag in $tags #end for ============================================================ --- viewmtn.py 276ac9117571c5c478d6e64b66b85fc6f3e0f414 +++ viewmtn.py f1159d02c5375dbe85c16b9b1ae9e99eac615dc7 @@ -1,12 +1,14 @@ import config #!/usr/bin/env python2.4 import cgi import mtn import web import config +import common import urllib import urlparse import syntax +import datetime hq = cgi.escape import web @@ -206,7 +208,13 @@ class Tags: class Tags: def GET(self): - renderer.render('tags.html', page_title="Tags", tags=ops.tags()) + tags = map(None, ops.tags()) + def revision_ago(rev): + for cert in ops.certs(rev): + if cert[4] == 'name' and cert[5] == 'date': + revdate = common.parse_timecert(cert[7]) + return common.ago(revdate) + renderer.render('tags.html', page_title="Tags", tags=tags, revision_ago=revision_ago) class Help: def GET(self):
TagSigned byWhen
TagSigned byAge
@@ -20,7 +20,7 @@ To view a particular tag, select it from $tag.author - + $revision_ago($tag.revision)