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): |