#
#
# patch "TODO"
# from [e0ea26c666b37c5f98ccf80cb933d021ee55c593]
# to [8caff57c44359cf5d6371175966a89f2bab498ab]
#
# patch "branch.psp"
# from [b740d23aebd091993e5a367e7d183d5634cc718d]
# to [f7ee6449c43df5afb9843bfd019f6216af7b04b4]
#
# patch "common.py"
# from [1e086f49256b4f4372e6ce1cb9cc53cc5564c9d2]
# to [13c75961de7952e45b67d1597b2314ba086fd383]
#
# patch "html.py"
# from [6121f3a3831136e182b9e1b9df342231675839dc]
# to [641fbffa7a36325df0c203e1ccb4299678fb3e7e]
#
# patch "manifest.psp"
# from [9244015efc03153b4837b17ac05570426213e9ad]
# to [4a261914914a02b3bc5fdbf8b6ed6ff95e37fa8e]
#
# patch "monotone.py"
# from [74e4db84f1ae2ba706d821f957226e3048f86ca0]
# to [09a54ce28dfd9610ba5c53188ee17f27c4716ef7]
#
# patch "viewmtn.css"
# from [8d04b3fc352a860b0e3240dcb539c1193705398f]
# to [8f34d3d1b7b375830bfbf12ae362a575b2a79385]
#
============================================================
--- TODO e0ea26c666b37c5f98ccf80cb933d021ee55c593
+++ TODO 8caff57c44359cf5d6371175966a89f2bab498ab
@@ -7,6 +7,8 @@
* getfile.py is setting the wrong content-disposition header
+ * some sort of double escaping with " in changelogs
+
TODO:
* Use monotone automate graph to do the ancestry graphing, and show some
============================================================
--- branch.psp b740d23aebd091993e5a367e7d183d5634cc718d
+++ branch.psp f7ee6449c43df5afb9843bfd019f6216af7b04b4
@@ -130,7 +130,7 @@
style = "font-size: 130%%; border-bottom-style: solid; border-bottom-width: 1px; border-bottom-color: black;"
if idx != 0:
style += "border-top-style: solid; border-top-width: 1px; border-top-color: black;"
- req.write('
%s ago: %s (%s) |
\n' % (style, ago, quicklog, link("revision", id, "more info")))
+ req.write('%s ago: %s (%s, %s) |
\n' % (style, ago, quicklog, link("revision", id, "revision info"), link("manifest", id, "browse files")))
req.write(certinfo)
elif output == 'rss':
req.write('\n')
============================================================
--- common.py 1e086f49256b4f4372e6ce1cb9cc53cc5564c9d2
+++ common.py 13c75961de7952e45b67d1597b2314ba086fd383
@@ -12,6 +12,13 @@
else:
return e(x)
+#
+# FIXME
+#
+# make these links use the mt instance (stricly Automate only)
+# to add extra information when the user hovers on a link
+#
+
def link(mt, link_type, link_to, description = None):
hq = html_escape()
if link_type == "revision":
============================================================
--- html.py 6121f3a3831136e182b9e1b9df342231675839dc
+++ html.py 641fbffa7a36325df0c203e1ccb4299678fb3e7e
@@ -9,17 +9,40 @@
hq = common.html_escape()
-def get_icon(filename, mime_type=None):
- if mime_type == None:
- mime_type = mimetypes.guess_type(filename)[0]
- if not mime_type:
- mime_type = "text"
- icon = 'gnome-mime-' + mime_type.replace('/', '-') + '.png'
- if os.access(os.path.join(config.gnome_mimetype_icon_path, icon), os.R_OK):
- return icon
+def get_icon(filename, mime_type=None, is_directory=False):
+ if config.gnome_mimetype_icon_path == None:
+ return None
+ if is_directory:
+ filename = 'gnome-fs-directory.png'
+ else:
+ if mime_type == None:
+ mime_type = mimetypes.guess_type(filename)[0]
+ if not mime_type:
+ mime_type = "text"
+ if mime_type.endswith('hdr'):
+ mime_type = mime_type[:-3] + 'src'
+ # some specific fixups
+ filename = 'gnome-mime-' + mime_type.replace('/', '-') + '.png'
+ if os.access(os.path.join(config.gnome_mimetype_icon_path, filename), os.R_OK):
+ return '/'.join([config.gnome_mimetype_uri, filename])
else:
return None
+class TableWriter:
+ def __init__(self, req):
+ self.req = req
+ self.odd = False
+ def start(self):
+ self.req.write('')
+ def write(self, row, is_header=False):
+ if self.odd: c = 'odd'
+ else: c = 'even'
+ if is_header: self.odd = False
+ else: self.odd = not self.odd
+ self.req.write('' % (c) + row + '
\n')
+ def stop(self):
+ self.req.write('
')
+
class Template:
def header(self, info):
if not info.has_key("title"): info['title'] = "untitled"
============================================================
--- manifest.psp 9244015efc03153b4837b17ac05570426213e9ad
+++ manifest.psp 4a261914914a02b3bc5fdbf8b6ed6ff95e37fa8e
@@ -5,7 +5,8 @@
import monotone
import common
import urllib
-from html import get_icon
+import sets
+from html import get_icon, TableWriter
#
# manifest.psp
@@ -24,6 +25,13 @@
if not monotone.is_valid_id(id):
raise Exception("Specified revision ID is not valid.")
+if not form.has_key('path'):
+ path = ''
+else:
+ path = form['path']
+if path.startswith('/'): path = path[1:]
+if path.endswith('/'): path = path[-1:]
+
revision = mt.revision(id)
if not revision.has_key('new_manifest'):
raise Exception("There is no manifest in this revision ID.")
@@ -31,17 +39,14 @@
manifest = mt.manifest(manifest_id)
info = {
- 'title' : "Manifest of revision %s" % (hq(id)),
+ 'title' : "/%s in revision %s" % (hq(path), hq(id)),
}
req.write(template.header(info))
-
-manifest = mt.manifest(manifest_id)
-
%>
-For more information about this revision, see its page: <%= link("revision", id) %>.
-below to view it.
+This page shows files contained within a particular revision; for more information
+about that revision see its page: <%= link("revision", id) %>.
@@ -49,23 +54,49 @@
<%
-# display the manifest broken into some columns.
-n_columns = 3
-offset = 0
-req.write('')
-for i in range(n_columns):
- size = len(manifest) / n_columns;
- spillage = len(manifest) % n_columns;
- if spillage > 0 and i < spillage: size += 1
- req.write('\n')
- for id, filename in manifest[offset:offset+size]:
- icon = get_icon(filename)
- if icon != None: req.write('' % icon)
- req.write('%s \n' % (link("file", [id, filename], filename)))
- req.write(' | \n')
- offset += size
-req.write('
')
+# filter this list of files into two lists;
+# subdirectories of 'path'
+# files in 'path'
+# each will contain entries relative to 'path'
+#
+# NB: the following code will break (perhaps) if monotone ever supports
+# empty subdirectories.
+subdirs, files, last_dir = [], [], None
+# root dir is depth 0, subdir of that 1, ..
+if path == '':
+ sp = []
+else:
+ sp = path.split('/')
+depth = len(sp)
+
+for file_id, filename in manifest:
+ parts = filename.split('/')
+
+ if len(parts) < depth or parts[:depth] != sp[:depth]:
+ continue
+
+ if len(parts) > depth + 1 and parts[depth] != last_dir:
+ subdirs.append((parts[depth], '/'.join(parts[:depth+1])))
+ last_dir = parts[depth]
+ elif len(parts) == depth + 1:
+ files.append((parts[-1], file_id, filename))
+
+if depth != 0:
+ subdirs = [('..', '/'.join(sp[:-1]))] + subdirs
+# req.write("%s %s %s
" % (str(sp), str(parts), depth))
+
+tr = TableWriter(req)
+tr.start()
+tr.write(' | Name | Rev | Age | Author | Last log entry | ', is_header=True)
+icon_uri = get_icon('', is_directory=True)
+for name, subdir in subdirs:
+ tr.write(' | %s | | | | | ' % (icon_uri, urllib.quote(id), urllib.quote(subdir), hq(name)))
+for name, file_id, file in files:
+ icon_uri = get_icon(file)
+ tr.write(' | %s | | | | | ' % (icon_uri, link("file", [file_id, file], name)))
+tr.stop()
+
%>
============================================================
--- monotone.py 74e4db84f1ae2ba706d821f957226e3048f86ca0
+++ monotone.py 09a54ce28dfd9610ba5c53188ee17f27c4716ef7
@@ -122,7 +122,7 @@
for c in str[1:]:
if in_escape:
if c != '\\' and c != '\"':
- raise Exception("basic_io parse error; expected \" or \\")
+ raise Exception(r'basic_io parse error; expected \" or \\')
rv += c
in_escape = False
else:
============================================================
--- viewmtn.css 8d04b3fc352a860b0e3240dcb539c1193705398f
+++ viewmtn.css 8f34d3d1b7b375830bfbf12ae362a575b2a79385
@@ -37,6 +37,14 @@
border-color: black;
}
+TR.odd {
+ background-color: #eeeeee;
+}
+
+TR.even {
+ background-color: #ffffff;
+}
+
TABLE.pretty TH {
/* background-color: black;*/
color: blue;