#
#
# patch ".htaccess"
# from [32f18fb3ae3287627ec6cba1a5ab8513ec58b06a]
# to [21143b11977f7a6c554e97c6270ffd6a9207febb]
#
# patch "index.psp"
# from [4d51e2425e0b157425e6360e97268c15712f43b3]
# to [f43a8e5926d4b7828765299cf23beba6bca256a7]
#
# patch "monotone.py"
# from [7f1c3f7f328134e117328056199a1a092d0f9583]
# to [2dff75c63bf007f86d0b3806c5a085890d27757f]
#
# patch "revision.psp"
# from [c8fd63ea4c16d9b8cd446ff765f773f20c7adf74]
# to [65c3b846ff13c46662f9ed4f1aafb3017181e354]
#
============================================================
--- .htaccess 32f18fb3ae3287627ec6cba1a5ab8513ec58b06a
+++ .htaccess 21143b11977f7a6c554e97c6270ffd6a9207febb
@@ -1,5 +1,6 @@
AddHandler mod_python .psp
#PythonHandler mod_python.psp
PythonHandler wrapper
+PythonInterpreter viewmtn
AddHandler mod_python .py
DirectoryIndex index.psp
============================================================
--- index.psp 4d51e2425e0b157425e6360e97268c15712f43b3
+++ index.psp f43a8e5926d4b7828765299cf23beba6bca256a7
@@ -44,6 +44,7 @@
Branch |
<%
+ branches.sort()
for branch in branches:
req.write('%s |
' % (urllib.quote(branch), hq(branch)))
@@ -69,6 +70,7 @@
Tag | Signed by |
<%
+ tags.sort(lambda x,y: cmp(x[0], y[0]))
for tag in tags:
req.write('%s | %s |
' % (urllib.quote(tag[1]), hq(tag[0]), hq(tag[2])))
============================================================
--- monotone.py 7f1c3f7f328134e117328056199a1a092d0f9583
+++ monotone.py 2dff75c63bf007f86d0b3806c5a085890d27757f
@@ -9,15 +9,19 @@
# should really use the "automate" interface as much as possible
#
+id_re = re.compile(r'^[0-9a-f]+$')
+
dash_re = re.compile(r'^-+$')
cert_value_re = re.compile(r'^(\S*) *: (.*)$')
-new_manifest_re = re.compile("^new_manifest \[(\S+)\]$")
-old_revision_re = re.compile("^old_revision \[(\S+)\]$")
-old_manifest_re = re.compile("^old_manifest \[(\S+)\]$")
+new_manifest_re = re.compile(r'^new_manifest \[(\S+)\]$')
+old_revision_re = re.compile(r'^old_revision \[(\S+)\]$')
+old_manifest_re = re.compile(r'^old_manifest \[(\S+)\]$')
-manifest_entry_re = re.compile("^(\S+) *(.*)$")
+manifest_entry_re = re.compile(r'^(\S+) *(.*)$')
+log_entry_re = re.compile(r'^(\S+): (.*)$')
+
class Monotone:
def __init__(self, mt, dbfile):
self.mt = mt
@@ -47,8 +51,11 @@
c_key = c_value = None
for line in utility.iter_command(self.base_command + " ls certs %s" % (pipes.quote(id))):
if dash_re.match(line):
- if c_key != None: c_cert[c_key] = c_value
- if c_cert: rv.append(c_cert)
+ if c_cert:
+ if c_key != None:
+ c_cert[c_key] = c_value
+ c_key = c_value = None
+ rv.append(c_cert)
c_cert = {}
elif c_cert != None:
m = cert_value_re.match(line)
@@ -60,6 +67,11 @@
c_key, c_value = key, [value]
else:
c_value.append(value)
+ if c_cert:
+ if c_key != None:
+ c_cert[c_key] = c_value
+ c_key = c_value = None
+ rv.append(c_cert)
return rv
def revision(self, id):
rv = {}
@@ -82,4 +94,24 @@
raise Exception("Unable to retrieve file: %s" % (result['childerr']))
else:
return result['fromchild']
+ def ancestry(self, id, limit=0):
+ rv = []
+ entry = None
+ for line in utility.iter_command(self.base_command + " log %s" % (pipes.quote(id))):
+ if dash_re.match(line):
+ print "dash"
+ entry = {}
+ elif entry != None:
+ if not line:
+ rv.append(entry)
+ entry = None
+ if limit > 0 and len(rv) >= limit: break
+ else:
+ m = log_entry_re.match(line)
+ if m: entry[m.groups()[0]] = m.groups()[1]
+ if entry: rv.append(entry)
+ return rv
+def is_valid_id(s):
+ return len(s) == 40 and id_re.match(s) != None
+
============================================================
--- revision.psp c8fd63ea4c16d9b8cd446ff765f773f20c7adf74
+++ revision.psp 65c3b846ff13c46662f9ed4f1aafb3017181e354
@@ -22,6 +22,8 @@
if not form.has_key('id'):
raise Exception("No revision ID specified.")
id = form['id']
+if not monotone.is_valid_id(id):
+ raise Exception("Specified revision ID is not valid.")
mt = Monotone(config.monotone, config.dbfile)