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 |