comparison hgweb.py @ 61:1215bf60468f

Add server side of hg:// protocol to hgweb
author mpm@selenic.com
date Thu, 12 May 2005 01:22:37 -0800
parents 115106376f45
children db5eb6a86179 58039eddbdda
comparison
equal deleted inserted replaced
60:e32fdbd97839 61:1215bf60468f
8 8
9 # useful for debugging 9 # useful for debugging
10 import cgitb 10 import cgitb
11 cgitb.enable() 11 cgitb.enable()
12 12
13 import os, cgi, time, re, difflib 13 import os, cgi, time, re, difflib, sys, zlib
14 from mercurial import hg, mdiff 14 from mercurial import hg, mdiff
15 15
16 repo_path = "." # change as needed 16 repo_path = "." # change as needed
17 17
18 def nl2br(text): 18 def nl2br(text):
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(): 27 def httphdr(type = "text/html"):
28 print 'Content-type: text/html\n\n' 28 print 'Content-type: %s\n' % type
29 29
30 def htmldoctype(): 30 def htmldoctype():
31 print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">' 31 print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">'
32 32
33 def htmlhead(title): 33 def htmlhead(title):
42 print '.plusline { color: green; }' 42 print '.plusline { color: green; }'
43 print '.minusline { color: red; }' 43 print '.minusline { color: red; }'
44 print '.atline { color: purple; }' 44 print '.atline { color: purple; }'
45 print '</style>' 45 print '</style>'
46 46
47 def startpage(title):
48 httphdr()
49 htmldoctype()
50 htmlhead(title)
51 print '<BODY>'
52
53 def endpage():
54 print '</BODY>'
55 print '</HTML>'
56
57
58
47 def ent_change(repo, nodeid): 59 def ent_change(repo, nodeid):
48 changes = repo.changelog.read(nodeid) 60 changes = repo.changelog.read(nodeid)
49 hn = hg.hex(nodeid) 61 hn = hg.hex(nodeid)
50 i = repo.changelog.rev(nodeid) 62 i = repo.changelog.rev(nodeid)
51 (h1, h2) = [ hg.hex(x) for x in repo.changelog.parents(nodeid) ] 63 (h1, h2) = [ hg.hex(x) for x in repo.changelog.parents(nodeid) ]
52 datestr = time.asctime(time.gmtime(float(changes[2].split(' ')[0]))) 64 datestr = time.asctime(time.gmtime(float(changes[2].split(' ')[0])))
53 mf = repo.manifest.read(changes[0])
54 print '<table width="100%" border="1">' 65 print '<table width="100%" border="1">'
55 print '\t<tr><td valign="top" width="10%%">author:</td>' + \ 66 print '\t<tr><td valign="top" width="10%%">author:</td>' + \
56 '<td valign="top" width="20%%">%s</td>' % (obfuscate(changes[1]), ) 67 '<td valign="top" width="20%%">%s</td>' % (obfuscate(changes[1]), )
57 print '\t\t<td valign="top" width="10%%">description:</td>' + \ 68 print '\t\t<td valign="top" width="10%%">description:</td>' + \
58 '<td width="60%%">' + \ 69 '<td width="60%%">' + \
59 '<a href="?cmd=chkin;nd=%s">%s</a></td></tr>' % \ 70 '<a href="?cmd=chkin;nd=%s">%s</a></td></tr>' % \
60 (hn, nl2br(changes[4]), ) 71 (hn, nl2br(changes[4]), )
61 print '\t<tr><td>date:</td><td>%s UTC</td>' % (datestr, ) 72 print '\t<tr><td>date:</td><td>%s UTC</td>' % (datestr, )
62 print '\t\t<td valign="top">files:</td><td valign="top">' 73 print '\t\t<td valign="top">files:</td><td valign="top">'
63 for f in changes[3]: 74 for f in changes[3]:
64 print '\t\t<a href="?cmd=file;nd=%s;fn=%s">%s</a>' % \ 75 print '\t\t%s&nbsp;&nbsp;' % f
65 (hg.hex(mf[f]), f, f, ),
66 print '&nbsp;&nbsp;'
67 print '\t</td></tr>' 76 print '\t</td></tr>'
68 # print '\t<tr><td>revision:</td><td colspan="3">%d:<a ' % (i, ) + \ 77 # print '\t<tr><td>revision:</td><td colspan="3">%d:<a ' % (i, ) + \
69 # 'href="?cmd=rev;nd=%s">%s</a></td></tr>' % (hn, hn, ) 78 # 'href="?cmd=rev;nd=%s">%s</a></td></tr>' % (hn, hn, )
70 print '</table><br />' 79 print '</table><br />'
71 80
85 else: 94 else:
86 print line 95 print line
87 print '</pre>' 96 print '</pre>'
88 97
89 def ent_checkin(repo, nodeid): 98 def ent_checkin(repo, nodeid):
99 startpage("Mercurial Web")
100
90 changes = repo.changelog.read(nodeid) 101 changes = repo.changelog.read(nodeid)
91 hn = hg.hex(nodeid) 102 hn = hg.hex(nodeid)
92 i = repo.changelog.rev(nodeid) 103 i = repo.changelog.rev(nodeid)
93 parents = repo.changelog.parents(nodeid) 104 parents = repo.changelog.parents(nodeid)
94 (h1, h2) = [ hg.hex(x) for x in parents ] 105 (h1, h2) = [ hg.hex(x) for x in parents ]
133 for f in a: 144 for f in a:
134 ent_diff('', repo.file(f).read(mf[f]), f) 145 ent_diff('', repo.file(f).read(mf[f]), f)
135 for f in d: 146 for f in d:
136 ent_diff(repo.file(f).read(mf2[f]), '', f) 147 ent_diff(repo.file(f).read(mf2[f]), '', f)
137 148
149 endpage()
150
151
138 def ent_file(repo, nodeid, fn): 152 def ent_file(repo, nodeid, fn):
139 print '<div class="filename">%s (%s)</div>' % (fn, hg.hex(nodeid), ) 153 print '<div class="filename">%s (%s)</div>' % (fn, hg.hex(nodeid), )
140 print '<pre>' 154 print '<pre>'
141 print cgi.escape(repo.file(fn).read(nodeid)) 155 print cgi.escape(repo.file(fn).read(nodeid))
142 print '</pre>' 156 print '</pre>'
143 157
144 httphdr() 158 def change_page():
145 htmldoctype() 159 startpage("Mercurial Web")
146 htmlhead('Mercurial Web')
147
148 print '<BODY>'
149
150
151 args = cgi.parse()
152
153 ui = hg.ui()
154 repo = hg.repository(ui, repo_path)
155
156 if not args.has_key('cmd'):
157 print '<table width="100%" align="center">' 160 print '<table width="100%" align="center">'
158 for i in xrange(repo.changelog.count()-1, -1, -1): 161 for i in xrange(0, repo.changelog.count()):
159 n = repo.changelog.node(i) 162 n = repo.changelog.node(i)
160 print '<tr><td>' 163 print '<tr><td>'
161 ent_change(repo, n) 164 ent_change(repo, n)
162 print '</td></th>' 165 print '</td></th>'
163 166
164 print '</table>' 167 print '</table>'
168 endpage()
169
170 args = cgi.parse()
171
172 ui = hg.ui()
173 repo = hg.repository(ui, repo_path)
174
175 if not args.has_key('cmd'):
176 change_page()
177
165 elif args['cmd'][0] == 'chkin': 178 elif args['cmd'][0] == 'chkin':
166 if not args.has_key('nd'): 179 if not args.has_key('nd'):
167 print '<div class="errmsg">No Node!</div>' 180 print '<div class="errmsg">No Node!</div>'
168 else: 181 else:
169 ent_checkin(repo, hg.bin(args['nd'][0])) 182 ent_checkin(repo, hg.bin(args['nd'][0]))
183
170 elif args['cmd'][0] == 'file': 184 elif args['cmd'][0] == 'file':
185 startpage("Mercurial Web")
186
171 if not args.has_key('nd'): 187 if not args.has_key('nd'):
172 print '<div class="errmsg">No Node!</div>' 188 print '<div class="errmsg">No Node!</div>'
173 elif not args.has_key('fn'): 189 elif not args.has_key('fn'):
174 print '<div class="errmsg">No Filename!</div>' 190 print '<div class="errmsg">No Filename!</div>'
175 else: 191 else:
176 ent_file(repo, hg.bin(args['nd'][0]), args['fn'][0]) 192 ent_file(repo, hg.bin(args['nd'][0]), args['fn'][0])
193 endpage()
194
195 elif args['cmd'][0] == 'branches':
196 httphdr("text/plain")
197 nodes = []
198 if args.has_key('nodes'):
199 nodes = map(hg.bin, args['nodes'][0].split(" "))
200 for b in repo.branches(nodes):
201 print " ".join(map(hg.hex, b))
202
203 elif args['cmd'][0] == 'between':
204 httphdr("text/plain")
205 nodes = []
206 if args.has_key('pairs'):
207 pairs = [ map(hg.bin, p.split("-"))
208 for p in args['pairs'][0].split(" ") ]
209 for b in repo.between(pairs):
210 print " ".join(map(hg.hex, b))
211
212 elif args['cmd'][0] == 'changegroup':
213 httphdr("application/hg-changegroup")
214 nodes = []
215 if args.has_key('roots'):
216 nodes = map(hg.bin, args['roots'][0].split(" "))
217
218 z = zlib.compressobj()
219 for chunk in repo.changegroup(nodes):
220 sys.stdout.write(z.compress(chunk))
221
222 sys.stdout.write(z.flush())
177 223
178 else: 224 else:
225 startpage("Mercurial Web Error")
179 print '<div class="errmsg">unknown command: ', args['cmd'][0], '</div>' 226 print '<div class="errmsg">unknown command: ', args['cmd'][0], '</div>'
180 227 endpage()
181 print '</BODY>'
182 print '</HTML>'