Mercurial > traipse_dev
comparison upmana/mercurial/hgweb/webcommands.py @ 135:dcf4fbe09b70 beta
Traipse Beta 'OpenRPG' {091010-00}
Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on
code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to
offer more advanced features and enhance the productivity of the user.
Update Summary (Beta)
Added Bookmarks
Fix to Remote Admin Commands
Minor fix to text based Server
Fix to Pretty Print, from Core
Fix to Splitter Nodes not being created
Fix to massive amounts of images loading, from Core
Added 'boot' command to remote admin
Added confirmation window for sent nodes
Minor changes to allow for portability to an OpenSUSE linux OS
Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG
Zoom Mouse plugin added
Images added to Plugin UI
Switching to Element Tree
Map efficiency, from FlexiRPG
Added Status Bar to Update Manager
default_manifest.xml renamed to default_upmana.xml
Cleaner clode for saved repositories
New TrueDebug Class in orpg_log (See documentation for usage)
Mercurial's hgweb folder is ported to upmana
**Pretty important update that can help remove thousands of dead children from your gametree.
**Children, <forms />, <group_atts />, <horizontal />, <cols />, <rows />, <height />, etc... are all tags now. Check your gametree and
look for dead children!!
**New Gamtree Recusion method, mapping, and context sensitivity. !!Alpha - Watch out for infinite loops!!
author | sirebral |
---|---|
date | Tue, 10 Nov 2009 14:11:28 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
101:394ebb3b6a0f | 135:dcf4fbe09b70 |
---|---|
1 # | |
2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> | |
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | |
4 # | |
5 # This software may be used and distributed according to the terms of the | |
6 # GNU General Public License version 2, incorporated herein by reference. | |
7 | |
8 import os, mimetypes, re, cgi, copy | |
9 import webutil | |
10 from upmana.mercurial import error, archival, templater, templatefilters | |
11 from upmana.mercurial.node import short, hex | |
12 from upmana.mercurial.util import binary | |
13 from common import paritygen, staticfile, get_contact, ErrorResponse | |
14 from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND | |
15 from upmana.mercurial import graphmod | |
16 | |
17 # __all__ is populated with the allowed commands. Be sure to add to it if | |
18 # you're adding a new command, or the new command won't work. | |
19 | |
20 __all__ = [ | |
21 'log', 'rawfile', 'file', 'changelog', 'shortlog', 'changeset', 'rev', | |
22 'manifest', 'tags', 'branches', 'summary', 'filediff', 'diff', 'annotate', | |
23 'filelog', 'archive', 'static', 'graph', | |
24 ] | |
25 | |
26 def log(web, req, tmpl): | |
27 if 'file' in req.form and req.form['file'][0]: | |
28 return filelog(web, req, tmpl) | |
29 else: | |
30 return changelog(web, req, tmpl) | |
31 | |
32 def rawfile(web, req, tmpl): | |
33 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | |
34 if not path: | |
35 content = manifest(web, req, tmpl) | |
36 req.respond(HTTP_OK, web.ctype) | |
37 return content | |
38 | |
39 try: | |
40 fctx = webutil.filectx(web.repo, req) | |
41 except error.LookupError, inst: | |
42 try: | |
43 content = manifest(web, req, tmpl) | |
44 req.respond(HTTP_OK, web.ctype) | |
45 return content | |
46 except ErrorResponse: | |
47 raise inst | |
48 | |
49 path = fctx.path() | |
50 text = fctx.data() | |
51 mt = mimetypes.guess_type(path)[0] | |
52 if mt is None: | |
53 mt = binary(text) and 'application/octet-stream' or 'text/plain' | |
54 | |
55 req.respond(HTTP_OK, mt, path, len(text)) | |
56 return [text] | |
57 | |
58 def _filerevision(web, tmpl, fctx): | |
59 f = fctx.path() | |
60 text = fctx.data() | |
61 parity = paritygen(web.stripecount) | |
62 | |
63 if binary(text): | |
64 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream' | |
65 text = '(binary:%s)' % mt | |
66 | |
67 def lines(): | |
68 for lineno, t in enumerate(text.splitlines(1)): | |
69 yield {"line": t, | |
70 "lineid": "l%d" % (lineno + 1), | |
71 "linenumber": "% 6d" % (lineno + 1), | |
72 "parity": parity.next()} | |
73 | |
74 return tmpl("filerevision", | |
75 file=f, | |
76 path=webutil.up(f), | |
77 text=lines(), | |
78 rev=fctx.rev(), | |
79 node=hex(fctx.node()), | |
80 author=fctx.user(), | |
81 date=fctx.date(), | |
82 desc=fctx.description(), | |
83 branch=webutil.nodebranchnodefault(fctx), | |
84 parent=webutil.parents(fctx), | |
85 child=webutil.children(fctx), | |
86 rename=webutil.renamelink(fctx), | |
87 permissions=fctx.manifest().flags(f)) | |
88 | |
89 def file(web, req, tmpl): | |
90 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | |
91 if not path: | |
92 return manifest(web, req, tmpl) | |
93 try: | |
94 return _filerevision(web, tmpl, webutil.filectx(web.repo, req)) | |
95 except error.LookupError, inst: | |
96 try: | |
97 return manifest(web, req, tmpl) | |
98 except ErrorResponse: | |
99 raise inst | |
100 | |
101 def _search(web, tmpl, query): | |
102 | |
103 def changelist(**map): | |
104 cl = web.repo.changelog | |
105 count = 0 | |
106 qw = query.lower().split() | |
107 | |
108 def revgen(): | |
109 for i in xrange(len(cl) - 1, 0, -100): | |
110 l = [] | |
111 for j in xrange(max(0, i - 100), i + 1): | |
112 ctx = web.repo[j] | |
113 l.append(ctx) | |
114 l.reverse() | |
115 for e in l: | |
116 yield e | |
117 | |
118 for ctx in revgen(): | |
119 miss = 0 | |
120 for q in qw: | |
121 if not (q in ctx.user().lower() or | |
122 q in ctx.description().lower() or | |
123 q in " ".join(ctx.files()).lower()): | |
124 miss = 1 | |
125 break | |
126 if miss: | |
127 continue | |
128 | |
129 count += 1 | |
130 n = ctx.node() | |
131 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) | |
132 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles) | |
133 | |
134 yield tmpl('searchentry', | |
135 parity=parity.next(), | |
136 author=ctx.user(), | |
137 parent=webutil.parents(ctx), | |
138 child=webutil.children(ctx), | |
139 changelogtag=showtags, | |
140 desc=ctx.description(), | |
141 date=ctx.date(), | |
142 files=files, | |
143 rev=ctx.rev(), | |
144 node=hex(n), | |
145 tags=webutil.nodetagsdict(web.repo, n), | |
146 inbranch=webutil.nodeinbranch(web.repo, ctx), | |
147 branches=webutil.nodebranchdict(web.repo, ctx)) | |
148 | |
149 if count >= web.maxchanges: | |
150 break | |
151 | |
152 cl = web.repo.changelog | |
153 parity = paritygen(web.stripecount) | |
154 | |
155 return tmpl('search', | |
156 query=query, | |
157 node=hex(cl.tip()), | |
158 entries=changelist, | |
159 archives=web.archivelist("tip")) | |
160 | |
161 def changelog(web, req, tmpl, shortlog = False): | |
162 if 'node' in req.form: | |
163 ctx = webutil.changectx(web.repo, req) | |
164 else: | |
165 if 'rev' in req.form: | |
166 hi = req.form['rev'][0] | |
167 else: | |
168 hi = len(web.repo) - 1 | |
169 try: | |
170 ctx = web.repo[hi] | |
171 except error.RepoError: | |
172 return _search(web, tmpl, hi) # XXX redirect to 404 page? | |
173 | |
174 def changelist(limit=0, **map): | |
175 l = [] # build a list in forward order for efficiency | |
176 for i in xrange(start, end): | |
177 ctx = web.repo[i] | |
178 n = ctx.node() | |
179 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) | |
180 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles) | |
181 | |
182 l.insert(0, {"parity": parity.next(), | |
183 "author": ctx.user(), | |
184 "parent": webutil.parents(ctx, i - 1), | |
185 "child": webutil.children(ctx, i + 1), | |
186 "changelogtag": showtags, | |
187 "desc": ctx.description(), | |
188 "date": ctx.date(), | |
189 "files": files, | |
190 "rev": i, | |
191 "node": hex(n), | |
192 "tags": webutil.nodetagsdict(web.repo, n), | |
193 "inbranch": webutil.nodeinbranch(web.repo, ctx), | |
194 "branches": webutil.nodebranchdict(web.repo, ctx) | |
195 }) | |
196 | |
197 if limit > 0: | |
198 l = l[:limit] | |
199 | |
200 for e in l: | |
201 yield e | |
202 | |
203 maxchanges = shortlog and web.maxshortchanges or web.maxchanges | |
204 cl = web.repo.changelog | |
205 count = len(cl) | |
206 pos = ctx.rev() | |
207 start = max(0, pos - maxchanges + 1) | |
208 end = min(count, start + maxchanges) | |
209 pos = end - 1 | |
210 parity = paritygen(web.stripecount, offset=start-end) | |
211 | |
212 changenav = webutil.revnavgen(pos, maxchanges, count, web.repo.changectx) | |
213 | |
214 return tmpl(shortlog and 'shortlog' or 'changelog', | |
215 changenav=changenav, | |
216 node=hex(ctx.node()), | |
217 rev=pos, changesets=count, | |
218 entries=lambda **x: changelist(limit=0,**x), | |
219 latestentry=lambda **x: changelist(limit=1,**x), | |
220 archives=web.archivelist("tip")) | |
221 | |
222 def shortlog(web, req, tmpl): | |
223 return changelog(web, req, tmpl, shortlog = True) | |
224 | |
225 def changeset(web, req, tmpl): | |
226 ctx = webutil.changectx(web.repo, req) | |
227 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node()) | |
228 showbranch = webutil.nodebranchnodefault(ctx) | |
229 | |
230 files = [] | |
231 parity = paritygen(web.stripecount) | |
232 for f in ctx.files(): | |
233 template = f in ctx and 'filenodelink' or 'filenolink' | |
234 files.append(tmpl(template, | |
235 node=ctx.hex(), file=f, | |
236 parity=parity.next())) | |
237 | |
238 parity = paritygen(web.stripecount) | |
239 diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity) | |
240 return tmpl('changeset', | |
241 diff=diffs, | |
242 rev=ctx.rev(), | |
243 node=ctx.hex(), | |
244 parent=webutil.parents(ctx), | |
245 child=webutil.children(ctx), | |
246 changesettag=showtags, | |
247 changesetbranch=showbranch, | |
248 author=ctx.user(), | |
249 desc=ctx.description(), | |
250 date=ctx.date(), | |
251 files=files, | |
252 archives=web.archivelist(ctx.hex()), | |
253 tags=webutil.nodetagsdict(web.repo, ctx.node()), | |
254 branch=webutil.nodebranchnodefault(ctx), | |
255 inbranch=webutil.nodeinbranch(web.repo, ctx), | |
256 branches=webutil.nodebranchdict(web.repo, ctx)) | |
257 | |
258 rev = changeset | |
259 | |
260 def manifest(web, req, tmpl): | |
261 ctx = webutil.changectx(web.repo, req) | |
262 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | |
263 mf = ctx.manifest() | |
264 node = ctx.node() | |
265 | |
266 files = {} | |
267 dirs = {} | |
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.iteritems(): | |
276 if f[:l] != path: | |
277 continue | |
278 remain = f[l:] | |
279 elements = remain.split('/') | |
280 if len(elements) == 1: | |
281 files[remain] = f | |
282 else: | |
283 h = dirs # need to retain ref to dirs (root) | |
284 for elem in elements[0:-1]: | |
285 if elem not in h: | |
286 h[elem] = {} | |
287 h = h[elem] | |
288 if len(h) > 1: | |
289 break | |
290 h[None] = None # denotes files present | |
291 | |
292 if mf and not files and not dirs: | |
293 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path) | |
294 | |
295 def filelist(**map): | |
296 for f in sorted(files): | |
297 full = files[f] | |
298 | |
299 fctx = ctx.filectx(full) | |
300 yield {"file": full, | |
301 "parity": parity.next(), | |
302 "basename": f, | |
303 "date": fctx.date(), | |
304 "size": fctx.size(), | |
305 "permissions": mf.flags(full)} | |
306 | |
307 def dirlist(**map): | |
308 for d in sorted(dirs): | |
309 | |
310 emptydirs = [] | |
311 h = dirs[d] | |
312 while isinstance(h, dict) and len(h) == 1: | |
313 k,v = h.items()[0] | |
314 if v: | |
315 emptydirs.append(k) | |
316 h = v | |
317 | |
318 path = "%s%s" % (abspath, d) | |
319 yield {"parity": parity.next(), | |
320 "path": path, | |
321 "emptydirs": "/".join(emptydirs), | |
322 "basename": d} | |
323 | |
324 return tmpl("manifest", | |
325 rev=ctx.rev(), | |
326 node=hex(node), | |
327 path=abspath, | |
328 up=webutil.up(abspath), | |
329 upparity=parity.next(), | |
330 fentries=filelist, | |
331 dentries=dirlist, | |
332 archives=web.archivelist(hex(node)), | |
333 tags=webutil.nodetagsdict(web.repo, node), | |
334 inbranch=webutil.nodeinbranch(web.repo, ctx), | |
335 branches=webutil.nodebranchdict(web.repo, ctx)) | |
336 | |
337 def tags(web, req, tmpl): | |
338 i = web.repo.tagslist() | |
339 i.reverse() | |
340 parity = paritygen(web.stripecount) | |
341 | |
342 def entries(notip=False,limit=0, **map): | |
343 count = 0 | |
344 for k, n in i: | |
345 if notip and k == "tip": | |
346 continue | |
347 if limit > 0 and count >= limit: | |
348 continue | |
349 count = count + 1 | |
350 yield {"parity": parity.next(), | |
351 "tag": k, | |
352 "date": web.repo[n].date(), | |
353 "node": hex(n)} | |
354 | |
355 return tmpl("tags", | |
356 node=hex(web.repo.changelog.tip()), | |
357 entries=lambda **x: entries(False,0, **x), | |
358 entriesnotip=lambda **x: entries(True,0, **x), | |
359 latestentry=lambda **x: entries(True,1, **x)) | |
360 | |
361 def branches(web, req, tmpl): | |
362 b = web.repo.branchtags() | |
363 tips = (web.repo[n] for t, n in web.repo.branchtags().iteritems()) | |
364 heads = web.repo.heads() | |
365 parity = paritygen(web.stripecount) | |
366 sortkey = lambda ctx: ('close' not in ctx.extra(), ctx.rev()) | |
367 | |
368 def entries(limit, **map): | |
369 count = 0 | |
370 for ctx in sorted(tips, key=sortkey, reverse=True): | |
371 if limit > 0 and count >= limit: | |
372 return | |
373 count += 1 | |
374 if ctx.node() not in heads: | |
375 status = 'inactive' | |
376 elif not web.repo.branchheads(ctx.branch()): | |
377 status = 'closed' | |
378 else: | |
379 status = 'open' | |
380 yield {'parity': parity.next(), | |
381 'branch': ctx.branch(), | |
382 'status': status, | |
383 'node': ctx.hex(), | |
384 'date': ctx.date()} | |
385 | |
386 return tmpl('branches', node=hex(web.repo.changelog.tip()), | |
387 entries=lambda **x: entries(0, **x), | |
388 latestentry=lambda **x: entries(1, **x)) | |
389 | |
390 def summary(web, req, tmpl): | |
391 i = web.repo.tagslist() | |
392 i.reverse() | |
393 | |
394 def tagentries(**map): | |
395 parity = paritygen(web.stripecount) | |
396 count = 0 | |
397 for k, n in i: | |
398 if k == "tip": # skip tip | |
399 continue | |
400 | |
401 count += 1 | |
402 if count > 10: # limit to 10 tags | |
403 break | |
404 | |
405 yield tmpl("tagentry", | |
406 parity=parity.next(), | |
407 tag=k, | |
408 node=hex(n), | |
409 date=web.repo[n].date()) | |
410 | |
411 def branches(**map): | |
412 parity = paritygen(web.stripecount) | |
413 | |
414 b = web.repo.branchtags() | |
415 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()] | |
416 for r,n,t in sorted(l): | |
417 yield {'parity': parity.next(), | |
418 'branch': t, | |
419 'node': hex(n), | |
420 'date': web.repo[n].date()} | |
421 | |
422 def changelist(**map): | |
423 parity = paritygen(web.stripecount, offset=start-end) | |
424 l = [] # build a list in forward order for efficiency | |
425 for i in xrange(start, end): | |
426 ctx = web.repo[i] | |
427 n = ctx.node() | |
428 hn = hex(n) | |
429 | |
430 l.insert(0, tmpl( | |
431 'shortlogentry', | |
432 parity=parity.next(), | |
433 author=ctx.user(), | |
434 desc=ctx.description(), | |
435 date=ctx.date(), | |
436 rev=i, | |
437 node=hn, | |
438 tags=webutil.nodetagsdict(web.repo, n), | |
439 inbranch=webutil.nodeinbranch(web.repo, ctx), | |
440 branches=webutil.nodebranchdict(web.repo, ctx))) | |
441 | |
442 yield l | |
443 | |
444 cl = web.repo.changelog | |
445 count = len(cl) | |
446 start = max(0, count - web.maxchanges) | |
447 end = min(count, start + web.maxchanges) | |
448 | |
449 return tmpl("summary", | |
450 desc=web.config("web", "description", "unknown"), | |
451 owner=get_contact(web.config) or "unknown", | |
452 lastchange=cl.read(cl.tip())[2], | |
453 tags=tagentries, | |
454 branches=branches, | |
455 shortlog=changelist, | |
456 node=hex(cl.tip()), | |
457 archives=web.archivelist("tip")) | |
458 | |
459 def filediff(web, req, tmpl): | |
460 fctx, ctx = None, None | |
461 try: | |
462 fctx = webutil.filectx(web.repo, req) | |
463 except LookupError: | |
464 ctx = webutil.changectx(web.repo, req) | |
465 path = webutil.cleanpath(web.repo, req.form['file'][0]) | |
466 if path not in ctx.files(): | |
467 raise | |
468 | |
469 if fctx is not None: | |
470 n = fctx.node() | |
471 path = fctx.path() | |
472 else: | |
473 n = ctx.node() | |
474 # path already defined in except clause | |
475 | |
476 parity = paritygen(web.stripecount) | |
477 diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity) | |
478 rename = fctx and webutil.renamelink(fctx) or [] | |
479 ctx = fctx and fctx or ctx | |
480 return tmpl("filediff", | |
481 file=path, | |
482 node=hex(n), | |
483 rev=ctx.rev(), | |
484 date=ctx.date(), | |
485 desc=ctx.description(), | |
486 author=ctx.user(), | |
487 rename=rename, | |
488 branch=webutil.nodebranchnodefault(ctx), | |
489 parent=webutil.parents(ctx), | |
490 child=webutil.children(ctx), | |
491 diff=diffs) | |
492 | |
493 diff = filediff | |
494 | |
495 def annotate(web, req, tmpl): | |
496 fctx = webutil.filectx(web.repo, req) | |
497 f = fctx.path() | |
498 parity = paritygen(web.stripecount) | |
499 | |
500 def annotate(**map): | |
501 last = None | |
502 if binary(fctx.data()): | |
503 mt = (mimetypes.guess_type(fctx.path())[0] | |
504 or 'application/octet-stream') | |
505 lines = enumerate([((fctx.filectx(fctx.filerev()), 1), | |
506 '(binary:%s)' % mt)]) | |
507 else: | |
508 lines = enumerate(fctx.annotate(follow=True, linenumber=True)) | |
509 for lineno, ((f, targetline), l) in lines: | |
510 fnode = f.filenode() | |
511 | |
512 if last != fnode: | |
513 last = fnode | |
514 | |
515 yield {"parity": parity.next(), | |
516 "node": hex(f.node()), | |
517 "rev": f.rev(), | |
518 "author": f.user(), | |
519 "desc": f.description(), | |
520 "file": f.path(), | |
521 "targetline": targetline, | |
522 "line": l, | |
523 "lineid": "l%d" % (lineno + 1), | |
524 "linenumber": "% 6d" % (lineno + 1)} | |
525 | |
526 return tmpl("fileannotate", | |
527 file=f, | |
528 annotate=annotate, | |
529 path=webutil.up(f), | |
530 rev=fctx.rev(), | |
531 node=hex(fctx.node()), | |
532 author=fctx.user(), | |
533 date=fctx.date(), | |
534 desc=fctx.description(), | |
535 rename=webutil.renamelink(fctx), | |
536 branch=webutil.nodebranchnodefault(fctx), | |
537 parent=webutil.parents(fctx), | |
538 child=webutil.children(fctx), | |
539 permissions=fctx.manifest().flags(f)) | |
540 | |
541 def filelog(web, req, tmpl): | |
542 | |
543 try: | |
544 fctx = webutil.filectx(web.repo, req) | |
545 f = fctx.path() | |
546 fl = fctx.filelog() | |
547 except error.LookupError: | |
548 f = webutil.cleanpath(web.repo, req.form['file'][0]) | |
549 fl = web.repo.file(f) | |
550 numrevs = len(fl) | |
551 if not numrevs: # file doesn't exist at all | |
552 raise | |
553 rev = webutil.changectx(web.repo, req).rev() | |
554 first = fl.linkrev(0) | |
555 if rev < first: # current rev is from before file existed | |
556 raise | |
557 frev = numrevs - 1 | |
558 while fl.linkrev(frev) > rev: | |
559 frev -= 1 | |
560 fctx = web.repo.filectx(f, fl.linkrev(frev)) | |
561 | |
562 count = fctx.filerev() + 1 | |
563 pagelen = web.maxshortchanges | |
564 start = max(0, fctx.filerev() - pagelen + 1) # first rev on this page | |
565 end = min(count, start + pagelen) # last rev on this page | |
566 parity = paritygen(web.stripecount, offset=start-end) | |
567 | |
568 def entries(limit=0, **map): | |
569 l = [] | |
570 | |
571 repo = web.repo | |
572 for i in xrange(start, end): | |
573 iterfctx = fctx.filectx(i) | |
574 | |
575 l.insert(0, {"parity": parity.next(), | |
576 "filerev": i, | |
577 "file": f, | |
578 "node": hex(iterfctx.node()), | |
579 "author": iterfctx.user(), | |
580 "date": iterfctx.date(), | |
581 "rename": webutil.renamelink(iterfctx), | |
582 "parent": webutil.parents(iterfctx), | |
583 "child": webutil.children(iterfctx), | |
584 "desc": iterfctx.description(), | |
585 "tags": webutil.nodetagsdict(repo, iterfctx.node()), | |
586 "branch": webutil.nodebranchnodefault(iterfctx), | |
587 "inbranch": webutil.nodeinbranch(repo, iterfctx), | |
588 "branches": webutil.nodebranchdict(repo, iterfctx)}) | |
589 | |
590 if limit > 0: | |
591 l = l[:limit] | |
592 | |
593 for e in l: | |
594 yield e | |
595 | |
596 nodefunc = lambda x: fctx.filectx(fileid=x) | |
597 nav = webutil.revnavgen(end - 1, pagelen, count, nodefunc) | |
598 return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav, | |
599 entries=lambda **x: entries(limit=0, **x), | |
600 latestentry=lambda **x: entries(limit=1, **x)) | |
601 | |
602 | |
603 def archive(web, req, tmpl): | |
604 type_ = req.form.get('type', [None])[0] | |
605 allowed = web.configlist("web", "allow_archive") | |
606 key = req.form['node'][0] | |
607 | |
608 if type_ not in web.archives: | |
609 msg = 'Unsupported archive type: %s' % type_ | |
610 raise ErrorResponse(HTTP_NOT_FOUND, msg) | |
611 | |
612 if not ((type_ in allowed or | |
613 web.configbool("web", "allow" + type_, False))): | |
614 msg = 'Archive type not allowed: %s' % type_ | |
615 raise ErrorResponse(HTTP_FORBIDDEN, msg) | |
616 | |
617 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame)) | |
618 cnode = web.repo.lookup(key) | |
619 arch_version = key | |
620 if cnode == key or key == 'tip': | |
621 arch_version = short(cnode) | |
622 name = "%s-%s" % (reponame, arch_version) | |
623 mimetype, artype, extension, encoding = web.archive_specs[type_] | |
624 headers = [ | |
625 ('Content-Type', mimetype), | |
626 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension)) | |
627 ] | |
628 if encoding: | |
629 headers.append(('Content-Encoding', encoding)) | |
630 req.header(headers) | |
631 req.respond(HTTP_OK) | |
632 archival.archive(web.repo, req, cnode, artype, prefix=name) | |
633 return [] | |
634 | |
635 | |
636 def static(web, req, tmpl): | |
637 fname = req.form['file'][0] | |
638 # a repo owner may set web.static in .hg/hgrc to get any file | |
639 # readable by the user running the CGI script | |
640 static = web.config("web", "static", None, untrusted=False) | |
641 if not static: | |
642 tp = web.templatepath or templater.templatepath() | |
643 if isinstance(tp, str): | |
644 tp = [tp] | |
645 static = [os.path.join(p, 'static') for p in tp] | |
646 return [staticfile(static, fname, req)] | |
647 | |
648 def graph(web, req, tmpl): | |
649 rev = webutil.changectx(web.repo, req).rev() | |
650 bg_height = 39 | |
651 | |
652 revcount = 25 | |
653 if 'revcount' in req.form: | |
654 revcount = int(req.form.get('revcount', [revcount])[0]) | |
655 tmpl.defaults['sessionvars']['revcount'] = revcount | |
656 | |
657 lessvars = copy.copy(tmpl.defaults['sessionvars']) | |
658 lessvars['revcount'] = revcount / 2 | |
659 morevars = copy.copy(tmpl.defaults['sessionvars']) | |
660 morevars['revcount'] = revcount * 2 | |
661 | |
662 max_rev = len(web.repo) - 1 | |
663 revcount = min(max_rev, revcount) | |
664 revnode = web.repo.changelog.node(rev) | |
665 revnode_hex = hex(revnode) | |
666 uprev = min(max_rev, rev + revcount) | |
667 downrev = max(0, rev - revcount) | |
668 count = len(web.repo) | |
669 changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx) | |
670 | |
671 dag = graphmod.revisions(web.repo, rev, downrev) | |
672 tree = list(graphmod.colored(dag)) | |
673 canvasheight = (len(tree) + 1) * bg_height - 27; | |
674 data = [] | |
675 for (id, type, ctx, vtx, edges) in tree: | |
676 if type != graphmod.CHANGESET: | |
677 continue | |
678 node = short(ctx.node()) | |
679 age = templatefilters.age(ctx.date()) | |
680 desc = templatefilters.firstline(ctx.description()) | |
681 desc = cgi.escape(templatefilters.nonempty(desc)) | |
682 user = cgi.escape(templatefilters.person(ctx.user())) | |
683 branch = ctx.branch() | |
684 branch = branch, web.repo.branchtags().get(branch) == ctx.node() | |
685 data.append((node, vtx, edges, desc, user, age, branch, ctx.tags())) | |
686 | |
687 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev, | |
688 lessvars=lessvars, morevars=morevars, downrev=downrev, | |
689 canvasheight=canvasheight, jsdata=data, bg_height=bg_height, | |
690 node=revnode_hex, changenav=changenav) |