91 |
91 |
92 For URLs of the form ``/log/{revision}/{file}``, the history for a specific |
92 For URLs of the form ``/log/{revision}/{file}``, the history for a specific |
93 file will be shown. This form is equivalent to the ``filelog`` handler. |
93 file will be shown. This form is equivalent to the ``filelog`` handler. |
94 """ |
94 """ |
95 |
95 |
96 if req.req.qsparams.get('file'): |
96 if web.req.qsparams.get('file'): |
97 return filelog(web, req, tmpl) |
97 return filelog(web, req, tmpl) |
98 else: |
98 else: |
99 return changelog(web, req, tmpl) |
99 return changelog(web, req, tmpl) |
100 |
100 |
101 @webcommand('rawfile') |
101 @webcommand('rawfile') |
102 def rawfile(web, req, tmpl): |
102 def rawfile(web, req, tmpl): |
103 guessmime = web.configbool('web', 'guessmime') |
103 guessmime = web.configbool('web', 'guessmime') |
104 |
104 |
105 path = webutil.cleanpath(web.repo, req.req.qsparams.get('file', '')) |
105 path = webutil.cleanpath(web.repo, web.req.qsparams.get('file', '')) |
106 if not path: |
106 if not path: |
107 return manifest(web, req, tmpl) |
107 return manifest(web, req, tmpl) |
108 |
108 |
109 try: |
109 try: |
110 fctx = webutil.filectx(web.repo, req) |
110 fctx = webutil.filectx(web.repo, req) |
185 be rendered. |
185 be rendered. |
186 """ |
186 """ |
187 if web.req.qsparams.get('style') == 'raw': |
187 if web.req.qsparams.get('style') == 'raw': |
188 return rawfile(web, req, tmpl) |
188 return rawfile(web, req, tmpl) |
189 |
189 |
190 path = webutil.cleanpath(web.repo, req.req.qsparams.get('file', '')) |
190 path = webutil.cleanpath(web.repo, web.req.qsparams.get('file', '')) |
191 if not path: |
191 if not path: |
192 return manifest(web, req, tmpl) |
192 return manifest(web, req, tmpl) |
193 try: |
193 try: |
194 return _filerevision(web, req, tmpl, webutil.filectx(web.repo, req)) |
194 return _filerevision(web, req, tmpl, webutil.filectx(web.repo, req)) |
195 except error.LookupError as inst: |
195 except error.LookupError as inst: |
196 try: |
196 try: |
197 return manifest(web, req, tmpl) |
197 return manifest(web, req, tmpl) |
198 except ErrorResponse: |
198 except ErrorResponse: |
199 raise inst |
199 raise inst |
200 |
200 |
201 def _search(web, req, tmpl): |
201 def _search(web, tmpl): |
202 MODE_REVISION = 'rev' |
202 MODE_REVISION = 'rev' |
203 MODE_KEYWORD = 'keyword' |
203 MODE_KEYWORD = 'keyword' |
204 MODE_REVSET = 'revset' |
204 MODE_REVSET = 'revset' |
205 |
205 |
206 def revsearch(ctx): |
206 def revsearch(ctx): |
301 **pycompat.strkwargs(webutil.commonentry(web.repo, ctx))) |
301 **pycompat.strkwargs(webutil.commonentry(web.repo, ctx))) |
302 |
302 |
303 if count >= revcount: |
303 if count >= revcount: |
304 break |
304 break |
305 |
305 |
306 query = req.req.qsparams['rev'] |
306 query = web.req.qsparams['rev'] |
307 revcount = web.maxchanges |
307 revcount = web.maxchanges |
308 if 'revcount' in req.req.qsparams: |
308 if 'revcount' in web.req.qsparams: |
309 try: |
309 try: |
310 revcount = int(req.req.qsparams.get('revcount', revcount)) |
310 revcount = int(web.req.qsparams.get('revcount', revcount)) |
311 revcount = max(revcount, 1) |
311 revcount = max(revcount, 1) |
312 tmpl.defaults['sessionvars']['revcount'] = revcount |
312 tmpl.defaults['sessionvars']['revcount'] = revcount |
313 except ValueError: |
313 except ValueError: |
314 pass |
314 pass |
315 |
315 |
320 morevars['revcount'] = revcount * 2 |
320 morevars['revcount'] = revcount * 2 |
321 morevars['rev'] = query |
321 morevars['rev'] = query |
322 |
322 |
323 mode, funcarg = getsearchmode(query) |
323 mode, funcarg = getsearchmode(query) |
324 |
324 |
325 if 'forcekw' in req.req.qsparams: |
325 if 'forcekw' in web.req.qsparams: |
326 showforcekw = '' |
326 showforcekw = '' |
327 showunforcekw = searchfuncs[mode][1] |
327 showunforcekw = searchfuncs[mode][1] |
328 mode = MODE_KEYWORD |
328 mode = MODE_KEYWORD |
329 funcarg = query |
329 funcarg = query |
330 else: |
330 else: |
379 |
379 |
380 For non-searches, the ``changelog`` template will be rendered. |
380 For non-searches, the ``changelog`` template will be rendered. |
381 """ |
381 """ |
382 |
382 |
383 query = '' |
383 query = '' |
384 if 'node' in req.req.qsparams: |
384 if 'node' in web.req.qsparams: |
385 ctx = webutil.changectx(web.repo, req) |
385 ctx = webutil.changectx(web.repo, req) |
386 symrev = webutil.symrevorshortnode(req, ctx) |
386 symrev = webutil.symrevorshortnode(req, ctx) |
387 elif 'rev' in req.req.qsparams: |
387 elif 'rev' in web.req.qsparams: |
388 return _search(web, req, tmpl) |
388 return _search(web, tmpl) |
389 else: |
389 else: |
390 ctx = web.repo['tip'] |
390 ctx = web.repo['tip'] |
391 symrev = 'tip' |
391 symrev = 'tip' |
392 |
392 |
393 def changelist(): |
393 def changelist(): |
407 if shortlog: |
407 if shortlog: |
408 revcount = web.maxshortchanges |
408 revcount = web.maxshortchanges |
409 else: |
409 else: |
410 revcount = web.maxchanges |
410 revcount = web.maxchanges |
411 |
411 |
412 if 'revcount' in req.req.qsparams: |
412 if 'revcount' in web.req.qsparams: |
413 try: |
413 try: |
414 revcount = int(req.req.qsparams.get('revcount', revcount)) |
414 revcount = int(web.req.qsparams.get('revcount', revcount)) |
415 revcount = max(revcount, 1) |
415 revcount = max(revcount, 1) |
416 tmpl.defaults['sessionvars']['revcount'] = revcount |
416 tmpl.defaults['sessionvars']['revcount'] = revcount |
417 except ValueError: |
417 except ValueError: |
418 pass |
418 pass |
419 |
419 |
514 is recommended to use the ``file`` handler instead, as it can handle both |
514 is recommended to use the ``file`` handler instead, as it can handle both |
515 directories and files. |
515 directories and files. |
516 |
516 |
517 The ``manifest`` template will be rendered for this handler. |
517 The ``manifest`` template will be rendered for this handler. |
518 """ |
518 """ |
519 if 'node' in req.req.qsparams: |
519 if 'node' in web.req.qsparams: |
520 ctx = webutil.changectx(web.repo, req) |
520 ctx = webutil.changectx(web.repo, req) |
521 symrev = webutil.symrevorshortnode(req, ctx) |
521 symrev = webutil.symrevorshortnode(req, ctx) |
522 else: |
522 else: |
523 ctx = web.repo['tip'] |
523 ctx = web.repo['tip'] |
524 symrev = 'tip' |
524 symrev = 'tip' |
525 path = webutil.cleanpath(web.repo, req.req.qsparams.get('file', '')) |
525 path = webutil.cleanpath(web.repo, web.req.qsparams.get('file', '')) |
526 mf = ctx.manifest() |
526 mf = ctx.manifest() |
527 node = ctx.node() |
527 node = ctx.node() |
528 |
528 |
529 files = {} |
529 files = {} |
530 dirs = {} |
530 dirs = {} |
804 fctx, ctx = None, None |
804 fctx, ctx = None, None |
805 try: |
805 try: |
806 fctx = webutil.filectx(web.repo, req) |
806 fctx = webutil.filectx(web.repo, req) |
807 except LookupError: |
807 except LookupError: |
808 ctx = webutil.changectx(web.repo, req) |
808 ctx = webutil.changectx(web.repo, req) |
809 path = webutil.cleanpath(web.repo, req.req.qsparams['file']) |
809 path = webutil.cleanpath(web.repo, web.req.qsparams['file']) |
810 if path not in ctx.files(): |
810 if path not in ctx.files(): |
811 raise |
811 raise |
812 |
812 |
813 if fctx is not None: |
813 if fctx is not None: |
814 path = fctx.path() |
814 path = fctx.path() |
815 ctx = fctx.changectx() |
815 ctx = fctx.changectx() |
816 basectx = ctx.p1() |
816 basectx = ctx.p1() |
817 |
817 |
818 style = web.config('web', 'style') |
818 style = web.config('web', 'style') |
819 if 'style' in req.req.qsparams: |
819 if 'style' in web.req.qsparams: |
820 style = req.req.qsparams['style'] |
820 style = web.req.qsparams['style'] |
821 |
821 |
822 diffs = webutil.diffs(web, tmpl, ctx, basectx, [path], style) |
822 diffs = webutil.diffs(web, tmpl, ctx, basectx, [path], style) |
823 if fctx is not None: |
823 if fctx is not None: |
824 rename = webutil.renamelink(fctx) |
824 rename = webutil.renamelink(fctx) |
825 ctx = fctx |
825 ctx = fctx |
855 context in the diff. |
855 context in the diff. |
856 |
856 |
857 The ``filecomparison`` template is rendered. |
857 The ``filecomparison`` template is rendered. |
858 """ |
858 """ |
859 ctx = webutil.changectx(web.repo, req) |
859 ctx = webutil.changectx(web.repo, req) |
860 if 'file' not in req.req.qsparams: |
860 if 'file' not in web.req.qsparams: |
861 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given') |
861 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given') |
862 path = webutil.cleanpath(web.repo, req.req.qsparams['file']) |
862 path = webutil.cleanpath(web.repo, web.req.qsparams['file']) |
863 |
863 |
864 parsecontext = lambda v: v == 'full' and -1 or int(v) |
864 parsecontext = lambda v: v == 'full' and -1 or int(v) |
865 if 'context' in req.req.qsparams: |
865 if 'context' in web.req.qsparams: |
866 context = parsecontext(req.req.qsparams['context']) |
866 context = parsecontext(web.req.qsparams['context']) |
867 else: |
867 else: |
868 context = parsecontext(web.config('web', 'comparisoncontext', '5')) |
868 context = parsecontext(web.config('web', 'comparisoncontext', '5')) |
869 |
869 |
870 def filelines(f): |
870 def filelines(f): |
871 if f.isbinary(): |
871 if f.isbinary(): |
1027 try: |
1027 try: |
1028 fctx = webutil.filectx(web.repo, req) |
1028 fctx = webutil.filectx(web.repo, req) |
1029 f = fctx.path() |
1029 f = fctx.path() |
1030 fl = fctx.filelog() |
1030 fl = fctx.filelog() |
1031 except error.LookupError: |
1031 except error.LookupError: |
1032 f = webutil.cleanpath(web.repo, req.req.qsparams['file']) |
1032 f = webutil.cleanpath(web.repo, web.req.qsparams['file']) |
1033 fl = web.repo.file(f) |
1033 fl = web.repo.file(f) |
1034 numrevs = len(fl) |
1034 numrevs = len(fl) |
1035 if not numrevs: # file doesn't exist at all |
1035 if not numrevs: # file doesn't exist at all |
1036 raise |
1036 raise |
1037 rev = webutil.changectx(web.repo, req).rev() |
1037 rev = webutil.changectx(web.repo, req).rev() |
1042 while fl.linkrev(frev) > rev: |
1042 while fl.linkrev(frev) > rev: |
1043 frev -= 1 |
1043 frev -= 1 |
1044 fctx = web.repo.filectx(f, fl.linkrev(frev)) |
1044 fctx = web.repo.filectx(f, fl.linkrev(frev)) |
1045 |
1045 |
1046 revcount = web.maxshortchanges |
1046 revcount = web.maxshortchanges |
1047 if 'revcount' in req.req.qsparams: |
1047 if 'revcount' in web.req.qsparams: |
1048 try: |
1048 try: |
1049 revcount = int(req.req.qsparams.get('revcount', revcount)) |
1049 revcount = int(web.req.qsparams.get('revcount', revcount)) |
1050 revcount = max(revcount, 1) |
1050 revcount = max(revcount, 1) |
1051 tmpl.defaults['sessionvars']['revcount'] = revcount |
1051 tmpl.defaults['sessionvars']['revcount'] = revcount |
1052 except ValueError: |
1052 except ValueError: |
1053 pass |
1053 pass |
1054 |
1054 |
1057 lessvars = copy.copy(tmpl.defaults['sessionvars']) |
1057 lessvars = copy.copy(tmpl.defaults['sessionvars']) |
1058 lessvars['revcount'] = max(revcount // 2, 1) |
1058 lessvars['revcount'] = max(revcount // 2, 1) |
1059 morevars = copy.copy(tmpl.defaults['sessionvars']) |
1059 morevars = copy.copy(tmpl.defaults['sessionvars']) |
1060 morevars['revcount'] = revcount * 2 |
1060 morevars['revcount'] = revcount * 2 |
1061 |
1061 |
1062 patch = 'patch' in req.req.qsparams |
1062 patch = 'patch' in web.req.qsparams |
1063 if patch: |
1063 if patch: |
1064 lessvars['patch'] = morevars['patch'] = req.req.qsparams['patch'] |
1064 lessvars['patch'] = morevars['patch'] = web.req.qsparams['patch'] |
1065 descend = 'descend' in req.req.qsparams |
1065 descend = 'descend' in web.req.qsparams |
1066 if descend: |
1066 if descend: |
1067 lessvars['descend'] = morevars['descend'] = req.req.qsparams['descend'] |
1067 lessvars['descend'] = morevars['descend'] = web.req.qsparams['descend'] |
1068 |
1068 |
1069 count = fctx.filerev() + 1 |
1069 count = fctx.filerev() + 1 |
1070 start = max(0, count - revcount) # first rev on this page |
1070 start = max(0, count - revcount) # first rev on this page |
1071 end = min(count, start + revcount) # last rev on this page |
1071 end = min(count, start + revcount) # last rev on this page |
1072 parity = paritygen(web.stripecount, offset=start - end) |
1072 parity = paritygen(web.stripecount, offset=start - end) |
1074 repo = web.repo |
1074 repo = web.repo |
1075 revs = fctx.filelog().revs(start, end - 1) |
1075 revs = fctx.filelog().revs(start, end - 1) |
1076 entries = [] |
1076 entries = [] |
1077 |
1077 |
1078 diffstyle = web.config('web', 'style') |
1078 diffstyle = web.config('web', 'style') |
1079 if 'style' in req.req.qsparams: |
1079 if 'style' in web.req.qsparams: |
1080 diffstyle = req.req.qsparams['style'] |
1080 diffstyle = web.req.qsparams['style'] |
1081 |
1081 |
1082 def diff(fctx, linerange=None): |
1082 def diff(fctx, linerange=None): |
1083 ctx = fctx.changectx() |
1083 ctx = fctx.changectx() |
1084 basectx = ctx.p1() |
1084 basectx = ctx.p1() |
1085 path = fctx.path() |
1085 path = fctx.path() |
1169 directory will be included in the archive. |
1169 directory will be included in the archive. |
1170 |
1170 |
1171 No template is used for this handler. Raw, binary content is generated. |
1171 No template is used for this handler. Raw, binary content is generated. |
1172 """ |
1172 """ |
1173 |
1173 |
1174 type_ = req.req.qsparams.get('type') |
1174 type_ = web.req.qsparams.get('type') |
1175 allowed = web.configlist("web", "allow_archive") |
1175 allowed = web.configlist("web", "allow_archive") |
1176 key = req.req.qsparams['node'] |
1176 key = web.req.qsparams['node'] |
1177 |
1177 |
1178 if type_ not in web.archivespecs: |
1178 if type_ not in web.archivespecs: |
1179 msg = 'Unsupported archive type: %s' % type_ |
1179 msg = 'Unsupported archive type: %s' % type_ |
1180 raise ErrorResponse(HTTP_NOT_FOUND, msg) |
1180 raise ErrorResponse(HTTP_NOT_FOUND, msg) |
1181 |
1181 |
1192 name = "%s-%s" % (reponame, arch_version) |
1192 name = "%s-%s" % (reponame, arch_version) |
1193 |
1193 |
1194 ctx = webutil.changectx(web.repo, req) |
1194 ctx = webutil.changectx(web.repo, req) |
1195 pats = [] |
1195 pats = [] |
1196 match = scmutil.match(ctx, []) |
1196 match = scmutil.match(ctx, []) |
1197 file = req.req.qsparams.get('file') |
1197 file = web.req.qsparams.get('file') |
1198 if file: |
1198 if file: |
1199 pats = ['path:' + file] |
1199 pats = ['path:' + file] |
1200 match = scmutil.match(ctx, pats, default='path') |
1200 match = scmutil.match(ctx, pats, default='path') |
1201 if pats: |
1201 if pats: |
1202 files = [f for f in ctx.manifest().keys() if match(f)] |
1202 files = [f for f in ctx.manifest().keys() if match(f)] |
1224 |
1224 |
1225 return [] |
1225 return [] |
1226 |
1226 |
1227 @webcommand('static') |
1227 @webcommand('static') |
1228 def static(web, req, tmpl): |
1228 def static(web, req, tmpl): |
1229 fname = req.req.qsparams['file'] |
1229 fname = web.req.qsparams['file'] |
1230 # a repo owner may set web.static in .hg/hgrc to get any file |
1230 # a repo owner may set web.static in .hg/hgrc to get any file |
1231 # readable by the user running the CGI script |
1231 # readable by the user running the CGI script |
1232 static = web.config("web", "static", None, untrusted=False) |
1232 static = web.config("web", "static", None, untrusted=False) |
1233 if not static: |
1233 if not static: |
1234 tp = web.templatepath or templater.templatepaths() |
1234 tp = web.templatepath or templater.templatepaths() |
1261 JavaScript. By default it has the same value as ``revision``. |
1261 JavaScript. By default it has the same value as ``revision``. |
1262 |
1262 |
1263 This handler will render the ``graph`` template. |
1263 This handler will render the ``graph`` template. |
1264 """ |
1264 """ |
1265 |
1265 |
1266 if 'node' in req.req.qsparams: |
1266 if 'node' in web.req.qsparams: |
1267 ctx = webutil.changectx(web.repo, req) |
1267 ctx = webutil.changectx(web.repo, req) |
1268 symrev = webutil.symrevorshortnode(req, ctx) |
1268 symrev = webutil.symrevorshortnode(req, ctx) |
1269 else: |
1269 else: |
1270 ctx = web.repo['tip'] |
1270 ctx = web.repo['tip'] |
1271 symrev = 'tip' |
1271 symrev = 'tip' |
1272 rev = ctx.rev() |
1272 rev = ctx.rev() |
1273 |
1273 |
1274 bg_height = 39 |
1274 bg_height = 39 |
1275 revcount = web.maxshortchanges |
1275 revcount = web.maxshortchanges |
1276 if 'revcount' in req.req.qsparams: |
1276 if 'revcount' in web.req.qsparams: |
1277 try: |
1277 try: |
1278 revcount = int(req.req.qsparams.get('revcount', revcount)) |
1278 revcount = int(web.req.qsparams.get('revcount', revcount)) |
1279 revcount = max(revcount, 1) |
1279 revcount = max(revcount, 1) |
1280 tmpl.defaults['sessionvars']['revcount'] = revcount |
1280 tmpl.defaults['sessionvars']['revcount'] = revcount |
1281 except ValueError: |
1281 except ValueError: |
1282 pass |
1282 pass |
1283 |
1283 |
1284 lessvars = copy.copy(tmpl.defaults['sessionvars']) |
1284 lessvars = copy.copy(tmpl.defaults['sessionvars']) |
1285 lessvars['revcount'] = max(revcount // 2, 1) |
1285 lessvars['revcount'] = max(revcount // 2, 1) |
1286 morevars = copy.copy(tmpl.defaults['sessionvars']) |
1286 morevars = copy.copy(tmpl.defaults['sessionvars']) |
1287 morevars['revcount'] = revcount * 2 |
1287 morevars['revcount'] = revcount * 2 |
1288 |
1288 |
1289 graphtop = req.req.qsparams.get('graphtop', ctx.hex()) |
1289 graphtop = web.req.qsparams.get('graphtop', ctx.hex()) |
1290 graphvars = copy.copy(tmpl.defaults['sessionvars']) |
1290 graphvars = copy.copy(tmpl.defaults['sessionvars']) |
1291 graphvars['graphtop'] = graphtop |
1291 graphvars['graphtop'] = graphtop |
1292 |
1292 |
1293 count = len(web.repo) |
1293 count = len(web.repo) |
1294 pos = rev |
1294 pos = rev |
1423 The ``help`` template will be rendered when requesting help for a topic. |
1423 The ``help`` template will be rendered when requesting help for a topic. |
1424 ``helptopics`` will be rendered for the index of help topics. |
1424 ``helptopics`` will be rendered for the index of help topics. |
1425 """ |
1425 """ |
1426 from .. import commands, help as helpmod # avoid cycle |
1426 from .. import commands, help as helpmod # avoid cycle |
1427 |
1427 |
1428 topicname = req.req.qsparams.get('node') |
1428 topicname = web.req.qsparams.get('node') |
1429 if not topicname: |
1429 if not topicname: |
1430 def topics(**map): |
1430 def topics(**map): |
1431 for entries, summary, _doc in helpmod.helptable: |
1431 for entries, summary, _doc in helpmod.helptable: |
1432 yield {'topic': entries[0], 'summary': summary} |
1432 yield {'topic': entries[0], 'summary': summary} |
1433 |
1433 |