[PATCH 01 of 22 hgweb-help] webcommands: define web commands using a decorator

Gregory Szorc gregory.szorc at gmail.com
Sat Feb 7 07:15:39 UTC 2015


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1423278377 28800
#      Fri Feb 06 19:06:17 2015 -0800
# Node ID a54bf6a609310887f4fa824579b9db3e29b3e550
# Parent  ff5caa8dfd993680d9602ca6ebb14da9de10d5f4
webcommands: define web commands using a decorator

Other parts of Mercurial have evolved to use decorators to declare
commands or handlers. This patch gives the same treatment to web
commands.

diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -21,20 +21,38 @@ from mercurial import revset
 
 # __all__ is populated with the allowed commands. Be sure to add to it if
 # you're adding a new command, or the new command won't work.
 
-__all__ = [
-   'log', 'rawfile', 'file', 'changelog', 'shortlog', 'changeset', 'rev',
-   'manifest', 'tags', 'bookmarks', 'branches', 'summary', 'filediff', 'diff',
-   'comparison', 'annotate', 'filelog', 'archive', 'static', 'graph', 'help',
-]
+__all__ = []
 
+class webcommand(object):
+    """Decorator used to register a web command handler.
+
+    The decorator takes as its positional arguments the name/path the
+    command should be accessible under.
+
+    Usage:
+
+    @webcommand('mycommand')
+    def mycommand(web, req, tmpl):
+        pass
+    """
+
+    def __init__(self, name):
+        self.name = name
+
+    def __call__(self, func):
+        __all__.append(self.name)
+        return func
+
+ at webcommand('log')
 def log(web, req, tmpl):
     if 'file' in req.form and req.form['file'][0]:
         return filelog(web, req, tmpl)
     else:
         return changelog(web, req, tmpl)
 
+ at webcommand('rawfile')
 def rawfile(web, req, tmpl):
     guessmime = web.configbool('web', 'guessmime', False)
 
     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
@@ -97,8 +115,9 @@ def _filerevision(web, tmpl, fctx):
                 child=webutil.children(fctx),
                 rename=webutil.renamelink(fctx),
                 permissions=fctx.manifest().flags(f))
 
+ at webcommand('file')
 def file(web, req, tmpl):
     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
     if not path:
         return manifest(web, req, tmpl)
@@ -266,8 +285,9 @@ def _search(web, req, tmpl):
                 morevars=morevars, lessvars=lessvars,
                 modedesc=searchfunc[1],
                 showforcekw=showforcekw, showunforcekw=showunforcekw)
 
+ at webcommand('changelog')
 def changelog(web, req, tmpl, shortlog=False):
 
     query = ''
     if 'node' in req.form:
@@ -325,11 +345,13 @@ def changelog(web, req, tmpl, shortlog=F
                 latestentry=latestentry, nextentry=nextentry,
                 archives=web.archivelist("tip"), revcount=revcount,
                 morevars=morevars, lessvars=lessvars, query=query)
 
+ at webcommand('shortlog')
 def shortlog(web, req, tmpl):
     return changelog(web, req, tmpl, shortlog=True)
 
+ at webcommand('changeset')
 def changeset(web, req, tmpl):
     ctx = webutil.changectx(web.repo, req)
     basectx = webutil.basechangectx(web.repo, req)
     if basectx is None:
@@ -381,9 +403,9 @@ def changeset(web, req, tmpl):
                 branch=webutil.nodebranchnodefault(ctx),
                 inbranch=webutil.nodeinbranch(web.repo, ctx),
                 branches=webutil.nodebranchdict(web.repo, ctx))
 
-rev = changeset
+rev = webcommand('rev')(changeset)
 
 def decodepath(path):
     """Hook for mapping a path in the repository to a path in the
     working copy.
@@ -391,8 +413,9 @@ def decodepath(path):
     Extensions (e.g., largefiles) can override this to remap files in
     the virtual file system presented by the manifest command below."""
     return path
 
+ at webcommand('manifest')
 def manifest(web, req, tmpl):
     ctx = webutil.changectx(web.repo, req)
     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
     mf = ctx.manifest()
@@ -473,8 +496,9 @@ def manifest(web, req, tmpl):
                 bookmarks=webutil.nodebookmarksdict(web.repo, node),
                 inbranch=webutil.nodeinbranch(web.repo, ctx),
                 branches=webutil.nodebranchdict(web.repo, ctx))
 
