Mercurial > public > mercurial-scm > hg
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 ' % 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> ' % \ | |
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 ' %d:<a href="?cmd=chkin;nd=%s">%s</a>' % \ | |
142 (i2, h2, h2, ), | |
93 else: | 143 else: |
94 print line | 144 print ' %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 ' ' |
113 if i2 != -1: | 163 print '\t</td></tr>' |
114 print ' %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 ' %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 ' ' | 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() |