##// END OF EJS Templates
wireproto: add out-of-band error class to allow remote repo to report errors...
Andrew Pritchard -
r15017:f4522df3 default
parent child Browse files
Show More
@@ -123,6 +123,9 b' def _runcatch(req):'
123 else:
123 else:
124 ui.warn(_("hg: %s\n") % inst.args[1])
124 ui.warn(_("hg: %s\n") % inst.args[1])
125 commands.help_(ui, 'shortlist')
125 commands.help_(ui, 'shortlist')
126 except error.OutOfBandError, inst:
127 ui.warn("abort: remote error:\n")
128 ui.warn(''.join(inst.args))
126 except error.RepoError, inst:
129 except error.RepoError, inst:
127 ui.warn(_("abort: %s!\n") % inst)
130 ui.warn(_("abort: %s!\n") % inst)
128 if inst.hint:
131 if inst.hint:
@@ -39,6 +39,9 b' class Abort(Exception):'
39 class ConfigError(Abort):
39 class ConfigError(Abort):
40 'Exception raised when parsing config files'
40 'Exception raised when parsing config files'
41
41
42 class OutOfBandError(Exception):
43 'Exception raised when a remote repo reports failure'
44
42 class ParseError(Exception):
45 class ParseError(Exception):
43 'Exception raised when parsing config files (msg[, pos])'
46 'Exception raised when parsing config files (msg[, pos])'
44
47
@@ -10,6 +10,7 b' from mercurial import util, wireproto'
10 from common import HTTP_OK
10 from common import HTTP_OK
11
11
12 HGTYPE = 'application/mercurial-0.1'
12 HGTYPE = 'application/mercurial-0.1'
13 HGERRTYPE = 'application/hg-error'
13
14
14 class webproto(object):
15 class webproto(object):
15 def __init__(self, req, ui):
16 def __init__(self, req, ui):
@@ -90,3 +91,7 b' def call(repo, req, cmd):'
90 rsp = '0\n%s\n' % rsp.res
91 rsp = '0\n%s\n' % rsp.res
91 req.respond(HTTP_OK, HGTYPE, length=len(rsp))
92 req.respond(HTTP_OK, HGTYPE, length=len(rsp))
92 return [rsp]
93 return [rsp]
94 elif isinstance(rsp, wireproto.ooberror):
95 rsp = rsp.message
96 req.respond(HTTP_OK, HGERRTYPE, length=len(rsp))
97 return [rsp]
@@ -136,6 +136,8 b' class httprepository(wireproto.wirerepos'
136 proto = resp.headers.get('content-type', '')
136 proto = resp.headers.get('content-type', '')
137
137
138 safeurl = util.hidepassword(self._url)
138 safeurl = util.hidepassword(self._url)
139 if proto.startswith('application/hg-error'):
140 raise error.OutOfBandError(resp.read())
139 # accept old "text/plain" and "application/hg-changegroup" for now
141 # accept old "text/plain" and "application/hg-changegroup" for now
140 if not (proto.startswith('application/mercurial-') or
142 if not (proto.startswith('application/mercurial-') or
141 proto.startswith('text/plain') or
143 proto.startswith('text/plain') or
@@ -164,6 +164,17 b' class sshrepository(wireproto.wirereposi'
164
164
165 def _recv(self):
165 def _recv(self):
166 l = self.pipei.readline()
166 l = self.pipei.readline()
167 if l == '\n':
168 err = []
169 while True:
170 line = self.pipee.readline()
171 if line == '-\n':
172 break
173 err.extend([line])
174 if len(err) > 0:
175 # strip the trailing newline added to the last line server-side
176 err[-1] = err[-1][:-1]
177 self._abort(error.OutOfBandError(*err))
167 self.readerr()
178 self.readerr()
168 try:
179 try:
169 l = int(l)
180 l = int(l)
@@ -82,6 +82,12 b' class sshserver(object):'
82 def sendpusherror(self, rsp):
82 def sendpusherror(self, rsp):
83 self.sendresponse(rsp.res)
83 self.sendresponse(rsp.res)
84
84
85 def sendooberror(self, rsp):
86 self.ui.ferr.write('%s\n-\n' % rsp.message)
87 self.ui.ferr.flush()
88 self.fout.write('\n')
89 self.fout.flush()
90
85 def serve_forever(self):
91 def serve_forever(self):
86 try:
92 try:
87 while self.serve_one():
93 while self.serve_one():
@@ -96,6 +102,7 b' class sshserver(object):'
96 wireproto.streamres: sendstream,
102 wireproto.streamres: sendstream,
97 wireproto.pushres: sendpushresponse,
103 wireproto.pushres: sendpushresponse,
98 wireproto.pusherr: sendpusherror,
104 wireproto.pusherr: sendpusherror,
105 wireproto.ooberror: sendooberror,
99 }
106 }
100
107
101 def serve_one(self):
108 def serve_one(self):
@@ -335,6 +335,10 b' class pusherr(object):'
335 def __init__(self, res):
335 def __init__(self, res):
336 self.res = res
336 self.res = res
337
337
338 class ooberror(object):
339 def __init__(self, message):
340 self.message = message
341
338 def dispatch(repo, proto, command):
342 def dispatch(repo, proto, command):
339 func, spec = commands[command]
343 func, spec = commands[command]
340 args = proto.getargs(spec)
344 args = proto.getargs(spec)
@@ -376,6 +380,8 b' def batch(repo, proto, cmds, others):'
376 result = func(repo, proto, *[data[k] for k in keys])
380 result = func(repo, proto, *[data[k] for k in keys])
377 else:
381 else:
378 result = func(repo, proto)
382 result = func(repo, proto)
383 if isinstance(result, ooberror):
384 return result
379 res.append(escapearg(result))
385 res.append(escapearg(result))
380 return ';'.join(res)
386 return ';'.join(res)
381
387
General Comments 0
You need to be logged in to leave comments. Login now