+ at webcommand('tags')
 def tags(web, req, tmpl):
     i = list(reversed(web.repo.tagslist()))
     parity = paritygen(web.stripecount)
 
@@ -495,8 +519,9 @@ def tags(web, req, tmpl):
                 entries=lambda **x: entries(False, False, **x),
                 entriesnotip=lambda **x: entries(True, False, **x),
                 latestentry=lambda **x: entries(True, True, **x))
 
+ at webcommand('bookmarks')
 def bookmarks(web, req, tmpl):
     i = [b for b in web.repo._bookmarks.items() if b[1] in web.repo]
     parity = paritygen(web.stripecount)
 
@@ -515,8 +540,9 @@ def bookmarks(web, req, tmpl):
                 node=hex(web.repo.changelog.tip()),
                 entries=lambda **x: entries(latestonly=False, **x),
                 latestentry=lambda **x: entries(latestonly=True, **x))
 
+ at webcommand('branches')
 def branches(web, req, tmpl):
     tips = []
     heads = web.repo.heads()
     parity = paritygen(web.stripecount)
@@ -546,8 +572,9 @@ def branches(web, req, tmpl):
     return tmpl('branches', node=hex(web.repo.changelog.tip()),
                 entries=lambda **x: entries(0, **x),
                 latestentry=lambda **x: entries(1, **x))
 
+ at webcommand('summary')
 def summary(web, req, tmpl):
     i = reversed(web.repo.tagslist())
 
     def tagentries(**map):
@@ -631,8 +658,9 @@ def summary(web, req, tmpl):
                 shortlog=changelist,
                 node=tip.hex(),
                 archives=web.archivelist("tip"))
 
+ at webcommand('filediff')
 def filediff(web, req, tmpl):
     fctx, ctx = None, None
     try:
         fctx = webutil.filectx(web.repo, req)
@@ -671,10 +699,11 @@ def filediff(web, req, tmpl):
                 parent=webutil.parents(ctx),
                 child=webutil.children(ctx),
                 diff=diffs)
 
-diff = filediff
+diff = webcommand('diff')(filediff)
 
+ at webcommand('comparison')
 def comparison(web, req, tmpl):
     ctx = webutil.changectx(web.repo, req)
     if 'file' not in req.form:
         raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
@@ -731,8 +760,9 @@ def comparison(web, req, tmpl):
                 rightrev=rightrev,
                 rightnode=hex(rightnode),
                 comparison=comparison)
 
+ at webcommand('annotate')
 def annotate(web, req, tmpl):
     fctx = webutil.filectx(web.repo, req)
     f = fctx.path()
     parity = paritygen(web.stripecount)
@@ -783,8 +813,9 @@ def annotate(web, req, tmpl):
                 parent=webutil.parents(fctx),
                 child=webutil.children(fctx),
                 permissions=fctx.manifest().flags(f))
 
+ at webcommand('filelog')
 def filelog(web, req, tmpl):
 
     try:
         fctx = webutil.filectx(web.repo, req)
@@ -861,8 +892,9 @@ def filelog(web, req, tmpl):
                 entries=entries,
                 latestentry=latestentry,
                 revcount=revcount, morevars=morevars, lessvars=lessvars)
 
+ at webcommand('archive')
 def archive(web, req, tmpl):
     type_ = req.form.get('type', [None])[0]
     allowed = web.configlist("web", "allow_archive")
     key = req.form['node'][0]
@@ -910,8 +942,9 @@ def archive(web, req, tmpl):
                      subrepos=web.configbool("web", "archivesubrepos"))
     return []
 
 
+ at webcommand('static')
 def static(web, req, tmpl):
     fname = req.form['file'][0]
     # a repo owner may set web.static in .hg/hgrc to get any file
     # readable by the user running the CGI script
@@ -923,8 +956,9 @@ def static(web, req, tmpl):
         static = [os.path.join(p, 'static') for p in tp]
     staticfile(static, fname, req)
     return []
 
+ at webcommand('graph')
 def graph(web, req, tmpl):
 
     ctx = webutil.changectx(web.repo, req)
     rev = ctx.rev()
@@ -1046,8 +1080,9 @@ def _getdoc(e):
     else:
         doc = _('(no help text available)')
     return doc
 
+ at webcommand('help')
 def help(web, req, tmpl):
     from mercurial import commands # avoid cycle
 
     topicname = req.form.get('node', [None])[0]


More information about the Mercurial-devel mailing list