mercurial/hgweb/webcommands.py
changeset 36871 3d60a22e27f5
parent 36869 1a1972b1a1ff
child 36876 1f42d621f090
equal deleted inserted replaced
36870:4e06e8336634 36871:3d60a22e27f5
    83 
    83 
    84     For URLs of the form ``/log/{revision}/{file}``, the history for a specific
    84     For URLs of the form ``/log/{revision}/{file}``, the history for a specific
    85     file will be shown. This form is equivalent to the ``filelog`` handler.
    85     file will be shown. This form is equivalent to the ``filelog`` handler.
    86     """
    86     """
    87 
    87 
    88     if 'file' in req.form and req.form['file'][0]:
    88     if req.req.qsparams.get('file'):
    89         return filelog(web, req, tmpl)
    89         return filelog(web, req, tmpl)
    90     else:
    90     else:
    91         return changelog(web, req, tmpl)
    91         return changelog(web, req, tmpl)
    92 
    92 
    93 @webcommand('rawfile')
    93 @webcommand('rawfile')
    94 def rawfile(web, req, tmpl):
    94 def rawfile(web, req, tmpl):
    95     guessmime = web.configbool('web', 'guessmime')
    95     guessmime = web.configbool('web', 'guessmime')
    96 
    96 
    97     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
    97     path = webutil.cleanpath(web.repo, req.req.qsparams.get('file', ''))
    98     if not path:
    98     if not path:
    99         content = manifest(web, req, tmpl)
    99         content = manifest(web, req, tmpl)
   100         req.respond(HTTP_OK, web.ctype)
   100         req.respond(HTTP_OK, web.ctype)
   101         return content
   101         return content
   102 
   102 
   171     the ``filerevision`` template.
   171     the ``filerevision`` template.
   172 
   172 
   173     If ``path`` is not defined, information about the root directory will
   173     If ``path`` is not defined, information about the root directory will
   174     be rendered.
   174     be rendered.
   175     """
   175     """
   176     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
   176     path = webutil.cleanpath(web.repo, req.req.qsparams.get('file', ''))
   177     if not path:
   177     if not path:
   178         return manifest(web, req, tmpl)
   178         return manifest(web, req, tmpl)
   179     try:
   179     try:
   180         return _filerevision(web, req, tmpl, webutil.filectx(web.repo, req))
   180         return _filerevision(web, req, tmpl, webutil.filectx(web.repo, req))
   181     except error.LookupError as inst:
   181     except error.LookupError as inst:
   287                        **pycompat.strkwargs(webutil.commonentry(web.repo, ctx)))
   287                        **pycompat.strkwargs(webutil.commonentry(web.repo, ctx)))
   288 
   288 
   289             if count >= revcount:
   289             if count >= revcount:
   290                 break
   290                 break
   291 
   291 
   292     query = req.form['rev'][0]
   292     query = req.req.qsparams['rev']
   293     revcount = web.maxchanges
   293     revcount = web.maxchanges
   294     if 'revcount' in req.form:
   294     if 'revcount' in req.req.qsparams:
   295         try:
   295         try:
   296             revcount = int(req.form.get('revcount', [revcount])[0])
   296             revcount = int(req.req.qsparams.get('revcount', revcount))
   297             revcount = max(revcount, 1)
   297             revcount = max(revcount, 1)
   298             tmpl.defaults['sessionvars']['revcount'] = revcount
   298             tmpl.defaults['sessionvars']['revcount'] = revcount
   299         except ValueError:
   299         except ValueError:
   300             pass
   300             pass
   301 
   301 
   306     morevars['revcount'] = revcount * 2
   306     morevars['revcount'] = revcount * 2
   307     morevars['rev'] = query
   307     morevars['rev'] = query
   308 
   308 
   309     mode, funcarg = getsearchmode(query)
   309     mode, funcarg = getsearchmode(query)
   310 
   310 
   311     if 'forcekw' in req.form:
   311     if 'forcekw' in req.req.qsparams:
   312         showforcekw = ''
   312         showforcekw = ''
   313         showunforcekw = searchfuncs[mode][1]
   313         showunforcekw = searchfuncs[mode][1]
   314         mode = MODE_KEYWORD
   314         mode = MODE_KEYWORD
   315         funcarg = query
   315         funcarg = query
   316     else:
   316     else:
   356 
   356 
   357     For non-searches, the ``changelog`` template will be rendered.
   357     For non-searches, the ``changelog`` template will be rendered.
   358     """
   358     """
   359 
   359 
   360     query = ''
   360     query = ''
   361     if 'node' in req.form:
   361     if 'node' in req.req.qsparams:
   362         ctx = webutil.changectx(web.repo, req)
   362         ctx = webutil.changectx(web.repo, req)
   363         symrev = webutil.symrevorshortnode(req, ctx)
   363         symrev = webutil.symrevorshortnode(req, ctx)
   364     elif 'rev' in req.form:
   364     elif 'rev' in req.req.qsparams:
   365         return _search(web, req, tmpl)
   365         return _search(web, req, tmpl)
   366     else:
   366     else:
   367         ctx = web.repo['tip']
   367         ctx = web.repo['tip']
   368         symrev = 'tip'
   368         symrev = 'tip'
   369 
   369 
   384     if shortlog:
   384     if shortlog:
   385         revcount = web.maxshortchanges
   385         revcount = web.maxshortchanges
   386     else:
   386     else:
   387         revcount = web.maxchanges
   387         revcount = web.maxchanges
   388 
   388 
   389     if 'revcount' in req.form:
   389     if 'revcount' in req.req.qsparams:
   390         try:
   390         try:
   391             revcount = int(req.form.get('revcount', [revcount])[0])
   391             revcount = int(req.req.qsparams.get('revcount', revcount))
   392             revcount = max(revcount, 1)
   392             revcount = max(revcount, 1)
   393             tmpl.defaults['sessionvars']['revcount'] = revcount
   393             tmpl.defaults['sessionvars']['revcount'] = revcount
   394         except ValueError:
   394         except ValueError:
   395             pass
   395             pass
   396 
   396 
   479     is recommended to use the ``file`` handler instead, as it can handle both
   479     is recommended to use the ``file`` handler instead, as it can handle both
   480     directories and files.
   480     directories and files.
   481 
   481 
   482     The ``manifest`` template will be rendered for this handler.
   482     The ``manifest`` template will be rendered for this handler.
   483     """
   483     """
   484     if 'node' in req.form:
   484     if 'node' in req.req.qsparams:
   485         ctx = webutil.changectx(web.repo, req)
   485         ctx = webutil.changectx(web.repo, req)
   486         symrev = webutil.symrevorshortnode(req, ctx)
   486         symrev = webutil.symrevorshortnode(req, ctx)
   487     else:
   487     else:
   488         ctx = web.repo['tip']
   488         ctx = web.repo['tip']
   489         symrev = 'tip'
   489         symrev = 'tip'
   490     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
   490     path = webutil.cleanpath(web.repo, req.req.qsparams.get('file', ''))
   491     mf = ctx.manifest()
   491     mf = ctx.manifest()
   492     node = ctx.node()
   492     node = ctx.node()
   493 
   493 
   494     files = {}
   494     files = {}
   495     dirs = {}
   495     dirs = {}
   750     fctx, ctx = None, None
   750     fctx, ctx = None, None
   751     try:
   751     try:
   752         fctx = webutil.filectx(web.repo, req)
   752         fctx = webutil.filectx(web.repo, req)
   753     except LookupError:
   753     except LookupError:
   754         ctx = webutil.changectx(web.repo, req)
   754         ctx = webutil.changectx(web.repo, req)
   755         path = webutil.cleanpath(web.repo, req.form['file'][0])
   755         path = webutil.cleanpath(web.repo, req.req.qsparams['file'])
   756         if path not in ctx.files():
   756         if path not in ctx.files():
   757             raise
   757             raise
   758 
   758 
   759     if fctx is not None:
   759     if fctx is not None:
   760         path = fctx.path()
   760         path = fctx.path()
   797     context in the diff.
   797     context in the diff.
   798 
   798 
   799     The ``filecomparison`` template is rendered.
   799     The ``filecomparison`` template is rendered.
   800     """
   800     """
   801     ctx = webutil.changectx(web.repo, req)
   801     ctx = webutil.changectx(web.repo, req)
   802     if 'file' not in req.form:
   802     if 'file' not in req.req.qsparams:
   803         raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
   803         raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
   804     path = webutil.cleanpath(web.repo, req.form['file'][0])
   804     path = webutil.cleanpath(web.repo, req.req.qsparams['file'])
   805 
   805 
   806     parsecontext = lambda v: v == 'full' and -1 or int(v)
   806     parsecontext = lambda v: v == 'full' and -1 or int(v)
   807     if 'context' in req.form:
   807     if 'context' in req.req.qsparams:
   808         context = parsecontext(req.form['context'][0])
   808         context = parsecontext(req.req.qsparams['context'])
   809     else:
   809     else:
   810         context = parsecontext(web.config('web', 'comparisoncontext', '5'))
   810         context = parsecontext(web.config('web', 'comparisoncontext', '5'))
   811 
   811 
   812     def filelines(f):
   812     def filelines(f):
   813         if f.isbinary():
   813         if f.isbinary():
   962     try:
   962     try:
   963         fctx = webutil.filectx(web.repo, req)
   963         fctx = webutil.filectx(web.repo, req)
   964         f = fctx.path()
   964         f = fctx.path()
   965         fl = fctx.filelog()
   965         fl = fctx.filelog()
   966     except error.LookupError:
   966     except error.LookupError:
   967         f = webutil.cleanpath(web.repo, req.form['file'][0])
   967         f = webutil.cleanpath(web.repo, req.req.qsparams['file'])
   968         fl = web.repo.file(f)
   968         fl = web.repo.file(f)
   969         numrevs = len(fl)
   969         numrevs = len(fl)
   970         if not numrevs: # file doesn't exist at all
   970         if not numrevs: # file doesn't exist at all
   971             raise
   971             raise
   972         rev = webutil.changectx(web.repo, req).rev()
   972         rev = webutil.changectx(web.repo, req).rev()
   977         while fl.linkrev(frev) > rev:
   977         while fl.linkrev(frev) > rev:
   978             frev -= 1
   978             frev -= 1
   979         fctx = web.repo.filectx(f, fl.linkrev(frev))
   979         fctx = web.repo.filectx(f, fl.linkrev(frev))
   980 
   980 
   981     revcount = web.maxshortchanges
   981     revcount = web.maxshortchanges
   982     if 'revcount' in req.form:
   982     if 'revcount' in req.req.qsparams:
   983         try:
   983         try:
   984             revcount = int(req.form.get('revcount', [revcount])[0])
   984             revcount = int(req.req.qsparams.get('revcount', revcount))
   985             revcount = max(revcount, 1)
   985             revcount = max(revcount, 1)
   986             tmpl.defaults['sessionvars']['revcount'] = revcount
   986             tmpl.defaults['sessionvars']['revcount'] = revcount
   987         except ValueError:
   987         except ValueError:
   988             pass
   988             pass
   989 
   989 
   992     lessvars = copy.copy(tmpl.defaults['sessionvars'])
   992     lessvars = copy.copy(tmpl.defaults['sessionvars'])
   993     lessvars['revcount'] = max(revcount // 2, 1)
   993     lessvars['revcount'] = max(revcount // 2, 1)
   994     morevars = copy.copy(tmpl.defaults['sessionvars'])
   994     morevars = copy.copy(tmpl.defaults['sessionvars'])
   995     morevars['revcount'] = revcount * 2
   995     morevars['revcount'] = revcount * 2
   996 
   996 
   997     patch = 'patch' in req.form
   997     patch = 'patch' in req.req.qsparams
   998     if patch:
   998     if patch:
   999         lessvars['patch'] = morevars['patch'] = req.form['patch'][0]
   999         lessvars['patch'] = morevars['patch'] = req.req.qsparams['patch']
  1000     descend = 'descend' in req.form
  1000     descend = 'descend' in req.req.qsparams
  1001     if descend:
  1001     if descend:
  1002         lessvars['descend'] = morevars['descend'] = req.form['descend'][0]
  1002         lessvars['descend'] = morevars['descend'] = req.req.qsparams['descend']
  1003 
  1003 
  1004     count = fctx.filerev() + 1
  1004     count = fctx.filerev() + 1
  1005     start = max(0, count - revcount) # first rev on this page
  1005     start = max(0, count - revcount) # first rev on this page
  1006     end = min(count, start + revcount) # last rev on this page
  1006     end = min(count, start + revcount) # last rev on this page
  1007     parity = paritygen(web.stripecount, offset=start - end)
  1007     parity = paritygen(web.stripecount, offset=start - end)
  1101     directory will be included in the archive.
  1101     directory will be included in the archive.
  1102 
  1102 
  1103     No template is used for this handler. Raw, binary content is generated.
  1103     No template is used for this handler. Raw, binary content is generated.
  1104     """
  1104     """
  1105 
  1105 
  1106     type_ = req.form.get('type', [None])[0]
  1106     type_ = req.req.qsparams.get('type')
  1107     allowed = web.configlist("web", "allow_archive")
  1107     allowed = web.configlist("web", "allow_archive")
  1108     key = req.form['node'][0]
  1108     key = req.req.qsparams['node']
  1109 
  1109 
  1110     if type_ not in web.archivespecs:
  1110     if type_ not in web.archivespecs:
  1111         msg = 'Unsupported archive type: %s' % type_
  1111         msg = 'Unsupported archive type: %s' % type_
  1112         raise ErrorResponse(HTTP_NOT_FOUND, msg)
  1112         raise ErrorResponse(HTTP_NOT_FOUND, msg)
  1113 
  1113 
  1124     name = "%s-%s" % (reponame, arch_version)
  1124     name = "%s-%s" % (reponame, arch_version)
  1125 
  1125 
  1126     ctx = webutil.changectx(web.repo, req)
  1126     ctx = webutil.changectx(web.repo, req)
  1127     pats = []
  1127     pats = []
  1128     match = scmutil.match(ctx, [])
  1128     match = scmutil.match(ctx, [])
  1129     file = req.form.get('file', None)
  1129     file = req.req.qsparams.get('file')
  1130     if file:
  1130     if file:
  1131         pats = ['path:' + file[0]]
  1131         pats = ['path:' + file]
  1132         match = scmutil.match(ctx, pats, default='path')
  1132         match = scmutil.match(ctx, pats, default='path')
  1133         if pats:
  1133         if pats:
  1134             files = [f for f in ctx.manifest().keys() if match(f)]
  1134             files = [f for f in ctx.manifest().keys() if match(f)]
  1135             if not files:
  1135             if not files:
  1136                 raise ErrorResponse(HTTP_NOT_FOUND,
  1136                 raise ErrorResponse(HTTP_NOT_FOUND,
  1137                     'file(s) not found: %s' % file[0])
  1137                     'file(s) not found: %s' % file)
  1138 
  1138 
  1139     mimetype, artype, extension, encoding = web.archivespecs[type_]
  1139     mimetype, artype, extension, encoding = web.archivespecs[type_]
  1140     headers = [
  1140     headers = [
  1141         ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
  1141         ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
  1142         ]
  1142         ]
  1151     return []
  1151     return []
  1152 
  1152 
  1153 
  1153 
  1154 @webcommand('static')
  1154 @webcommand('static')
  1155 def static(web, req, tmpl):
  1155 def static(web, req, tmpl):
  1156     fname = req.form['file'][0]
  1156     fname = req.req.qsparams['file']
  1157     # a repo owner may set web.static in .hg/hgrc to get any file
  1157     # a repo owner may set web.static in .hg/hgrc to get any file
  1158     # readable by the user running the CGI script
  1158     # readable by the user running the CGI script
  1159     static = web.config("web", "static", None, untrusted=False)
  1159     static = web.config("web", "static", None, untrusted=False)
  1160     if not static:
  1160     if not static:
  1161         tp = web.templatepath or templater.templatepaths()
  1161         tp = web.templatepath or templater.templatepaths()
  1187     JavaScript. By default it has the same value as ``revision``.
  1187     JavaScript. By default it has the same value as ``revision``.
  1188 
  1188 
  1189     This handler will render the ``graph`` template.
  1189     This handler will render the ``graph`` template.
  1190     """
  1190     """
  1191 
  1191 
  1192     if 'node' in req.form:
  1192     if 'node' in req.req.qsparams:
  1193         ctx = webutil.changectx(web.repo, req)
  1193         ctx = webutil.changectx(web.repo, req)
  1194         symrev = webutil.symrevorshortnode(req, ctx)
  1194         symrev = webutil.symrevorshortnode(req, ctx)
  1195     else:
  1195     else:
  1196         ctx = web.repo['tip']
  1196         ctx = web.repo['tip']
  1197         symrev = 'tip'
  1197         symrev = 'tip'
  1198     rev = ctx.rev()
  1198     rev = ctx.rev()
  1199 
  1199 
  1200     bg_height = 39
  1200     bg_height = 39
  1201     revcount = web.maxshortchanges
  1201     revcount = web.maxshortchanges
  1202     if 'revcount' in req.form:
  1202     if 'revcount' in req.req.qsparams:
  1203         try:
  1203         try:
  1204             revcount = int(req.form.get('revcount', [revcount])[0])
  1204             revcount = int(req.req.qsparams.get('revcount', revcount))
  1205             revcount = max(revcount, 1)
  1205             revcount = max(revcount, 1)
  1206             tmpl.defaults['sessionvars']['revcount'] = revcount
  1206             tmpl.defaults['sessionvars']['revcount'] = revcount
  1207         except ValueError:
  1207         except ValueError:
  1208             pass
  1208             pass
  1209 
  1209 
  1210     lessvars = copy.copy(tmpl.defaults['sessionvars'])
  1210     lessvars = copy.copy(tmpl.defaults['sessionvars'])
  1211     lessvars['revcount'] = max(revcount // 2, 1)
  1211     lessvars['revcount'] = max(revcount // 2, 1)
  1212     morevars = copy.copy(tmpl.defaults['sessionvars'])
  1212     morevars = copy.copy(tmpl.defaults['sessionvars'])
  1213     morevars['revcount'] = revcount * 2
  1213     morevars['revcount'] = revcount * 2
  1214 
  1214 
  1215     graphtop = req.form.get('graphtop', [ctx.hex()])[0]
  1215     graphtop = req.req.qsparams.get('graphtop', ctx.hex())
  1216     graphvars = copy.copy(tmpl.defaults['sessionvars'])
  1216     graphvars = copy.copy(tmpl.defaults['sessionvars'])
  1217     graphvars['graphtop'] = graphtop
  1217     graphvars['graphtop'] = graphtop
  1218 
  1218 
  1219     count = len(web.repo)
  1219     count = len(web.repo)
  1220     pos = rev
  1220     pos = rev
  1340     The ``help`` template will be rendered when requesting help for a topic.
  1340     The ``help`` template will be rendered when requesting help for a topic.
  1341     ``helptopics`` will be rendered for the index of help topics.
  1341     ``helptopics`` will be rendered for the index of help topics.
  1342     """
  1342     """
  1343     from .. import commands, help as helpmod  # avoid cycle
  1343     from .. import commands, help as helpmod  # avoid cycle
  1344 
  1344 
  1345     topicname = req.form.get('node', [None])[0]
  1345     topicname = req.req.qsparams.get('node')
  1346     if not topicname:
  1346     if not topicname:
  1347         def topics(**map):
  1347         def topics(**map):
  1348             for entries, summary, _doc in helpmod.helptable:
  1348             for entries, summary, _doc in helpmod.helptable:
  1349                 yield {'topic': entries[0], 'summary': summary}
  1349                 yield {'topic': entries[0], 'summary': summary}
  1350 
  1350