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