Mercurial > public > mercurial-scm > hg
comparison mercurial/hgweb/webcommands.py @ 6393:894875eae49b
hgweb: refactor hgweb code
author | Dirkjan Ochtman <dirkjan@ochtman.nl> |
---|---|
date | Fri, 28 Mar 2008 19:40:44 +0100 |
parents | 2540521dc7c1 |
children | 644a56c7ae79 |
comparison
equal
deleted
inserted
replaced
6392:2540521dc7c1 | 6393:894875eae49b |
---|---|
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
4 # | 4 # |
5 # This software may be used and distributed according to the terms | 5 # This software may be used and distributed according to the terms |
6 # of the GNU General Public License, incorporated herein by reference. | 6 # of the GNU General Public License, incorporated herein by reference. |
7 | 7 |
8 import os, mimetypes | 8 import os, mimetypes, re |
9 import webutil | 9 import webutil |
10 from mercurial import revlog | 10 from mercurial import revlog, archival |
11 from mercurial.node import hex, nullid | |
11 from mercurial.util import binary | 12 from mercurial.util import binary |
12 from mercurial.repo import RepoError | 13 from mercurial.repo import RepoError |
13 from common import staticfile, ErrorResponse, HTTP_OK, HTTP_NOT_FOUND | 14 from common import paritygen, staticfile, get_contact, ErrorResponse |
15 from common import HTTP_OK, HTTP_NOT_FOUND | |
14 | 16 |
15 # __all__ is populated with the allowed commands. Be sure to add to it if | 17 # __all__ is populated with the allowed commands. Be sure to add to it if |
16 # you're adding a new command, or the new command won't work. | 18 # you're adding a new command, or the new command won't work. |
17 | 19 |
18 __all__ = [ | 20 __all__ = [ |
28 return changelog(web, req, tmpl) | 30 return changelog(web, req, tmpl) |
29 | 31 |
30 def rawfile(web, req, tmpl): | 32 def rawfile(web, req, tmpl): |
31 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | 33 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) |
32 if not path: | 34 if not path: |
33 content = web.manifest(tmpl, webutil.changectx(web.repo, req), path) | 35 content = manifest(web, req, tmpl) |
34 req.respond(HTTP_OK, web.ctype) | 36 req.respond(HTTP_OK, web.ctype) |
35 return content | 37 return content |
36 | 38 |
37 try: | 39 try: |
38 fctx = webutil.filectx(web.repo, req) | 40 fctx = webutil.filectx(web.repo, req) |
39 except revlog.LookupError, inst: | 41 except revlog.LookupError, inst: |
40 try: | 42 try: |
41 content = web.manifest(tmpl, webutil.changectx(web.repo, req), path) | 43 content = manifest(web, req, tmpl) |
42 req.respond(HTTP_OK, web.ctype) | 44 req.respond(HTTP_OK, web.ctype) |
43 return content | 45 return content |
44 except ErrorResponse: | 46 except ErrorResponse: |
45 raise inst | 47 raise inst |
46 | 48 |
51 mt = mt or 'application/octet-stream' | 53 mt = mt or 'application/octet-stream' |
52 | 54 |
53 req.respond(HTTP_OK, mt, path, len(text)) | 55 req.respond(HTTP_OK, mt, path, len(text)) |
54 return [text] | 56 return [text] |
55 | 57 |
58 def _filerevision(web, tmpl, fctx): | |
59 f = fctx.path() | |
60 text = fctx.data() | |
61 fl = fctx.filelog() | |
62 n = fctx.filenode() | |
63 parity = paritygen(web.stripecount) | |
64 | |
65 if binary(text): | |
66 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream' | |
67 text = '(binary:%s)' % mt | |
68 | |
69 def lines(): | |
70 for lineno, t in enumerate(text.splitlines(1)): | |
71 yield {"line": t, | |
72 "lineid": "l%d" % (lineno + 1), | |
73 "linenumber": "% 6d" % (lineno + 1), | |
74 "parity": parity.next()} | |
75 | |
76 return tmpl("filerevision", | |
77 file=f, | |
78 path=webutil.up(f), | |
79 text=lines(), | |
80 rev=fctx.rev(), | |
81 node=hex(fctx.node()), | |
82 author=fctx.user(), | |
83 date=fctx.date(), | |
84 desc=fctx.description(), | |
85 branch=webutil.nodebranchnodefault(fctx), | |
86 parent=webutil.siblings(fctx.parents()), | |
87 child=webutil.siblings(fctx.children()), | |
88 rename=webutil.renamelink(fl, n), | |
89 permissions=fctx.manifest().flags(f)) | |
90 | |
56 def file(web, req, tmpl): | 91 def file(web, req, tmpl): |
57 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | 92 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) |
58 if path: | 93 if path: |
59 try: | 94 try: |
60 return web.filerevision(tmpl, webutil.filectx(web.repo, req)) | 95 return _filerevision(web, tmpl, webutil.filectx(web.repo, req)) |
61 except revlog.LookupError, inst: | 96 except revlog.LookupError, inst: |
62 pass | 97 pass |
63 | 98 |
64 try: | 99 try: |
65 return web.manifest(tmpl, webutil.changectx(web.repo, req), path) | 100 return manifest(web, req, tmpl) |
66 except ErrorResponse: | 101 except ErrorResponse: |
67 raise inst | 102 raise inst |
103 | |
104 def _search(web, tmpl, query): | |
105 | |
106 def changelist(**map): | |
107 cl = web.repo.changelog | |
108 count = 0 | |
109 qw = query.lower().split() | |
110 | |
111 def revgen(): | |
112 for i in xrange(cl.count() - 1, 0, -100): | |
113 l = [] | |
114 for j in xrange(max(0, i - 100), i + 1): | |
115 ctx = web.repo.changectx(j) | |
116 l.append(ctx) | |
117 l.reverse() | |
118 for e in l: | |
119 yield e | |
120 | |
121 for ctx in revgen(): | |
122 miss = 0 | |
123 for q in qw: | |
124 if not (q in ctx.user().lower() or | |
125 q in ctx.description().lower() or | |
126 q in " ".join(ctx.files()).lower()): | |
127 miss = 1 | |
128 break | |
129 if miss: | |
130 continue | |
131 | |
132 count = 1 | |
133 n = ctx.node() | |
134 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) | |
135 | |
136 yield tmpl('searchentry', | |
137 parity=parity.next(), | |
138 author=ctx.user(), | |
139 parent=webutil.siblings(ctx.parents()), | |
140 child=webutil.siblings(ctx.children()), | |
141 changelogtag=showtags, | |
142 desc=ctx.description(), | |
143 date=ctx.date(), | |
144 files=web.listfilediffs(tmpl, ctx.files(), n), | |
145 rev=ctx.rev(), | |
146 node=hex(n), | |
147 tags=webutil.nodetagsdict(web.repo, n), | |
148 inbranch=webutil.nodeinbranch(web.repo, ctx), | |
149 branches=webutil.nodebranchdict(web.repo, ctx)) | |
150 | |
151 if count >= web.maxchanges: | |
152 break | |
153 | |
154 cl = web.repo.changelog | |
155 parity = paritygen(web.stripecount) | |
156 | |
157 return tmpl('search', | |
158 query=query, | |
159 node=hex(cl.tip()), | |
160 entries=changelist, | |
161 archives=web.archivelist("tip")) | |
68 | 162 |
69 def changelog(web, req, tmpl, shortlog = False): | 163 def changelog(web, req, tmpl, shortlog = False): |
70 if 'node' in req.form: | 164 if 'node' in req.form: |
71 ctx = webutil.changectx(web.repo, req) | 165 ctx = webutil.changectx(web.repo, req) |
72 else: | 166 else: |
75 else: | 169 else: |
76 hi = web.repo.changelog.count() - 1 | 170 hi = web.repo.changelog.count() - 1 |
77 try: | 171 try: |
78 ctx = web.repo.changectx(hi) | 172 ctx = web.repo.changectx(hi) |
79 except RepoError: | 173 except RepoError: |
80 return web.search(tmpl, hi) # XXX redirect to 404 page? | 174 return _search(web, tmpl, hi) # XXX redirect to 404 page? |
81 | 175 |
82 return web.changelog(tmpl, ctx, shortlog = shortlog) | 176 def changelist(limit=0, **map): |
177 cl = web.repo.changelog | |
178 l = [] # build a list in forward order for efficiency | |
179 for i in xrange(start, end): | |
180 ctx = web.repo.changectx(i) | |
181 n = ctx.node() | |
182 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) | |
183 | |
184 l.insert(0, {"parity": parity.next(), | |
185 "author": ctx.user(), | |
186 "parent": webutil.siblings(ctx.parents(), i - 1), | |
187 "child": webutil.siblings(ctx.children(), i + 1), | |
188 "changelogtag": showtags, | |
189 "desc": ctx.description(), | |
190 "date": ctx.date(), | |
191 "files": web.listfilediffs(tmpl, ctx.files(), n), | |
192 "rev": i, | |
193 "node": hex(n), | |
194 "tags": webutil.nodetagsdict(web.repo, n), | |
195 "inbranch": webutil.nodeinbranch(web.repo, ctx), | |
196 "branches": webutil.nodebranchdict(web.repo, ctx) | |
197 }) | |
198 | |
199 if limit > 0: | |
200 l = l[:limit] | |
201 | |
202 for e in l: | |
203 yield e | |
204 | |
205 maxchanges = shortlog and web.maxshortchanges or web.maxchanges | |
206 cl = web.repo.changelog | |
207 count = cl.count() | |
208 pos = ctx.rev() | |
209 start = max(0, pos - maxchanges + 1) | |
210 end = min(count, start + maxchanges) | |
211 pos = end - 1 | |
212 parity = paritygen(web.stripecount, offset=start-end) | |
213 | |
214 changenav = webutil.revnavgen(pos, maxchanges, count, web.repo.changectx) | |
215 | |
216 return tmpl(shortlog and 'shortlog' or 'changelog', | |
217 changenav=changenav, | |
218 node=hex(cl.tip()), | |
219 rev=pos, changesets=count, | |
220 entries=lambda **x: changelist(limit=0,**x), | |
221 latestentry=lambda **x: changelist(limit=1,**x), | |
222 archives=web.archivelist("tip")) | |
83 | 223 |
84 def shortlog(web, req, tmpl): | 224 def shortlog(web, req, tmpl): |
85 return changelog(web, req, tmpl, shortlog = True) | 225 return changelog(web, req, tmpl, shortlog = True) |
86 | 226 |
87 def changeset(web, req, tmpl): | 227 def changeset(web, req, tmpl): |
88 return web.changeset(tmpl, webutil.changectx(web.repo, req)) | 228 ctx = webutil.changectx(web.repo, req) |
229 n = ctx.node() | |
230 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', n) | |
231 parents = ctx.parents() | |
232 p1 = parents[0].node() | |
233 | |
234 files = [] | |
235 parity = paritygen(web.stripecount) | |
236 for f in ctx.files(): | |
237 files.append(tmpl("filenodelink", | |
238 node=hex(n), file=f, | |
239 parity=parity.next())) | |
240 | |
241 diffs = web.diff(tmpl, p1, n, None) | |
242 return tmpl('changeset', | |
243 diff=diffs, | |
244 rev=ctx.rev(), | |
245 node=hex(n), | |
246 parent=webutil.siblings(parents), | |
247 child=webutil.siblings(ctx.children()), | |
248 changesettag=showtags, | |
249 author=ctx.user(), | |
250 desc=ctx.description(), | |
251 date=ctx.date(), | |
252 files=files, | |
253 archives=web.archivelist(hex(n)), | |
254 tags=webutil.nodetagsdict(web.repo, n), | |
255 branch=webutil.nodebranchnodefault(ctx), | |
256 inbranch=webutil.nodeinbranch(web.repo, ctx), | |
257 branches=webutil.nodebranchdict(web.repo, ctx)) | |
89 | 258 |
90 rev = changeset | 259 rev = changeset |
91 | 260 |
92 def manifest(web, req, tmpl): | 261 def manifest(web, req, tmpl): |
93 return web.manifest(tmpl, webutil.changectx(web.repo, req), | 262 ctx = webutil.changectx(web.repo, req) |
94 webutil.cleanpath(web.repo, req.form['path'][0])) | 263 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) |
264 mf = ctx.manifest() | |
265 node = ctx.node() | |
266 | |
267 files = {} | |
268 parity = paritygen(web.stripecount) | |
269 | |
270 if path and path[-1] != "/": | |
271 path += "/" | |
272 l = len(path) | |
273 abspath = "/" + path | |
274 | |
275 for f, n in mf.items(): | |
276 if f[:l] != path: | |
277 continue | |
278 remain = f[l:] | |
279 if "/" in remain: | |
280 short = remain[:remain.index("/") + 1] # bleah | |
281 files[short] = (f, None) | |
282 else: | |
283 short = os.path.basename(remain) | |
284 files[short] = (f, n) | |
285 | |
286 if not files: | |
287 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path) | |
288 | |
289 def filelist(**map): | |
290 fl = files.keys() | |
291 fl.sort() | |
292 for f in fl: | |
293 full, fnode = files[f] | |
294 if not fnode: | |
295 continue | |
296 | |
297 fctx = ctx.filectx(full) | |
298 yield {"file": full, | |
299 "parity": parity.next(), | |
300 "basename": f, | |
301 "date": fctx.changectx().date(), | |
302 "size": fctx.size(), | |
303 "permissions": mf.flags(full)} | |
304 | |
305 def dirlist(**map): | |
306 fl = files.keys() | |
307 fl.sort() | |
308 for f in fl: | |
309 full, fnode = files[f] | |
310 if fnode: | |
311 continue | |
312 | |
313 yield {"parity": parity.next(), | |
314 "path": "%s%s" % (abspath, f), | |
315 "basename": f[:-1]} | |
316 | |
317 return tmpl("manifest", | |
318 rev=ctx.rev(), | |
319 node=hex(node), | |
320 path=abspath, | |
321 up=webutil.up(abspath), | |
322 upparity=parity.next(), | |
323 fentries=filelist, | |
324 dentries=dirlist, | |
325 archives=web.archivelist(hex(node)), | |
326 tags=webutil.nodetagsdict(web.repo, node), | |
327 inbranch=webutil.nodeinbranch(web.repo, ctx), | |
328 branches=webutil.nodebranchdict(web.repo, ctx)) | |
95 | 329 |
96 def tags(web, req, tmpl): | 330 def tags(web, req, tmpl): |
97 return web.tags(tmpl) | 331 i = web.repo.tagslist() |
332 i.reverse() | |
333 parity = paritygen(web.stripecount) | |
334 | |
335 def entries(notip=False,limit=0, **map): | |
336 count = 0 | |
337 for k, n in i: | |
338 if notip and k == "tip": | |
339 continue | |
340 if limit > 0 and count >= limit: | |
341 continue | |
342 count = count + 1 | |
343 yield {"parity": parity.next(), | |
344 "tag": k, | |
345 "date": web.repo.changectx(n).date(), | |
346 "node": hex(n)} | |
347 | |
348 return tmpl("tags", | |
349 node=hex(web.repo.changelog.tip()), | |
350 entries=lambda **x: entries(False,0, **x), | |
351 entriesnotip=lambda **x: entries(True,0, **x), | |
352 latestentry=lambda **x: entries(True,1, **x)) | |
98 | 353 |
99 def summary(web, req, tmpl): | 354 def summary(web, req, tmpl): |
100 return web.summary(tmpl) | 355 i = web.repo.tagslist() |
356 i.reverse() | |
357 | |
358 def tagentries(**map): | |
359 parity = paritygen(web.stripecount) | |
360 count = 0 | |
361 for k, n in i: | |
362 if k == "tip": # skip tip | |
363 continue | |
364 | |
365 count = 1 | |
366 if count > 10: # limit to 10 tags | |
367 break | |
368 | |
369 yield tmpl("tagentry", | |
370 parity=parity.next(), | |
371 tag=k, | |
372 node=hex(n), | |
373 date=web.repo.changectx(n).date()) | |
374 | |
375 def branches(**map): | |
376 parity = paritygen(web.stripecount) | |
377 | |
378 b = web.repo.branchtags() | |
379 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.items()] | |
380 l.sort() | |
381 | |
382 for r,n,t in l: | |
383 ctx = web.repo.changectx(n) | |
384 yield {'parity': parity.next(), | |
385 'branch': t, | |
386 'node': hex(n), | |
387 'date': ctx.date()} | |
388 | |
389 def changelist(**map): | |
390 parity = paritygen(web.stripecount, offset=start-end) | |
391 l = [] # build a list in forward order for efficiency | |
392 for i in xrange(start, end): | |
393 ctx = web.repo.changectx(i) | |
394 n = ctx.node() | |
395 hn = hex(n) | |
396 | |
397 l.insert(0, tmpl( | |
398 'shortlogentry', | |
399 parity=parity.next(), | |
400 author=ctx.user(), | |
401 desc=ctx.description(), | |
402 date=ctx.date(), | |
403 rev=i, | |
404 node=hn, | |
405 tags=webutil.nodetagsdict(web.repo, n), | |
406 inbranch=webutil.nodeinbranch(web.repo, ctx), | |
407 branches=webutil.nodebranchdict(web.repo, ctx))) | |
408 | |
409 yield l | |
410 | |
411 cl = web.repo.changelog | |
412 count = cl.count() | |
413 start = max(0, count - web.maxchanges) | |
414 end = min(count, start + web.maxchanges) | |
415 | |
416 return tmpl("summary", | |
417 desc=web.config("web", "description", "unknown"), | |
418 owner=get_contact(web.config) or "unknown", | |
419 lastchange=cl.read(cl.tip())[2], | |
420 tags=tagentries, | |
421 branches=branches, | |
422 shortlog=changelist, | |
423 node=hex(cl.tip()), | |
424 archives=web.archivelist("tip")) | |
101 | 425 |
102 def filediff(web, req, tmpl): | 426 def filediff(web, req, tmpl): |
103 return web.filediff(tmpl, webutil.filectx(web.repo, req)) | 427 fctx = webutil.filectx(web.repo, req) |
428 n = fctx.node() | |
429 path = fctx.path() | |
430 parents = fctx.parents() | |
431 p1 = parents and parents[0].node() or nullid | |
432 | |
433 diffs = web.diff(tmpl, p1, n, [path]) | |
434 return tmpl("filediff", | |
435 file=path, | |
436 node=hex(n), | |
437 rev=fctx.rev(), | |
438 branch=webutil.nodebranchnodefault(fctx), | |
439 parent=webutil.siblings(parents), | |
440 child=webutil.siblings(fctx.children()), | |
441 diff=diffs) | |
104 | 442 |
105 diff = filediff | 443 diff = filediff |
106 | 444 |
107 def annotate(web, req, tmpl): | 445 def annotate(web, req, tmpl): |
108 return web.fileannotate(tmpl, webutil.filectx(web.repo, req)) | 446 fctx = webutil.filectx(web.repo, req) |
447 f = fctx.path() | |
448 n = fctx.filenode() | |
449 fl = fctx.filelog() | |
450 parity = paritygen(web.stripecount) | |
451 | |
452 def annotate(**map): | |
453 last = None | |
454 if binary(fctx.data()): | |
455 mt = (mimetypes.guess_type(fctx.path())[0] | |
456 or 'application/octet-stream') | |
457 lines = enumerate([((fctx.filectx(fctx.filerev()), 1), | |
458 '(binary:%s)' % mt)]) | |
459 else: | |
460 lines = enumerate(fctx.annotate(follow=True, linenumber=True)) | |
461 for lineno, ((f, targetline), l) in lines: | |
462 fnode = f.filenode() | |
463 name = web.repo.ui.shortuser(f.user()) | |
464 | |
465 if last != fnode: | |
466 last = fnode | |
467 | |
468 yield {"parity": parity.next(), | |
469 "node": hex(f.node()), | |
470 "rev": f.rev(), | |
471 "author": name, | |
472 "file": f.path(), | |
473 "targetline": targetline, | |
474 "line": l, | |
475 "lineid": "l%d" % (lineno + 1), | |
476 "linenumber": "% 6d" % (lineno + 1)} | |
477 | |
478 return tmpl("fileannotate", | |
479 file=f, | |
480 annotate=annotate, | |
481 path=webutil.up(f), | |
482 rev=fctx.rev(), | |
483 node=hex(fctx.node()), | |
484 author=fctx.user(), | |
485 date=fctx.date(), | |
486 desc=fctx.description(), | |
487 rename=webutil.renamelink(fl, n), | |
488 branch=webutil.nodebranchnodefault(fctx), | |
489 parent=webutil.siblings(fctx.parents()), | |
490 child=webutil.siblings(fctx.children()), | |
491 permissions=fctx.manifest().flags(f)) | |
109 | 492 |
110 def filelog(web, req, tmpl): | 493 def filelog(web, req, tmpl): |
111 return web.filelog(tmpl, webutil.filectx(web.repo, req)) | 494 fctx = webutil.filectx(web.repo, req) |
495 f = fctx.path() | |
496 fl = fctx.filelog() | |
497 count = fl.count() | |
498 pagelen = web.maxshortchanges | |
499 pos = fctx.filerev() | |
500 start = max(0, pos - pagelen + 1) | |
501 end = min(count, start + pagelen) | |
502 pos = end - 1 | |
503 parity = paritygen(web.stripecount, offset=start-end) | |
504 | |
505 def entries(limit=0, **map): | |
506 l = [] | |
507 | |
508 for i in xrange(start, end): | |
509 ctx = fctx.filectx(i) | |
510 n = fl.node(i) | |
511 | |
512 l.insert(0, {"parity": parity.next(), | |
513 "filerev": i, | |
514 "file": f, | |
515 "node": hex(ctx.node()), | |
516 "author": ctx.user(), | |
517 "date": ctx.date(), | |
518 "rename": webutil.renamelink(fl, n), | |
519 "parent": webutil.siblings(fctx.parents()), | |
520 "child": webutil.siblings(fctx.children()), | |
521 "desc": ctx.description()}) | |
522 | |
523 if limit > 0: | |
524 l = l[:limit] | |
525 | |
526 for e in l: | |
527 yield e | |
528 | |
529 nodefunc = lambda x: fctx.filectx(fileid=x) | |
530 nav = webutil.revnavgen(pos, pagelen, count, nodefunc) | |
531 return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav, | |
532 entries=lambda **x: entries(limit=0, **x), | |
533 latestentry=lambda **x: entries(limit=1, **x)) | |
534 | |
112 | 535 |
113 def archive(web, req, tmpl): | 536 def archive(web, req, tmpl): |
114 type_ = req.form['type'][0] | 537 type_ = req.form['type'][0] |
115 allowed = web.configlist("web", "allow_archive") | 538 allowed = web.configlist("web", "allow_archive") |
116 if (type_ in web.archives and (type_ in allowed or | 539 key = req.form['node'][0] |
540 | |
541 if not (type_ in web.archives and (type_ in allowed or | |
117 web.configbool("web", "allow" + type_, False))): | 542 web.configbool("web", "allow" + type_, False))): |
118 web.archive(tmpl, req, req.form['node'][0], type_) | 543 msg = 'Unsupported archive type: %s' % type_ |
119 return [] | 544 raise ErrorResponse(HTTP_NOT_FOUND, msg) |
120 raise ErrorResponse(HTTP_NOT_FOUND, 'unsupported archive type: %s' % type_) | 545 |
546 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame)) | |
547 cnode = web.repo.lookup(key) | |
548 arch_version = key | |
549 if cnode == key or key == 'tip': | |
550 arch_version = short(cnode) | |
551 name = "%s-%s" % (reponame, arch_version) | |
552 mimetype, artype, extension, encoding = web.archive_specs[type_] | |
553 headers = [ | |
554 ('Content-Type', mimetype), | |
555 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension)) | |
556 ] | |
557 if encoding: | |
558 headers.append(('Content-Encoding', encoding)) | |
559 req.header(headers) | |
560 req.respond(HTTP_OK) | |
561 archival.archive(web.repo, req, cnode, artype, prefix=name) | |
562 return [] | |
563 | |
121 | 564 |
122 def static(web, req, tmpl): | 565 def static(web, req, tmpl): |
123 fname = req.form['file'][0] | 566 fname = req.form['file'][0] |
124 # a repo owner may set web.static in .hg/hgrc to get any file | 567 # a repo owner may set web.static in .hg/hgrc to get any file |
125 # readable by the user running the CGI script | 568 # readable by the user running the CGI script |