Show More
@@ -0,0 +1,94 b'' | |||
|
1 | # hgweb/webutil.py - utility library for the web interface. | |
|
2 | # | |
|
3 | # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> | |
|
4 | # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | |
|
5 | # | |
|
6 | # This software may be used and distributed according to the terms | |
|
7 | # of the GNU General Public License, incorporated herein by reference. | |
|
8 | ||
|
9 | from mercurial.node import hex, nullid | |
|
10 | from mercurial.repo import RepoError | |
|
11 | from mercurial import util | |
|
12 | ||
|
13 | def siblings(siblings=[], hiderev=None, **args): | |
|
14 | siblings = [s for s in siblings if s.node() != nullid] | |
|
15 | if len(siblings) == 1 and siblings[0].rev() == hiderev: | |
|
16 | return | |
|
17 | for s in siblings: | |
|
18 | d = {'node': hex(s.node()), 'rev': s.rev()} | |
|
19 | if hasattr(s, 'path'): | |
|
20 | d['file'] = s.path() | |
|
21 | d.update(args) | |
|
22 | yield d | |
|
23 | ||
|
24 | def renamelink(fl, node): | |
|
25 | r = fl.renamed(node) | |
|
26 | if r: | |
|
27 | return [dict(file=r[0], node=hex(r[1]))] | |
|
28 | return [] | |
|
29 | ||
|
30 | def nodetagsdict(repo, node): | |
|
31 | return [{"name": i} for i in repo.nodetags(node)] | |
|
32 | ||
|
33 | def nodebranchdict(repo, ctx): | |
|
34 | branches = [] | |
|
35 | branch = ctx.branch() | |
|
36 | # If this is an empty repo, ctx.node() == nullid, | |
|
37 | # ctx.branch() == 'default', but branchtags() is | |
|
38 | # an empty dict. Using dict.get avoids a traceback. | |
|
39 | if repo.branchtags().get(branch) == ctx.node(): | |
|
40 | branches.append({"name": branch}) | |
|
41 | return branches | |
|
42 | ||
|
43 | def nodeinbranch(repo, ctx): | |
|
44 | branches = [] | |
|
45 | branch = ctx.branch() | |
|
46 | if branch != 'default' and repo.branchtags().get(branch) != ctx.node(): | |
|
47 | branches.append({"name": branch}) | |
|
48 | return branches | |
|
49 | ||
|
50 | def nodebranchnodefault(ctx): | |
|
51 | branches = [] | |
|
52 | branch = ctx.branch() | |
|
53 | if branch != 'default': | |
|
54 | branches.append({"name": branch}) | |
|
55 | return branches | |
|
56 | ||
|
57 | def showtag(repo, tmpl, t1, node=nullid, **args): | |
|
58 | for t in repo.nodetags(node): | |
|
59 | yield tmpl(t1, tag=t, **args) | |
|
60 | ||
|
61 | def cleanpath(repo, path): | |
|
62 | path = path.lstrip('/') | |
|
63 | return util.canonpath(repo.root, '', path) | |
|
64 | ||
|
65 | def changectx(repo, req): | |
|
66 | if 'node' in req.form: | |
|
67 | changeid = req.form['node'][0] | |
|
68 | elif 'manifest' in req.form: | |
|
69 | changeid = req.form['manifest'][0] | |
|
70 | else: | |
|
71 | changeid = self.repo.changelog.count() - 1 | |
|
72 | ||
|
73 | try: | |
|
74 | ctx = repo.changectx(changeid) | |
|
75 | except RepoError: | |
|
76 | man = repo.manifest | |
|
77 | mn = man.lookup(changeid) | |
|
78 | ctx = repo.changectx(man.linkrev(mn)) | |
|
79 | ||
|
80 | return ctx | |
|
81 | ||
|
82 | def filectx(repo, req): | |
|
83 | path = cleanpath(repo, req.form['file'][0]) | |
|
84 | if 'node' in req.form: | |
|
85 | changeid = req.form['node'][0] | |
|
86 | else: | |
|
87 | changeid = req.form['filenode'][0] | |
|
88 | try: | |
|
89 | ctx = repo.changectx(changeid) | |
|
90 | fctx = ctx.filectx(path) | |
|
91 | except RepoError: | |
|
92 | fctx = repo.filectx(path, fileid=changeid) | |
|
93 | ||
|
94 | return fctx |
@@ -15,7 +15,7 b' from common import get_mtime, style_map,' | |||
|
15 | 15 | from common import ErrorResponse |
|
16 | 16 | from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR |
|
17 | 17 | from request import wsgirequest |
|
18 | import webcommands, protocol | |
|
18 | import webcommands, protocol, webutil | |
|
19 | 19 | |
|
20 | 20 | shortcuts = { |
|
21 | 21 | 'cl': [('cmd', ['changelog']), ('rev', None)], |
@@ -340,54 +340,6 b' class hgweb(object):' | |||
|
340 | 340 | if len(files) > self.maxfiles: |
|
341 | 341 | yield tmpl("fileellipses") |
|
342 | 342 | |
|
343 | def siblings(self, siblings=[], hiderev=None, **args): | |
|
344 | siblings = [s for s in siblings if s.node() != nullid] | |
|
345 | if len(siblings) == 1 and siblings[0].rev() == hiderev: | |
|
346 | return | |
|
347 | for s in siblings: | |
|
348 | d = {'node': hex(s.node()), 'rev': s.rev()} | |
|
349 | if hasattr(s, 'path'): | |
|
350 | d['file'] = s.path() | |
|
351 | d.update(args) | |
|
352 | yield d | |
|
353 | ||
|
354 | def renamelink(self, fl, node): | |
|
355 | r = fl.renamed(node) | |
|
356 | if r: | |
|
357 | return [dict(file=r[0], node=hex(r[1]))] | |
|
358 | return [] | |
|
359 | ||
|
360 | def nodetagsdict(self, node): | |
|
361 | return [{"name": i} for i in self.repo.nodetags(node)] | |
|
362 | ||
|
363 | def nodebranchdict(self, ctx): | |
|
364 | branches = [] | |
|
365 | branch = ctx.branch() | |
|
366 | # If this is an empty repo, ctx.node() == nullid, | |
|
367 | # ctx.branch() == 'default', but branchtags() is | |
|
368 | # an empty dict. Using dict.get avoids a traceback. | |
|
369 | if self.repo.branchtags().get(branch) == ctx.node(): | |
|
370 | branches.append({"name": branch}) | |
|
371 | return branches | |
|
372 | ||
|
373 | def nodeinbranch(self, ctx): | |
|
374 | branches = [] | |
|
375 | branch = ctx.branch() | |
|
376 | if branch != 'default' and self.repo.branchtags().get(branch) != ctx.node(): | |
|
377 | branches.append({"name": branch}) | |
|
378 | return branches | |
|
379 | ||
|
380 | def nodebranchnodefault(self, ctx): | |
|
381 | branches = [] | |
|
382 | branch = ctx.branch() | |
|
383 | if branch != 'default': | |
|
384 | branches.append({"name": branch}) | |
|
385 | return branches | |
|
386 | ||
|
387 | def showtag(self, tmpl, t1, node=nullid, **args): | |
|
388 | for t in self.repo.nodetags(node): | |
|
389 | yield tmpl(t1, tag=t, **args) | |
|
390 | ||
|
391 | 343 | def diff(self, tmpl, node1, node2, files): |
|
392 | 344 | def filterfiles(filters, files): |
|
393 | 345 | l = [x for x in files if x in filters] |
@@ -462,21 +414,22 b' class hgweb(object):' | |||
|
462 | 414 | for i in xrange(start, end): |
|
463 | 415 | ctx = self.repo.changectx(i) |
|
464 | 416 | n = ctx.node() |
|
465 |
showtags = |
|
|
417 | showtags = webutil.showtag(self.repo, tmpl, 'changelogtag', n) | |
|
466 | 418 | |
|
467 | 419 | l.insert(0, {"parity": parity.next(), |
|
468 | 420 | "author": ctx.user(), |
|
469 |
"parent": |
|
|
470 |
"child": |
|
|
421 | "parent": webutil.siblings(ctx.parents(), i - 1), | |
|
422 | "child": webutil.siblings(ctx.children(), i + 1), | |
|
471 | 423 | "changelogtag": showtags, |
|
472 | 424 | "desc": ctx.description(), |
|
473 | 425 | "date": ctx.date(), |
|
474 | 426 | "files": self.listfilediffs(tmpl, ctx.files(), n), |
|
475 | 427 | "rev": i, |
|
476 | 428 | "node": hex(n), |
|
477 |
"tags": |
|
|
478 |
"inbranch": |
|
|
479 |
"branches": |
|
|
429 | "tags": webutil.nodetagsdict(self.repo, n), | |
|
430 | "inbranch": webutil.nodeinbranch(self.repo, ctx), | |
|
431 | "branches": webutil.nodebranchdict(self.repo, ctx) | |
|
432 | }) | |
|
480 | 433 | |
|
481 | 434 | if limit > 0: |
|
482 | 435 | l = l[:limit] |
@@ -533,22 +486,22 b' class hgweb(object):' | |||
|
533 | 486 | |
|
534 | 487 | count += 1 |
|
535 | 488 | n = ctx.node() |
|
536 |
showtags = |
|
|
489 | showtags = webutil.showtag(self.repo, tmpl, 'changelogtag', n) | |
|
537 | 490 | |
|
538 | 491 | yield tmpl('searchentry', |
|
539 | 492 | parity=parity.next(), |
|
540 | 493 | author=ctx.user(), |
|
541 |
parent= |
|
|
542 |
child= |
|
|
494 | parent=webutil.siblings(ctx.parents()), | |
|
495 | child=webutil.siblings(ctx.children()), | |
|
543 | 496 | changelogtag=showtags, |
|
544 | 497 | desc=ctx.description(), |
|
545 | 498 | date=ctx.date(), |
|
546 | 499 | files=self.listfilediffs(tmpl, ctx.files(), n), |
|
547 | 500 | rev=ctx.rev(), |
|
548 | 501 | node=hex(n), |
|
549 |
tags= |
|
|
550 |
inbranch= |
|
|
551 |
branches= |
|
|
502 | tags=webutil.nodetagsdict(self.repo, n), | |
|
503 | inbranch=webutil.nodeinbranch(self.repo, ctx), | |
|
504 | branches=webutil.nodebranchdict(self.repo, ctx)) | |
|
552 | 505 | |
|
553 | 506 | if count >= self.maxchanges: |
|
554 | 507 | break |
@@ -564,7 +517,7 b' class hgweb(object):' | |||
|
564 | 517 | |
|
565 | 518 | def changeset(self, tmpl, ctx): |
|
566 | 519 | n = ctx.node() |
|
567 |
showtags = |
|
|
520 | showtags = webutil.showtag(self.repo, tmpl, 'changesettag', n) | |
|
568 | 521 | parents = ctx.parents() |
|
569 | 522 | p1 = parents[0].node() |
|
570 | 523 | |
@@ -582,18 +535,18 b' class hgweb(object):' | |||
|
582 | 535 | diff=diff, |
|
583 | 536 | rev=ctx.rev(), |
|
584 | 537 | node=hex(n), |
|
585 |
parent= |
|
|
586 |
child= |
|
|
538 | parent=webutil.siblings(parents), | |
|
539 | child=webutil.siblings(ctx.children()), | |
|
587 | 540 | changesettag=showtags, |
|
588 | 541 | author=ctx.user(), |
|
589 | 542 | desc=ctx.description(), |
|
590 | 543 | date=ctx.date(), |
|
591 | 544 | files=files, |
|
592 | 545 | archives=self.archivelist(hex(n)), |
|
593 |
tags= |
|
|
594 |
branch= |
|
|
595 |
inbranch= |
|
|
596 |
branches= |
|
|
546 | tags=webutil.nodetagsdict(self.repo, n), | |
|
547 | branch=webutil.nodebranchnodefault(ctx), | |
|
548 | inbranch=webutil.nodeinbranch(self.repo, ctx), | |
|
549 | branches=webutil.nodebranchdict(self.repo, ctx)) | |
|
597 | 550 | |
|
598 | 551 | def filelog(self, tmpl, fctx): |
|
599 | 552 | f = fctx.path() |
@@ -619,9 +572,9 b' class hgweb(object):' | |||
|
619 | 572 | "node": hex(ctx.node()), |
|
620 | 573 | "author": ctx.user(), |
|
621 | 574 | "date": ctx.date(), |
|
622 |
"rename": |
|
|
623 |
"parent": |
|
|
624 |
"child": |
|
|
575 | "rename": webutil.renamelink(fl, n), | |
|
576 | "parent": webutil.siblings(fctx.parents()), | |
|
577 | "child": webutil.siblings(fctx.children()), | |
|
625 | 578 | "desc": ctx.description()}) |
|
626 | 579 | |
|
627 | 580 | if limit > 0: |
@@ -663,10 +616,10 b' class hgweb(object):' | |||
|
663 | 616 | author=fctx.user(), |
|
664 | 617 | date=fctx.date(), |
|
665 | 618 | desc=fctx.description(), |
|
666 |
branch= |
|
|
667 |
parent= |
|
|
668 |
child= |
|
|
669 |
rename= |
|
|
619 | branch=webutil.nodebranchnodefault(fctx), | |
|
620 | parent=webutil.siblings(fctx.parents()), | |
|
621 | child=webutil.siblings(fctx.children()), | |
|
622 | rename=webutil.renamelink(fl, n), | |
|
670 | 623 | permissions=fctx.manifest().flags(f)) |
|
671 | 624 | |
|
672 | 625 | def fileannotate(self, tmpl, fctx): |
@@ -710,10 +663,10 b' class hgweb(object):' | |||
|
710 | 663 | author=fctx.user(), |
|
711 | 664 | date=fctx.date(), |
|
712 | 665 | desc=fctx.description(), |
|
713 |
rename= |
|
|
714 |
branch= |
|
|
715 |
parent= |
|
|
716 |
child= |
|
|
666 | rename=webutil.renamelink(fl, n), | |
|
667 | branch=webutil.nodebranchnodefault(fctx), | |
|
668 | parent=webutil.siblings(fctx.parents()), | |
|
669 | child=webutil.siblings(fctx.children()), | |
|
717 | 670 | permissions=fctx.manifest().flags(f)) |
|
718 | 671 | |
|
719 | 672 | def manifest(self, tmpl, ctx, path): |
@@ -779,9 +732,9 b' class hgweb(object):' | |||
|
779 | 732 | fentries=filelist, |
|
780 | 733 | dentries=dirlist, |
|
781 | 734 | archives=self.archivelist(hex(node)), |
|
782 |
tags= |
|
|
783 |
inbranch= |
|
|
784 |
branches= |
|
|
735 | tags=webutil.nodetagsdict(self.repo, node), | |
|
736 | inbranch=webutil.nodeinbranch(self.repo, ctx), | |
|
737 | branches=webutil.nodebranchdict(self.repo, ctx)) | |
|
785 | 738 | |
|
786 | 739 | def tags(self, tmpl): |
|
787 | 740 | i = self.repo.tagslist() |
@@ -860,9 +813,9 b' class hgweb(object):' | |||
|
860 | 813 | date=ctx.date(), |
|
861 | 814 | rev=i, |
|
862 | 815 | node=hn, |
|
863 |
tags= |
|
|
864 |
inbranch= |
|
|
865 |
branches= |
|
|
816 | tags=webutil.nodetagsdict(self.repo, n), | |
|
817 | inbranch=webutil.nodeinbranch(self.repo, ctx), | |
|
818 | branches=webutil.nodebranchdict(self.repo, ctx))) | |
|
866 | 819 | |
|
867 | 820 | yield l |
|
868 | 821 | |
@@ -894,9 +847,9 b' class hgweb(object):' | |||
|
894 | 847 | file=path, |
|
895 | 848 | node=hex(n), |
|
896 | 849 | rev=fctx.rev(), |
|
897 |
branch= |
|
|
898 |
parent= |
|
|
899 |
child= |
|
|
850 | branch=webutil.nodebranchnodefault(fctx), | |
|
851 | parent=webutil.siblings(parents), | |
|
852 | child=webutil.siblings(fctx.children()), | |
|
900 | 853 | diff=diff) |
|
901 | 854 | |
|
902 | 855 | archive_specs = { |
@@ -924,45 +877,6 b' class hgweb(object):' | |||
|
924 | 877 | req.respond(HTTP_OK) |
|
925 | 878 | archival.archive(self.repo, req, cnode, artype, prefix=name) |
|
926 | 879 | |
|
927 | # add tags to things | |
|
928 | # tags -> list of changesets corresponding to tags | |
|
929 | # find tag, changeset, file | |
|
930 | ||
|
931 | def cleanpath(self, path): | |
|
932 | path = path.lstrip('/') | |
|
933 | return util.canonpath(self.repo.root, '', path) | |
|
934 | ||
|
935 | def changectx(self, req): | |
|
936 | if 'node' in req.form: | |
|
937 | changeid = req.form['node'][0] | |
|
938 | elif 'manifest' in req.form: | |
|
939 | changeid = req.form['manifest'][0] | |
|
940 | else: | |
|
941 | changeid = self.repo.changelog.count() - 1 | |
|
942 | ||
|
943 | try: | |
|
944 | ctx = self.repo.changectx(changeid) | |
|
945 | except RepoError: | |
|
946 | man = self.repo.manifest | |
|
947 | mn = man.lookup(changeid) | |
|
948 | ctx = self.repo.changectx(man.linkrev(mn)) | |
|
949 | ||
|
950 | return ctx | |
|
951 | ||
|
952 | def filectx(self, req): | |
|
953 | path = self.cleanpath(req.form['file'][0]) | |
|
954 | if 'node' in req.form: | |
|
955 | changeid = req.form['node'][0] | |
|
956 | else: | |
|
957 | changeid = req.form['filenode'][0] | |
|
958 | try: | |
|
959 | ctx = self.repo.changectx(changeid) | |
|
960 | fctx = ctx.filectx(path) | |
|
961 | except RepoError: | |
|
962 | fctx = self.repo.filectx(path, fileid=changeid) | |
|
963 | ||
|
964 | return fctx | |
|
965 | ||
|
966 | 880 | def check_perm(self, req, op, default): |
|
967 | 881 | '''check permission for operation based on user auth. |
|
968 | 882 | return true if op allowed, else false. |
@@ -6,7 +6,9 b'' | |||
|
6 | 6 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | 7 | |
|
8 | 8 | import os, mimetypes |
|
9 | from mercurial import revlog, util | |
|
9 | import webutil | |
|
10 | from mercurial import revlog | |
|
11 | from mercurial.util import binary | |
|
10 | 12 | from mercurial.repo import RepoError |
|
11 | 13 | from common import staticfile, ErrorResponse, HTTP_OK, HTTP_NOT_FOUND |
|
12 | 14 | |
@@ -26,17 +28,17 b' def log(web, req, tmpl):' | |||
|
26 | 28 | return changelog(web, req, tmpl) |
|
27 | 29 | |
|
28 | 30 | def rawfile(web, req, tmpl): |
|
29 | path = web.cleanpath(req.form.get('file', [''])[0]) | |
|
31 | path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | |
|
30 | 32 | if not path: |
|
31 | content = web.manifest(tmpl, web.changectx(req), path) | |
|
33 | content = web.manifest(tmpl, webutil.changectx(web.repo, req), path) | |
|
32 | 34 | req.respond(HTTP_OK, web.ctype) |
|
33 | 35 | return content |
|
34 | 36 | |
|
35 | 37 | try: |
|
36 | fctx = web.filectx(req) | |
|
38 | fctx = webutil.filectx(web.repo, req) | |
|
37 | 39 | except revlog.LookupError, inst: |
|
38 | 40 | try: |
|
39 | content = web.manifest(tmpl, web.changectx(req), path) | |
|
41 | content = web.manifest(tmpl, webutil.changectx(web.repo, req), path) | |
|
40 | 42 | req.respond(HTTP_OK, web.ctype) |
|
41 | 43 | return content |
|
42 | 44 | except ErrorResponse: |
@@ -45,28 +47,28 b' def rawfile(web, req, tmpl):' | |||
|
45 | 47 | path = fctx.path() |
|
46 | 48 | text = fctx.data() |
|
47 | 49 | mt = mimetypes.guess_type(path)[0] |
|
48 |
if mt is None or |
|
|
50 | if mt is None or binary(text): | |
|
49 | 51 | mt = mt or 'application/octet-stream' |
|
50 | 52 | |
|
51 | 53 | req.respond(HTTP_OK, mt, path, len(text)) |
|
52 | 54 | return [text] |
|
53 | 55 | |
|
54 | 56 | def file(web, req, tmpl): |
|
55 | path = web.cleanpath(req.form.get('file', [''])[0]) | |
|
57 | path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0]) | |
|
56 | 58 | if path: |
|
57 | 59 | try: |
|
58 | return web.filerevision(tmpl, web.filectx(req)) | |
|
60 | return web.filerevision(tmpl, webutil.filectx(web.repo, req)) | |
|
59 | 61 | except revlog.LookupError, inst: |
|
60 | 62 | pass |
|
61 | 63 | |
|
62 | 64 | try: |
|
63 | return web.manifest(tmpl, web.changectx(req), path) | |
|
65 | return web.manifest(tmpl, webutil.changectx(web.repo, req), path) | |
|
64 | 66 | except ErrorResponse: |
|
65 | 67 | raise inst |
|
66 | 68 | |
|
67 | 69 | def changelog(web, req, tmpl, shortlog = False): |
|
68 | 70 | if 'node' in req.form: |
|
69 | ctx = web.changectx(req) | |
|
71 | ctx = webutil.changectx(web.repo, req) | |
|
70 | 72 | else: |
|
71 | 73 | if 'rev' in req.form: |
|
72 | 74 | hi = req.form['rev'][0] |
@@ -83,13 +85,13 b' def shortlog(web, req, tmpl):' | |||
|
83 | 85 | return changelog(web, req, tmpl, shortlog = True) |
|
84 | 86 | |
|
85 | 87 | def changeset(web, req, tmpl): |
|
86 | return web.changeset(tmpl, web.changectx(req)) | |
|
88 | return web.changeset(tmpl, webutil.changectx(web.repo, req)) | |
|
87 | 89 | |
|
88 | 90 | rev = changeset |
|
89 | 91 | |
|
90 | 92 | def manifest(web, req, tmpl): |
|
91 | return web.manifest(tmpl, web.changectx(req), | |
|
92 | web.cleanpath(req.form['path'][0])) | |
|
93 | return web.manifest(tmpl, webutil.changectx(web.repo, req), | |
|
94 | webutil.cleanpath(web.repo, req.form['path'][0])) | |
|
93 | 95 | |
|
94 | 96 | def tags(web, req, tmpl): |
|
95 | 97 | return web.tags(tmpl) |
@@ -98,15 +100,15 b' def summary(web, req, tmpl):' | |||
|
98 | 100 | return web.summary(tmpl) |
|
99 | 101 | |
|
100 | 102 | def filediff(web, req, tmpl): |
|
101 | return web.filediff(tmpl, web.filectx(req)) | |
|
103 | return web.filediff(tmpl, webutil.filectx(web.repo, req)) | |
|
102 | 104 | |
|
103 | 105 | diff = filediff |
|
104 | 106 | |
|
105 | 107 | def annotate(web, req, tmpl): |
|
106 | return web.fileannotate(tmpl, web.filectx(req)) | |
|
108 | return web.fileannotate(tmpl, webutil.filectx(web.repo, req)) | |
|
107 | 109 | |
|
108 | 110 | def filelog(web, req, tmpl): |
|
109 | return web.filelog(tmpl, web.filectx(req)) | |
|
111 | return web.filelog(tmpl, webutil.filectx(web.repo, req)) | |
|
110 | 112 | |
|
111 | 113 | def archive(web, req, tmpl): |
|
112 | 114 | type_ = req.form['type'][0] |
General Comments 0
You need to be logged in to leave comments.
Login now