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