Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/hgweb/hgweb_mod.py @ 5561:22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Wed, 28 Nov 2007 08:38:42 -0800 |
parents | 48c22c719f8c |
children | d61fea133f2d |
comparison
equal
deleted
inserted
replaced
5560:e78c24011001 | 5561:22713dce19f6 |
---|---|
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | 4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
5 # | 5 # |
6 # This software may be used and distributed according to the terms | 6 # This software may be used and distributed according to the terms |
7 # of the GNU General Public License, incorporated herein by reference. | 7 # of the GNU General Public License, incorporated herein by reference. |
8 | 8 |
9 import os, mimetypes, re, zlib, mimetools, cStringIO, sys | 9 import errno, os, mimetypes, re, zlib, mimetools, cStringIO, sys |
10 import tempfile, urllib, bz2 | 10 import tempfile, urllib, bz2 |
11 from mercurial.node import * | 11 from mercurial.node import * |
12 from mercurial.i18n import gettext as _ | 12 from mercurial.i18n import gettext as _ |
13 from mercurial import mdiff, ui, hg, util, archival, streamclone, patch | 13 from mercurial import mdiff, ui, hg, util, archival, streamclone, patch |
14 from mercurial import revlog, templater | 14 from mercurial import revlog, templater |
15 from common import get_mtime, staticfile, style_map, paritygen | 15 from common import ErrorResponse, get_mtime, staticfile, style_map, paritygen |
16 | 16 |
17 def _up(p): | 17 def _up(p): |
18 if p[0] != "/": | 18 if p[0] != "/": |
19 p = "/" + p | 19 p = "/" + p |
20 if p[-1] == "/": | 20 if p[-1] == "/": |
476 files[short] = (f, None) | 476 files[short] = (f, None) |
477 else: | 477 else: |
478 short = os.path.basename(remain) | 478 short = os.path.basename(remain) |
479 files[short] = (f, n) | 479 files[short] = (f, n) |
480 | 480 |
481 if not files: | |
482 raise ErrorResponse(404, 'Path not found: ' + path) | |
483 | |
481 def filelist(**map): | 484 def filelist(**map): |
482 fl = files.keys() | 485 fl = files.keys() |
483 fl.sort() | 486 fl.sort() |
484 for f in fl: | 487 for f in fl: |
485 full, fnode = files[f] | 488 full, fnode = files[f] |
843 if not req.form.has_key('cmd'): | 846 if not req.form.has_key('cmd'): |
844 req.form['cmd'] = [self.t.cache['default']] | 847 req.form['cmd'] = [self.t.cache['default']] |
845 | 848 |
846 cmd = req.form['cmd'][0] | 849 cmd = req.form['cmd'][0] |
847 | 850 |
848 method = getattr(self, 'do_' + cmd, None) | 851 try: |
849 if method: | 852 method = getattr(self, 'do_' + cmd) |
850 try: | 853 method(req) |
851 method(req) | 854 except revlog.LookupError, err: |
852 except (hg.RepoError, revlog.RevlogError), inst: | 855 req.respond(404, self.t( |
853 req.write(self.t("error", error=str(inst))) | 856 'error', error='revision not found: %s' % err.name)) |
854 else: | 857 except (hg.RepoError, revlog.RevlogError), inst: |
855 req.write(self.t("error", error='No such method: ' + cmd)) | 858 req.respond('500 Internal Server Error', |
859 self.t('error', error=str(inst))) | |
860 except ErrorResponse, inst: | |
861 req.respond(inst.code, self.t('error', error=inst.message)) | |
862 except AttributeError: | |
863 req.respond(400, | |
864 self.t('error', error='No such method: ' + cmd)) | |
856 finally: | 865 finally: |
857 self.t = None | 866 self.t = None |
858 | 867 |
859 def changectx(self, req): | 868 def changectx(self, req): |
860 if req.form.has_key('node'): | 869 if req.form.has_key('node'): |
1036 if (type_ in self.archives and (type_ in allowed or | 1045 if (type_ in self.archives and (type_ in allowed or |
1037 self.configbool("web", "allow" + type_, False))): | 1046 self.configbool("web", "allow" + type_, False))): |
1038 self.archive(req, req.form['node'][0], type_) | 1047 self.archive(req, req.form['node'][0], type_) |
1039 return | 1048 return |
1040 | 1049 |
1041 req.write(self.t("error")) | 1050 req.respond(400, self.t('error', |
1051 error='Unsupported archive type: %s' % type_)) | |
1042 | 1052 |
1043 def do_static(self, req): | 1053 def do_static(self, req): |
1044 fname = req.form['file'][0] | 1054 fname = req.form['file'][0] |
1045 # a repo owner may set web.static in .hg/hgrc to get any file | 1055 # a repo owner may set web.static in .hg/hgrc to get any file |
1046 # readable by the user running the CGI script | 1056 # readable by the user running the CGI script |
1047 static = self.config("web", "static", | 1057 static = self.config("web", "static", |
1048 os.path.join(self.templatepath, "static"), | 1058 os.path.join(self.templatepath, "static"), |
1049 untrusted=False) | 1059 untrusted=False) |
1050 req.write(staticfile(static, fname, req) | 1060 req.write(staticfile(static, fname, req)) |
1051 or self.t("error", error="%r not found" % fname)) | |
1052 | 1061 |
1053 def do_capabilities(self, req): | 1062 def do_capabilities(self, req): |
1054 caps = ['lookup', 'changegroupsubset'] | 1063 caps = ['lookup', 'changegroupsubset'] |
1055 if self.configbool('server', 'uncompressed'): | 1064 if self.configbool('server', 'uncompressed'): |
1056 caps.append('stream=%d' % self.repo.changelog.version) | 1065 caps.append('stream=%d' % self.repo.changelog.version) |
1196 if filename.startswith(self.repo.root): | 1205 if filename.startswith(self.repo.root): |
1197 filename = filename[len(self.repo.root)+1:] | 1206 filename = filename[len(self.repo.root)+1:] |
1198 else: | 1207 else: |
1199 filename = '' | 1208 filename = '' |
1200 error = getattr(inst, 'strerror', 'Unknown error') | 1209 error = getattr(inst, 'strerror', 'Unknown error') |
1201 req.write('%s: %s\n' % (error, filename)) | 1210 if inst.errno == errno.ENOENT: |
1211 code = 404 | |
1212 else: | |
1213 code = 500 | |
1214 req.respond(code, '%s: %s\n' % (error, filename)) | |
1202 finally: | 1215 finally: |
1203 fp.close() | 1216 fp.close() |
1204 os.unlink(tempname) | 1217 os.unlink(tempname) |
1205 | 1218 |
1206 def do_stream_out(self, req): | 1219 def do_stream_out(self, req): |