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