comparison mercurial/hgweb/webcommands.py @ 36871:3d60a22e27f5

hgweb: perform all parameter lookup via qsparams I think I managed to update all call sites using wsgirequest.form to use parsedrequest.qsparams. Since behavior of qsparams is to retrieve last value, behavior will change if a parameter was specified multiple times. But I think this is acceptable. I'm not a fan of the `req.req.qsparams` pattern. And some of the modified code could be written better. But I was aiming for a straight port with this change. Cleanup can come later. Differential Revision: https://phab.mercurial-scm.org/D2781
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 10 Mar 2018 12:36:36 -0800
parents 1a1972b1a1ff
children 1f42d621f090
comparison
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