##// END OF EJS Templates
hgweb: separate out utility functions
Dirkjan Ochtman -
r6392:2540521d default
parent child Browse files
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 from common import ErrorResponse
15 from common import ErrorResponse
16 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
16 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
17 from request import wsgirequest
17 from request import wsgirequest
18 import webcommands, protocol
18 import webcommands, protocol, webutil
19
19
20 shortcuts = {
20 shortcuts = {
21 'cl': [('cmd', ['changelog']), ('rev', None)],
21 'cl': [('cmd', ['changelog']), ('rev', None)],
@@ -340,54 +340,6 b' class hgweb(object):'
340 if len(files) > self.maxfiles:
340 if len(files) > self.maxfiles:
341 yield tmpl("fileellipses")
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 def diff(self, tmpl, node1, node2, files):
343 def diff(self, tmpl, node1, node2, files):
392 def filterfiles(filters, files):
344 def filterfiles(filters, files):
393 l = [x for x in files if x in filters]
345 l = [x for x in files if x in filters]
@@ -462,21 +414,22 b' class hgweb(object):'
462 for i in xrange(start, end):
414 for i in xrange(start, end):
463 ctx = self.repo.changectx(i)
415 ctx = self.repo.changectx(i)
464 n = ctx.node()
416 n = ctx.node()
465 showtags = self.showtag(tmpl, 'changelogtag', n)
417 showtags = webutil.showtag(self.repo, tmpl, 'changelogtag', n)
466
418
467 l.insert(0, {"parity": parity.next(),
419 l.insert(0, {"parity": parity.next(),
468 "author": ctx.user(),
420 "author": ctx.user(),
469 "parent": self.siblings(ctx.parents(), i - 1),
421 "parent": webutil.siblings(ctx.parents(), i - 1),
470 "child": self.siblings(ctx.children(), i + 1),
422 "child": webutil.siblings(ctx.children(), i + 1),
471 "changelogtag": showtags,
423 "changelogtag": showtags,
472 "desc": ctx.description(),
424 "desc": ctx.description(),
473 "date": ctx.date(),
425 "date": ctx.date(),
474 "files": self.listfilediffs(tmpl, ctx.files(), n),
426 "files": self.listfilediffs(tmpl, ctx.files(), n),
475 "rev": i,
427 "rev": i,
476 "node": hex(n),
428 "node": hex(n),
477 "tags": self.nodetagsdict(n),
429 "tags": webutil.nodetagsdict(self.repo, n),
478 "inbranch": self.nodeinbranch(ctx),
430 "inbranch": webutil.nodeinbranch(self.repo, ctx),
479 "branches": self.nodebranchdict(ctx)})
431 "branches": webutil.nodebranchdict(self.repo, ctx)
432 })
480
433
481 if limit > 0:
434 if limit > 0:
482 l = l[:limit]
435 l = l[:limit]
@@ -533,22 +486,22 b' class hgweb(object):'
533
486
534 count += 1
487 count += 1
535 n = ctx.node()
488 n = ctx.node()
536 showtags = self.showtag(tmpl, 'changelogtag', n)
489 showtags = webutil.showtag(self.repo, tmpl, 'changelogtag', n)
537
490
538 yield tmpl('searchentry',
491 yield tmpl('searchentry',
539 parity=parity.next(),
492 parity=parity.next(),
540 author=ctx.user(),
493 author=ctx.user(),
541 parent=self.siblings(ctx.parents()),
494 parent=webutil.siblings(ctx.parents()),
542 child=self.siblings(ctx.children()),
495 child=webutil.siblings(ctx.children()),
543 changelogtag=showtags,
496 changelogtag=showtags,
544 desc=ctx.description(),
497 desc=ctx.description(),
545 date=ctx.date(),
498 date=ctx.date(),
546 files=self.listfilediffs(tmpl, ctx.files(), n),
499 files=self.listfilediffs(tmpl, ctx.files(), n),
547 rev=ctx.rev(),
500 rev=ctx.rev(),
548 node=hex(n),
501 node=hex(n),
549 tags=self.nodetagsdict(n),
502 tags=webutil.nodetagsdict(self.repo, n),
550 inbranch=self.nodeinbranch(ctx),
503 inbranch=webutil.nodeinbranch(self.repo, ctx),
551 branches=self.nodebranchdict(ctx))
504 branches=webutil.nodebranchdict(self.repo, ctx))
552
505
553 if count >= self.maxchanges:
506 if count >= self.maxchanges:
554 break
507 break
@@ -564,7 +517,7 b' class hgweb(object):'
564
517
565 def changeset(self, tmpl, ctx):
518 def changeset(self, tmpl, ctx):
566 n = ctx.node()
519 n = ctx.node()
567 showtags = self.showtag(tmpl, 'changesettag', n)
520 showtags = webutil.showtag(self.repo, tmpl, 'changesettag', n)
568 parents = ctx.parents()
521 parents = ctx.parents()
569 p1 = parents[0].node()
522 p1 = parents[0].node()
570
523
@@ -582,18 +535,18 b' class hgweb(object):'
582 diff=diff,
535 diff=diff,
583 rev=ctx.rev(),
536 rev=ctx.rev(),
584 node=hex(n),
537 node=hex(n),
585 parent=self.siblings(parents),
538 parent=webutil.siblings(parents),
586 child=self.siblings(ctx.children()),
539 child=webutil.siblings(ctx.children()),
587 changesettag=showtags,
540 changesettag=showtags,
588 author=ctx.user(),
541 author=ctx.user(),
589 desc=ctx.description(),
542 desc=ctx.description(),
590 date=ctx.date(),
543 date=ctx.date(),
591 files=files,
544 files=files,
592 archives=self.archivelist(hex(n)),
545 archives=self.archivelist(hex(n)),
593 tags=self.nodetagsdict(n),
546 tags=webutil.nodetagsdict(self.repo, n),
594 branch=self.nodebranchnodefault(ctx),
547 branch=webutil.nodebranchnodefault(ctx),
595 inbranch=self.nodeinbranch(ctx),
548 inbranch=webutil.nodeinbranch(self.repo, ctx),
596 branches=self.nodebranchdict(ctx))
549 branches=webutil.nodebranchdict(self.repo, ctx))
597
550
598 def filelog(self, tmpl, fctx):
551 def filelog(self, tmpl, fctx):
599 f = fctx.path()
552 f = fctx.path()
@@ -619,9 +572,9 b' class hgweb(object):'
619 "node": hex(ctx.node()),
572 "node": hex(ctx.node()),
620 "author": ctx.user(),
573 "author": ctx.user(),
621 "date": ctx.date(),
574 "date": ctx.date(),
622 "rename": self.renamelink(fl, n),
575 "rename": webutil.renamelink(fl, n),
623 "parent": self.siblings(fctx.parents()),
576 "parent": webutil.siblings(fctx.parents()),
624 "child": self.siblings(fctx.children()),
577 "child": webutil.siblings(fctx.children()),
625 "desc": ctx.description()})
578 "desc": ctx.description()})
626
579
627 if limit > 0:
580 if limit > 0:
@@ -663,10 +616,10 b' class hgweb(object):'
663 author=fctx.user(),
616 author=fctx.user(),
664 date=fctx.date(),
617 date=fctx.date(),
665 desc=fctx.description(),
618 desc=fctx.description(),
666 branch=self.nodebranchnodefault(fctx),
619 branch=webutil.nodebranchnodefault(fctx),
667 parent=self.siblings(fctx.parents()),
620 parent=webutil.siblings(fctx.parents()),
668 child=self.siblings(fctx.children()),
621 child=webutil.siblings(fctx.children()),
669 rename=self.renamelink(fl, n),
622 rename=webutil.renamelink(fl, n),
670 permissions=fctx.manifest().flags(f))
623 permissions=fctx.manifest().flags(f))
671
624
672 def fileannotate(self, tmpl, fctx):
625 def fileannotate(self, tmpl, fctx):
@@ -710,10 +663,10 b' class hgweb(object):'
710 author=fctx.user(),
663 author=fctx.user(),
711 date=fctx.date(),
664 date=fctx.date(),
712 desc=fctx.description(),
665 desc=fctx.description(),
713 rename=self.renamelink(fl, n),
666 rename=webutil.renamelink(fl, n),
714 branch=self.nodebranchnodefault(fctx),
667 branch=webutil.nodebranchnodefault(fctx),
715 parent=self.siblings(fctx.parents()),
668 parent=webutil.siblings(fctx.parents()),
716 child=self.siblings(fctx.children()),
669 child=webutil.siblings(fctx.children()),
717 permissions=fctx.manifest().flags(f))
670 permissions=fctx.manifest().flags(f))
718
671
719 def manifest(self, tmpl, ctx, path):
672 def manifest(self, tmpl, ctx, path):
@@ -779,9 +732,9 b' class hgweb(object):'
779 fentries=filelist,
732 fentries=filelist,
780 dentries=dirlist,
733 dentries=dirlist,
781 archives=self.archivelist(hex(node)),
734 archives=self.archivelist(hex(node)),
782 tags=self.nodetagsdict(node),
735 tags=webutil.nodetagsdict(self.repo, node),
783 inbranch=self.nodeinbranch(ctx),
736 inbranch=webutil.nodeinbranch(self.repo, ctx),
784 branches=self.nodebranchdict(ctx))
737 branches=webutil.nodebranchdict(self.repo, ctx))
785
738
786 def tags(self, tmpl):
739 def tags(self, tmpl):
787 i = self.repo.tagslist()
740 i = self.repo.tagslist()
@@ -860,9 +813,9 b' class hgweb(object):'
860 date=ctx.date(),
813 date=ctx.date(),
861 rev=i,
814 rev=i,
862 node=hn,
815 node=hn,
863 tags=self.nodetagsdict(n),
816 tags=webutil.nodetagsdict(self.repo, n),
864 inbranch=self.nodeinbranch(ctx),
817 inbranch=webutil.nodeinbranch(self.repo, ctx),
865 branches=self.nodebranchdict(ctx)))
818 branches=webutil.nodebranchdict(self.repo, ctx)))
866
819
867 yield l
820 yield l
868
821
@@ -894,9 +847,9 b' class hgweb(object):'
894 file=path,
847 file=path,
895 node=hex(n),
848 node=hex(n),
896 rev=fctx.rev(),
849 rev=fctx.rev(),
897 branch=self.nodebranchnodefault(fctx),
850 branch=webutil.nodebranchnodefault(fctx),
898 parent=self.siblings(parents),
851 parent=webutil.siblings(parents),
899 child=self.siblings(fctx.children()),
852 child=webutil.siblings(fctx.children()),
900 diff=diff)
853 diff=diff)
901
854
902 archive_specs = {
855 archive_specs = {
@@ -924,45 +877,6 b' class hgweb(object):'
924 req.respond(HTTP_OK)
877 req.respond(HTTP_OK)
925 archival.archive(self.repo, req, cnode, artype, prefix=name)
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 def check_perm(self, req, op, default):
880 def check_perm(self, req, op, default):
967 '''check permission for operation based on user auth.
881 '''check permission for operation based on user auth.
968 return true if op allowed, else false.
882 return true if op allowed, else false.
@@ -6,7 +6,9 b''
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os, mimetypes
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 from mercurial.repo import RepoError
12 from mercurial.repo import RepoError
11 from common import staticfile, ErrorResponse, HTTP_OK, HTTP_NOT_FOUND
13 from common import staticfile, ErrorResponse, HTTP_OK, HTTP_NOT_FOUND
12
14
@@ -26,17 +28,17 b' def log(web, req, tmpl):'
26 return changelog(web, req, tmpl)
28 return changelog(web, req, tmpl)
27
29
28 def rawfile(web, req, tmpl):
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 if not path:
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 req.respond(HTTP_OK, web.ctype)
34 req.respond(HTTP_OK, web.ctype)
33 return content
35 return content
34
36
35 try:
37 try:
36 fctx = web.filectx(req)
38 fctx = webutil.filectx(web.repo, req)
37 except revlog.LookupError, inst:
39 except revlog.LookupError, inst:
38 try:
40 try:
39 content = web.manifest(tmpl, web.changectx(req), path)
41 content = web.manifest(tmpl, webutil.changectx(web.repo, req), path)
40 req.respond(HTTP_OK, web.ctype)
42 req.respond(HTTP_OK, web.ctype)
41 return content
43 return content
42 except ErrorResponse:
44 except ErrorResponse:
@@ -45,28 +47,28 b' def rawfile(web, req, tmpl):'
45 path = fctx.path()
47 path = fctx.path()
46 text = fctx.data()
48 text = fctx.data()
47 mt = mimetypes.guess_type(path)[0]
49 mt = mimetypes.guess_type(path)[0]
48 if mt is None or util.binary(text):
50 if mt is None or binary(text):
49 mt = mt or 'application/octet-stream'
51 mt = mt or 'application/octet-stream'
50
52
51 req.respond(HTTP_OK, mt, path, len(text))
53 req.respond(HTTP_OK, mt, path, len(text))
52 return [text]
54 return [text]
53
55
54 def file(web, req, tmpl):
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 if path:
58 if path:
57 try:
59 try:
58 return web.filerevision(tmpl, web.filectx(req))
60 return web.filerevision(tmpl, webutil.filectx(web.repo, req))
59 except revlog.LookupError, inst:
61 except revlog.LookupError, inst:
60 pass
62 pass
61
63
62 try:
64 try:
63 return web.manifest(tmpl, web.changectx(req), path)
65 return web.manifest(tmpl, webutil.changectx(web.repo, req), path)
64 except ErrorResponse:
66 except ErrorResponse:
65 raise inst
67 raise inst
66
68
67 def changelog(web, req, tmpl, shortlog = False):
69 def changelog(web, req, tmpl, shortlog = False):
68 if 'node' in req.form:
70 if 'node' in req.form:
69 ctx = web.changectx(req)
71 ctx = webutil.changectx(web.repo, req)
70 else:
72 else:
71 if 'rev' in req.form:
73 if 'rev' in req.form:
72 hi = req.form['rev'][0]
74 hi = req.form['rev'][0]
@@ -83,13 +85,13 b' def shortlog(web, req, tmpl):'
83 return changelog(web, req, tmpl, shortlog = True)
85 return changelog(web, req, tmpl, shortlog = True)
84
86
85 def changeset(web, req, tmpl):
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 rev = changeset
90 rev = changeset
89
91
90 def manifest(web, req, tmpl):
92 def manifest(web, req, tmpl):
91 return web.manifest(tmpl, web.changectx(req),
93 return web.manifest(tmpl, webutil.changectx(web.repo, req),
92 web.cleanpath(req.form['path'][0]))
94 webutil.cleanpath(web.repo, req.form['path'][0]))
93
95
94 def tags(web, req, tmpl):
96 def tags(web, req, tmpl):
95 return web.tags(tmpl)
97 return web.tags(tmpl)
@@ -98,15 +100,15 b' def summary(web, req, tmpl):'
98 return web.summary(tmpl)
100 return web.summary(tmpl)
99
101
100 def filediff(web, req, tmpl):
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 diff = filediff
105 diff = filediff
104
106
105 def annotate(web, req, tmpl):
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 def filelog(web, req, tmpl):
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 def archive(web, req, tmpl):
113 def archive(web, req, tmpl):
112 type_ = req.form['type'][0]
114 type_ = req.form['type'][0]
General Comments 0
You need to be logged in to leave comments. Login now