comparison hgweb.py @ 100:526722d24ee5

reorganize code into classes clean up html code for w3c validation
author jake@edge2.net
date Fri, 13 May 2005 17:48:10 -0700
parents db5eb6a86179
children 6da5cf0c4193
comparison
equal deleted inserted replaced
99:db5eb6a86179 100:526722d24ee5
22 l = [] 22 l = []
23 for c in text: 23 for c in text:
24 l.append('&#%d;' % ord(c)) 24 l.append('&#%d;' % ord(c))
25 return ''.join(l) 25 return ''.join(l)
26 26
27 def httphdr(type = "text/html"): 27 def httphdr(type):
28 print 'Content-type: %s\n' % type 28 print 'Content-type: %s\n' % type
29 29
30 def htmldoctype(): 30 class page:
31 print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">' 31 def __init__(self, type="text/html", title="Mercurial Web",
32 32 charset="ISO-8859-1"):
33 def htmlhead(title): 33 print 'Content-type: %s; charset=%s\n' % (type, charset)
34 print '<HTML>' 34 print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'
35 print '<!-- created by hgweb 0.1 - jake@edge2.net -->' 35 print '<HTML>'
36 print '<HEAD><TITLE>%s</TITLE></HEAD>' % (title, ) 36 print '<!-- created by hgweb 0.1 - jake@edge2.net -->'
37 print '<style type="text/css">' 37 print '<HEAD><TITLE>%s</TITLE>' % title
38 print 'body { font-family: sans-serif; font-size: 12px; }' 38 print '<style type="text/css">'
39 print 'table { font-size: 12px; }' 39 print 'body { font-family: sans-serif; font-size: 12px; }'
40 print '.errmsg { font-size: 200%; color: red; }' 40 print 'table { font-size: 12px; }'
41 print '.filename { font-size: 150%; color: purple; }' 41 print '.errmsg { font-size: 200%; color: red; }'
42 print '.plusline { color: green; }' 42 print '.filename { font-size: 150%; color: purple; }'
43 print '.minusline { color: red; }' 43 print '.plusline { color: green; }'
44 print '.atline { color: purple; }' 44 print '.minusline { color: red; }'
45 print '</style>' 45 print '.atline { color: purple; }'
46 46 print '</style>'
47 def startpage(title): 47 print '</HEAD>'
48 httphdr() 48 print '<BODY>'
49 htmldoctype() 49
50 htmlhead(title) 50 def endpage(self):
51 print '<BODY>' 51 print '</BODY>'
52 52 print '</HTML>'
53 def endpage(): 53
54 print '</BODY>' 54 def show_diff(self, a, b, fn):
55 print '</HTML>' 55 a = a.splitlines(1)
56 56 b = b.splitlines(1)
57 57 l = difflib.unified_diff(a, b, fn, fn)
58 58 print '<pre>'
59 def ent_change(repo, nodeid, changes): 59 for line in l:
60 hn = hg.hex(nodeid) 60 line = cgi.escape(line[:-1])
61 i = repo.changelog.rev(nodeid) 61 if line.startswith('+'):
62 (h1, h2) = [ hg.hex(x) for x in repo.changelog.parents(nodeid) ] 62 print '<span class="plusline">%s</span>' % (line, )
63 datestr = time.asctime(time.gmtime(float(changes[2].split(' ')[0]))) 63 elif line.startswith('-'):
64 print '<table width="100%" border="1">' 64 print '<span class="minusline">%s</span>' % (line, )
65 print '\t<tr><td valign="top" width="10%%">author:</td>' + \ 65 elif line.startswith('@'):
66 '<td valign="top" width="20%%">%s</td>' % (obfuscate(changes[1]), ) 66 print '<span class="atline">%s</span>' % (line, )
67 print '\t\t<td valign="top" width="10%%">description:</td>' + \ 67 else:
68 '<td width="60%%">' + \ 68 print line
69 '<a href="?cmd=chkin;nd=%s">%s</a></td></tr>' % \ 69 print '</pre>'
70 (hn, nl2br(changes[4]), ) 70
71 print '\t<tr><td>date:</td><td>%s UTC</td>' % (datestr, ) 71 class errpage(page):
72 print '\t\t<td valign="top">files:</td><td valign="top">' 72 def __init__(self):
73 for f in changes[3]: 73 page.__init__(self, title="Mercurial Web Error Page")
74 print '\t\t%s&nbsp;&nbsp;' % f 74
75 print '\t</td></tr>' 75 class change_list(page):
76 print '\t<tr><td>revision:</td><td colspan="3">%d:<a ' % (i, ) + \ 76 def __init__(self, repo, reponame):
77 'href="?cmd=chkin;nd=%s">%s</a></td></tr>' % (hn, hn, ) 77 page.__init__(self)
78 print '</table><br />' 78 self.repo = repo
79 79 print '<h3>Changes For: %s</h3>' % reponame
80 def ent_diff(a, b, fn): 80
81 a = a.splitlines(1) 81 def content(self, start='tip', end='0', boundtype='rev'):
82 b = b.splitlines(1) 82 print '<table summary="" width="100%" align="center">'
83 l = difflib.unified_diff(a, b, fn, fn) 83 cl = []
84 print '<pre>' 84 for i in xrange(self.repo.changelog.count()):
85 for line in l: 85 n = self.repo.changelog.node(i)
86 line = cgi.escape(line[:-1]) 86 cl.append((n, self.repo.changelog.read(n)))
87 if line.startswith('+'): 87 cl.reverse()
88 print '<span class="plusline">%s</span>' % (line, ) 88 for n, ch in cl:
89 elif line.startswith('-'): 89 print '<tr><td>'
90 print '<span class="minusline">%s</span>' % (line, ) 90 self.change_table(n, ch)
91 elif line.startswith('@'): 91 print '</td></tr>'
92 print '<span class="atline">%s</span>' % (line, ) 92
93 print '</table>'
94
95 def change_table(self, nodeid, changes):
96 hn = hg.hex(nodeid)
97 i = self.repo.changelog.rev(nodeid)
98 (h1, h2) = [ hg.hex(x) for x in self.repo.changelog.parents(nodeid) ]
99 datestr = time.asctime(time.gmtime(float(changes[2].split(' ')[0])))
100 print '<table summary="" width="100%" border="1">'
101 print '\t<tr><td valign="top" width="10%">author:</td>' + \
102 '<td valign="top" width="20%%">%s</td>' % \
103 (obfuscate(changes[1]), )
104 print '\t\t<td valign="top" width="10%">description:</td>' + \
105 '<td width="60%">' + \
106 '<a href="?cmd=chkin;nd=%s">%s</a></td></tr>' % \
107 (hn, nl2br(cgi.escape(changes[4])), )
108 print '\t<tr><td>date:</td><td>%s UTC</td>' % (datestr, )
109 print '\t\t<td valign="top">files:</td><td valign="top">'
110 for f in changes[3]:
111 print '\t\t<a href="?cmd=file;cs=%s;fn=%s">%s</a>&nbsp;&nbsp;' % \
112 (hn, f, cgi.escape(f), )
113 print '\t</td></tr>'
114 print '\t<tr><td>revision:</td><td colspan="3">%d:<a ' % (i, ) + \
115 'href="?cmd=chkin;nd=%s">%s</a></td></tr>' % (hn, hn, )
116 print '</table><br />'
117
118 class checkin(page):
119 def __init__(self, repo, nodestr):
120 page.__init__(self)
121 self.repo = repo
122 self.node = hg.bin(nodestr)
123 self.nodestr = nodestr
124 print '<h3>Checkin: %s</h3>' % nodestr
125
126 def content(self):
127 changes = self.repo.changelog.read(self.node)
128 i = self.repo.changelog.rev(self.node)
129 parents = self.repo.changelog.parents(self.node)
130 (h1, h2) = [ hg.hex(x) for x in parents ]
131 (i1, i2) = [ self.repo.changelog.rev(x) for x in parents ]
132 datestr = time.asctime(time.gmtime(float(changes[2].split(' ')[0])))
133 mf = self.repo.manifest.read(changes[0])
134 print '<table summary="" width="100%" border="1">'
135 print '\t<tr><td>revision:</td><td colspan="3">%d:' % (i, ),
136 print '<a href="?cmd=chkin;nd=%s">%s</a></td></tr>' % \
137 (self.nodestr, self.nodestr, )
138 print '\t<tr><td>parent(s):</td><td colspan="3">%d:' % (i1, )
139 print '<a href="?cmd=chkin;nd=%s">%s</a>' % (h1, h1, ),
140 if i2 != -1:
141 print '&nbsp;&nbsp;%d:<a href="?cmd=chkin;nd=%s">%s</a>' % \
142 (i2, h2, h2, ),
93 else: 143 else:
94 print line 144 print '&nbsp;&nbsp;%d:%s' % (i2, h2, ),
95 print '</pre>' 145 print '</td></tr>'
96 146 print '\t<tr><td>manifest:</td><td colspan="3">%d:' % \
97 def ent_checkin(repo, nodeid): 147 (self.repo.manifest.rev(changes[0]), ),
98 startpage("Mercurial Web") 148 print '<a href="?cmd=mf;nd=%s">%s</a></td></tr>' % \
99 149 (hg.hex(changes[0]), hg.hex(changes[0]), )
100 changes = repo.changelog.read(nodeid) 150 print '\t<tr><td valign="top" width="10%">author:</td>' + \
101 hn = hg.hex(nodeid) 151 '<td valign="top" width="20%%">%s</td>' % \
102 i = repo.changelog.rev(nodeid) 152 (obfuscate(changes[1]), )
103 parents = repo.changelog.parents(nodeid) 153 print '\t\t<td valign="top" width="10%">description:</td>' + \
104 (h1, h2) = [ hg.hex(x) for x in parents ] 154 '<td width="60%">' + \
105 (i1, i2) = [ repo.changelog.rev(x) for x in parents ] 155 '<a href="?cmd=chkin;nd=%s">%s</a></td></tr>' % \
106 datestr = time.asctime(time.gmtime(float(changes[2].split(' ')[0]))) 156 (self.nodestr, nl2br(cgi.escape(changes[4])), )
107 mf = repo.manifest.read(changes[0]) 157 print '\t<tr><td>date:</td><td>%s UTC</td>' % (datestr, )
108 print '<table width="100%" border="1">' 158 print '\t\t<td valign="top">files:</td><td valign="top">'
109 print '\t<tr><td>revision:</td><td colspan="3">%d:' % (i, ), 159 for f in changes[3]:
110 print '<a href="?cmd=chkin;nd=%s">%s</a></td></tr>' % (hn, hn, ) 160 print '\t\t<a href="?cmd=file;nd=%s&fn=%s">%s</a>' % \
111 print '\t<tr><td>parent(s):</td><td colspan="3">%d:' % (i1, ) 161 (hg.hex(mf[f]), f, cgi.escape(f), ),
112 print '<a href="?cmd=chkin;nd=%s">%s</a>' % (h1, h1, ), 162 print '&nbsp;&nbsp;'
113 if i2 != -1: 163 print '\t</td></tr>'
114 print '&nbsp;&nbsp;%d:<a href="?cmd=chkin;nd=%s">%s</a>' % \ 164 print '</table><br />'
115 (i2, h2, h2, ), 165
116 else: 166 (c, a, d) = self.repo.diffrevs(parents[0], self.node)
117 print '&nbsp;&nbsp;%d:%s' % (i2, h2, ), 167 change = self.repo.changelog.read(parents[0])
118 print '</td></tr>' 168 mf2 = self.repo.manifest.read(change[0])
119 print '\t<tr><td>manifest:</td><td colspan="3">%d:' % \ 169 for f in c:
120 (repo.manifest.rev(changes[0]), ), 170 self.show_diff(self.repo.file(f).read(mf2[f]), \
121 print '<a href="?cmd=mf;nd=%s">%s</a></td></tr>' % \ 171 self.repo.file(f).read(mf[f]), f)
122 (hg.hex(changes[0]), hg.hex(changes[0]), ) 172 for f in a:
123 print '\t<tr><td valign="top" width="10%%">author:</td>' + \ 173 self.show_diff('', self.repo.file(f).read(mf[f]), f)
124 '<td valign="top" width="20%%">%s</td>' % (obfuscate(changes[1]), ) 174 for f in d:
125 print '\t\t<td valign="top" width="10%%">description:</td>' + \ 175 self.show_diff(self.repo.file(f).read(mf2[f]), '', f)
126 '<td width="60%%">' + \ 176
127 '<a href="?cmd=chkin;nd=%s">%s</a></td></tr>' % \ 177 class filepage(page):
128 (hn, nl2br(changes[4]), ) 178 def __init__(self, repo, fn, node=None, cs=None):
129 print '\t<tr><td>date:</td><td>%s UTC</td>' % (datestr, ) 179 page.__init__(self)
130 print '\t\t<td valign="top">files:</td><td valign="top">' 180 self.repo = repo
131 for f in changes[3]: 181 self.fn = fn
132 print '\t\t<a href="?cmd=file;nd=%s&fn=%s">%s</a>' % \ 182 if cs:
133 (hg.hex(mf[f]), f, f, ), 183 chng = self.repo.changelog.read(hg.bin(cs))
134 print '&nbsp;&nbsp;' 184 mf = self.repo.manifest.read(chng[0])
135 print '\t</td></tr>' 185 self.node = mf[self.fn]
136 print '</table><br />' 186 self.nodestr = hg.hex(self.node)
137 187 else:
138 (c, a, d) = repo.diffrevs(parents[0], nodeid) 188 self.nodestr = node
139 change = repo.changelog.read(parents[0]) 189 self.node = hg.bin(node)
140 mf2 = repo.manifest.read(change[0]) 190 print '<div class="filename">%s (%s)</div>' % \
141 for f in c: 191 (cgi.escape(self.fn), self.nodestr, )
142 ent_diff(repo.file(f).read(mf2[f]), repo.file(f).read(mf[f]), f) 192 print '<a href="?cmd=hist;fn=%s">history</a><br />' % self.fn
143 for f in a: 193
144 ent_diff('', repo.file(f).read(mf[f]), f) 194 def content(self):
145 for f in d: 195 print '<pre>'
146 ent_diff(repo.file(f).read(mf2[f]), '', f) 196 print cgi.escape(self.repo.file(self.fn).read(self.node))
147 197 print '</pre>'
148 endpage()
149
150
151 def ent_file(repo, nodeid, fn):
152 print '<div class="filename">%s (%s)</div>' % (fn, hg.hex(nodeid), )
153 print '<pre>'
154 print cgi.escape(repo.file(fn).read(nodeid))
155 print '</pre>'
156
157 def change_page():
158 startpage("Mercurial Web")
159 print '<table width="100%" align="center">'
160 cl = []
161 for i in xrange(repo.changelog.count()):
162 n = repo.changelog.node(i)
163 cl.append((n, repo.changelog.read(n)))
164 cl.reverse()
165 for n, ch in cl:
166 print '<tr><td>'
167 ent_change(repo, n, ch)
168 print '</td></th>'
169
170 print '</table>'
171 endpage()
172 198
173 args = cgi.parse() 199 args = cgi.parse()
174 200
175 ui = hg.ui() 201 ui = hg.ui()
176 repo = hg.repository(ui, repo_path) 202 repo = hg.repository(ui, repo_path)
177 203
178 if not args.has_key('cmd'): 204 if not args.has_key('cmd'):
179 change_page() 205 page = change_list(repo, 'Mercurial')
206 page.content()
207 page.endpage()
180 208
181 elif args['cmd'][0] == 'chkin': 209 elif args['cmd'][0] == 'chkin':
182 if not args.has_key('nd'): 210 if not args.has_key('nd'):
211 page = errpage()
183 print '<div class="errmsg">No Node!</div>' 212 print '<div class="errmsg">No Node!</div>'
184 else: 213 else:
185 ent_checkin(repo, hg.bin(args['nd'][0])) 214 page = checkin(repo, args['nd'][0])
215 page.content()
216 page.endpage()
186 217
187 elif args['cmd'][0] == 'file': 218 elif args['cmd'][0] == 'file':
188 startpage("Mercurial Web") 219 if not (args.has_key('nd') and args.has_key('fn')) and \
189 220 not (args.has_key('cs') and args.has_key('fn')):
190 if not args.has_key('nd'): 221 page = errpage()
191 print '<div class="errmsg">No Node!</div>' 222 print '<div class="errmsg">Invalid Args!</div>'
192 elif not args.has_key('fn'):
193 print '<div class="errmsg">No Filename!</div>'
194 else: 223 else:
195 ent_file(repo, hg.bin(args['nd'][0]), args['fn'][0]) 224 if args.has_key('nd'):
196 endpage() 225 page = filepage(repo, args['fn'][0], node=args['nd'][0])
226 else:
227 page = filepage(repo, args['fn'][0], cs=args['cs'][0])
228 page.content()
229 page.endpage()
197 230
198 elif args['cmd'][0] == 'branches': 231 elif args['cmd'][0] == 'branches':
199 httphdr("text/plain") 232 httphdr("text/plain")
200 nodes = [] 233 nodes = []
201 if args.has_key('nodes'): 234 if args.has_key('nodes'):
223 sys.stdout.write(z.compress(chunk)) 256 sys.stdout.write(z.compress(chunk))
224 257
225 sys.stdout.write(z.flush()) 258 sys.stdout.write(z.flush())
226 259
227 else: 260 else:
228 startpage("Mercurial Web Error") 261 page = errpage()
229 print '<div class="errmsg">unknown command: ', args['cmd'][0], '</div>' 262 print '<div class="errmsg">unknown command: %s</div>' % \
230 endpage() 263 cgi.escape(args['cmd'][0])
264 page.endpage()