##// END OF EJS Templates
httppeer: always add x-hg* headers to Vary header...
Gregory Szorc -
r37573:930c433e default
parent child Browse files
Show More
@@ -1,658 +1,660
1 # httppeer.py - HTTP repository proxy classes for mercurial
1 # httppeer.py - HTTP repository proxy classes for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 import errno
11 import errno
12 import io
12 import io
13 import os
13 import os
14 import socket
14 import socket
15 import struct
15 import struct
16 import tempfile
16 import tempfile
17
17
18 from .i18n import _
18 from .i18n import _
19 from .thirdparty import (
19 from .thirdparty import (
20 cbor,
20 cbor,
21 )
21 )
22 from . import (
22 from . import (
23 bundle2,
23 bundle2,
24 error,
24 error,
25 httpconnection,
25 httpconnection,
26 pycompat,
26 pycompat,
27 statichttprepo,
27 statichttprepo,
28 url as urlmod,
28 url as urlmod,
29 util,
29 util,
30 wireproto,
30 wireproto,
31 wireprotoframing,
31 wireprotoframing,
32 wireprotov2server,
32 wireprotov2server,
33 )
33 )
34
34
35 httplib = util.httplib
35 httplib = util.httplib
36 urlerr = util.urlerr
36 urlerr = util.urlerr
37 urlreq = util.urlreq
37 urlreq = util.urlreq
38
38
39 def encodevalueinheaders(value, header, limit):
39 def encodevalueinheaders(value, header, limit):
40 """Encode a string value into multiple HTTP headers.
40 """Encode a string value into multiple HTTP headers.
41
41
42 ``value`` will be encoded into 1 or more HTTP headers with the names
42 ``value`` will be encoded into 1 or more HTTP headers with the names
43 ``header-<N>`` where ``<N>`` is an integer starting at 1. Each header
43 ``header-<N>`` where ``<N>`` is an integer starting at 1. Each header
44 name + value will be at most ``limit`` bytes long.
44 name + value will be at most ``limit`` bytes long.
45
45
46 Returns an iterable of 2-tuples consisting of header names and
46 Returns an iterable of 2-tuples consisting of header names and
47 values as native strings.
47 values as native strings.
48 """
48 """
49 # HTTP Headers are ASCII. Python 3 requires them to be unicodes,
49 # HTTP Headers are ASCII. Python 3 requires them to be unicodes,
50 # not bytes. This function always takes bytes in as arguments.
50 # not bytes. This function always takes bytes in as arguments.
51 fmt = pycompat.strurl(header) + r'-%s'
51 fmt = pycompat.strurl(header) + r'-%s'
52 # Note: it is *NOT* a bug that the last bit here is a bytestring
52 # Note: it is *NOT* a bug that the last bit here is a bytestring
53 # and not a unicode: we're just getting the encoded length anyway,
53 # and not a unicode: we're just getting the encoded length anyway,
54 # and using an r-string to make it portable between Python 2 and 3
54 # and using an r-string to make it portable between Python 2 and 3
55 # doesn't work because then the \r is a literal backslash-r
55 # doesn't work because then the \r is a literal backslash-r
56 # instead of a carriage return.
56 # instead of a carriage return.
57 valuelen = limit - len(fmt % r'000') - len(': \r\n')
57 valuelen = limit - len(fmt % r'000') - len(': \r\n')
58 result = []
58 result = []
59
59
60 n = 0
60 n = 0
61 for i in xrange(0, len(value), valuelen):
61 for i in xrange(0, len(value), valuelen):
62 n += 1
62 n += 1
63 result.append((fmt % str(n), pycompat.strurl(value[i:i + valuelen])))
63 result.append((fmt % str(n), pycompat.strurl(value[i:i + valuelen])))
64
64
65 return result
65 return result
66
66
67 def _wraphttpresponse(resp):
67 def _wraphttpresponse(resp):
68 """Wrap an HTTPResponse with common error handlers.
68 """Wrap an HTTPResponse with common error handlers.
69
69
70 This ensures that any I/O from any consumer raises the appropriate
70 This ensures that any I/O from any consumer raises the appropriate
71 error and messaging.
71 error and messaging.
72 """
72 """
73 origread = resp.read
73 origread = resp.read
74
74
75 class readerproxy(resp.__class__):
75 class readerproxy(resp.__class__):
76 def read(self, size=None):
76 def read(self, size=None):
77 try:
77 try:
78 return origread(size)
78 return origread(size)
79 except httplib.IncompleteRead as e:
79 except httplib.IncompleteRead as e:
80 # e.expected is an integer if length known or None otherwise.
80 # e.expected is an integer if length known or None otherwise.
81 if e.expected:
81 if e.expected:
82 msg = _('HTTP request error (incomplete response; '
82 msg = _('HTTP request error (incomplete response; '
83 'expected %d bytes got %d)') % (e.expected,
83 'expected %d bytes got %d)') % (e.expected,
84 len(e.partial))
84 len(e.partial))
85 else:
85 else:
86 msg = _('HTTP request error (incomplete response)')
86 msg = _('HTTP request error (incomplete response)')
87
87
88 raise error.PeerTransportError(
88 raise error.PeerTransportError(
89 msg,
89 msg,
90 hint=_('this may be an intermittent network failure; '
90 hint=_('this may be an intermittent network failure; '
91 'if the error persists, consider contacting the '
91 'if the error persists, consider contacting the '
92 'network or server operator'))
92 'network or server operator'))
93 except httplib.HTTPException as e:
93 except httplib.HTTPException as e:
94 raise error.PeerTransportError(
94 raise error.PeerTransportError(
95 _('HTTP request error (%s)') % e,
95 _('HTTP request error (%s)') % e,
96 hint=_('this may be an intermittent network failure; '
96 hint=_('this may be an intermittent network failure; '
97 'if the error persists, consider contacting the '
97 'if the error persists, consider contacting the '
98 'network or server operator'))
98 'network or server operator'))
99
99
100 resp.__class__ = readerproxy
100 resp.__class__ = readerproxy
101
101
102 class _multifile(object):
102 class _multifile(object):
103 def __init__(self, *fileobjs):
103 def __init__(self, *fileobjs):
104 for f in fileobjs:
104 for f in fileobjs:
105 if not util.safehasattr(f, 'length'):
105 if not util.safehasattr(f, 'length'):
106 raise ValueError(
106 raise ValueError(
107 '_multifile only supports file objects that '
107 '_multifile only supports file objects that '
108 'have a length but this one does not:', type(f), f)
108 'have a length but this one does not:', type(f), f)
109 self._fileobjs = fileobjs
109 self._fileobjs = fileobjs
110 self._index = 0
110 self._index = 0
111
111
112 @property
112 @property
113 def length(self):
113 def length(self):
114 return sum(f.length for f in self._fileobjs)
114 return sum(f.length for f in self._fileobjs)
115
115
116 def read(self, amt=None):
116 def read(self, amt=None):
117 if amt <= 0:
117 if amt <= 0:
118 return ''.join(f.read() for f in self._fileobjs)
118 return ''.join(f.read() for f in self._fileobjs)
119 parts = []
119 parts = []
120 while amt and self._index < len(self._fileobjs):
120 while amt and self._index < len(self._fileobjs):
121 parts.append(self._fileobjs[self._index].read(amt))
121 parts.append(self._fileobjs[self._index].read(amt))
122 got = len(parts[-1])
122 got = len(parts[-1])
123 if got < amt:
123 if got < amt:
124 self._index += 1
124 self._index += 1
125 amt -= got
125 amt -= got
126 return ''.join(parts)
126 return ''.join(parts)
127
127
128 def seek(self, offset, whence=os.SEEK_SET):
128 def seek(self, offset, whence=os.SEEK_SET):
129 if whence != os.SEEK_SET:
129 if whence != os.SEEK_SET:
130 raise NotImplementedError(
130 raise NotImplementedError(
131 '_multifile does not support anything other'
131 '_multifile does not support anything other'
132 ' than os.SEEK_SET for whence on seek()')
132 ' than os.SEEK_SET for whence on seek()')
133 if offset != 0:
133 if offset != 0:
134 raise NotImplementedError(
134 raise NotImplementedError(
135 '_multifile only supports seeking to start, but that '
135 '_multifile only supports seeking to start, but that '
136 'could be fixed if you need it')
136 'could be fixed if you need it')
137 for f in self._fileobjs:
137 for f in self._fileobjs:
138 f.seek(0)
138 f.seek(0)
139 self._index = 0
139 self._index = 0
140
140
141 def makev1commandrequest(ui, requestbuilder, caps, capablefn,
141 def makev1commandrequest(ui, requestbuilder, caps, capablefn,
142 repobaseurl, cmd, args):
142 repobaseurl, cmd, args):
143 """Make an HTTP request to run a command for a version 1 client.
143 """Make an HTTP request to run a command for a version 1 client.
144
144
145 ``caps`` is a set of known server capabilities. The value may be
145 ``caps`` is a set of known server capabilities. The value may be
146 None if capabilities are not yet known.
146 None if capabilities are not yet known.
147
147
148 ``capablefn`` is a function to evaluate a capability.
148 ``capablefn`` is a function to evaluate a capability.
149
149
150 ``cmd``, ``args``, and ``data`` define the command, its arguments, and
150 ``cmd``, ``args``, and ``data`` define the command, its arguments, and
151 raw data to pass to it.
151 raw data to pass to it.
152 """
152 """
153 if cmd == 'pushkey':
153 if cmd == 'pushkey':
154 args['data'] = ''
154 args['data'] = ''
155 data = args.pop('data', None)
155 data = args.pop('data', None)
156 headers = args.pop('headers', {})
156 headers = args.pop('headers', {})
157
157
158 ui.debug("sending %s command\n" % cmd)
158 ui.debug("sending %s command\n" % cmd)
159 q = [('cmd', cmd)]
159 q = [('cmd', cmd)]
160 headersize = 0
160 headersize = 0
161 varyheaders = []
162 # Important: don't use self.capable() here or else you end up
161 # Important: don't use self.capable() here or else you end up
163 # with infinite recursion when trying to look up capabilities
162 # with infinite recursion when trying to look up capabilities
164 # for the first time.
163 # for the first time.
165 postargsok = caps is not None and 'httppostargs' in caps
164 postargsok = caps is not None and 'httppostargs' in caps
166
165
167 # Send arguments via POST.
166 # Send arguments via POST.
168 if postargsok and args:
167 if postargsok and args:
169 strargs = urlreq.urlencode(sorted(args.items()))
168 strargs = urlreq.urlencode(sorted(args.items()))
170 if not data:
169 if not data:
171 data = strargs
170 data = strargs
172 else:
171 else:
173 if isinstance(data, bytes):
172 if isinstance(data, bytes):
174 i = io.BytesIO(data)
173 i = io.BytesIO(data)
175 i.length = len(data)
174 i.length = len(data)
176 data = i
175 data = i
177 argsio = io.BytesIO(strargs)
176 argsio = io.BytesIO(strargs)
178 argsio.length = len(strargs)
177 argsio.length = len(strargs)
179 data = _multifile(argsio, data)
178 data = _multifile(argsio, data)
180 headers[r'X-HgArgs-Post'] = len(strargs)
179 headers[r'X-HgArgs-Post'] = len(strargs)
181 elif args:
180 elif args:
182 # Calling self.capable() can infinite loop if we are calling
181 # Calling self.capable() can infinite loop if we are calling
183 # "capabilities". But that command should never accept wire
182 # "capabilities". But that command should never accept wire
184 # protocol arguments. So this should never happen.
183 # protocol arguments. So this should never happen.
185 assert cmd != 'capabilities'
184 assert cmd != 'capabilities'
186 httpheader = capablefn('httpheader')
185 httpheader = capablefn('httpheader')
187 if httpheader:
186 if httpheader:
188 headersize = int(httpheader.split(',', 1)[0])
187 headersize = int(httpheader.split(',', 1)[0])
189
188
190 # Send arguments via HTTP headers.
189 # Send arguments via HTTP headers.
191 if headersize > 0:
190 if headersize > 0:
192 # The headers can typically carry more data than the URL.
191 # The headers can typically carry more data than the URL.
193 encargs = urlreq.urlencode(sorted(args.items()))
192 encargs = urlreq.urlencode(sorted(args.items()))
194 for header, value in encodevalueinheaders(encargs, 'X-HgArg',
193 for header, value in encodevalueinheaders(encargs, 'X-HgArg',
195 headersize):
194 headersize):
196 headers[header] = value
195 headers[header] = value
197 varyheaders.append(header)
198 # Send arguments via query string (Mercurial <1.9).
196 # Send arguments via query string (Mercurial <1.9).
199 else:
197 else:
200 q += sorted(args.items())
198 q += sorted(args.items())
201
199
202 qs = '?%s' % urlreq.urlencode(q)
200 qs = '?%s' % urlreq.urlencode(q)
203 cu = "%s%s" % (repobaseurl, qs)
201 cu = "%s%s" % (repobaseurl, qs)
204 size = 0
202 size = 0
205 if util.safehasattr(data, 'length'):
203 if util.safehasattr(data, 'length'):
206 size = data.length
204 size = data.length
207 elif data is not None:
205 elif data is not None:
208 size = len(data)
206 size = len(data)
209 if data is not None and r'Content-Type' not in headers:
207 if data is not None and r'Content-Type' not in headers:
210 headers[r'Content-Type'] = r'application/mercurial-0.1'
208 headers[r'Content-Type'] = r'application/mercurial-0.1'
211
209
212 # Tell the server we accept application/mercurial-0.2 and multiple
210 # Tell the server we accept application/mercurial-0.2 and multiple
213 # compression formats if the server is capable of emitting those
211 # compression formats if the server is capable of emitting those
214 # payloads.
212 # payloads.
215 protoparams = {'partial-pull'}
213 protoparams = {'partial-pull'}
216
214
217 mediatypes = set()
215 mediatypes = set()
218 if caps is not None:
216 if caps is not None:
219 mt = capablefn('httpmediatype')
217 mt = capablefn('httpmediatype')
220 if mt:
218 if mt:
221 protoparams.add('0.1')
219 protoparams.add('0.1')
222 mediatypes = set(mt.split(','))
220 mediatypes = set(mt.split(','))
223
221
224 if '0.2tx' in mediatypes:
222 if '0.2tx' in mediatypes:
225 protoparams.add('0.2')
223 protoparams.add('0.2')
226
224
227 if '0.2tx' in mediatypes and capablefn('compression'):
225 if '0.2tx' in mediatypes and capablefn('compression'):
228 # We /could/ compare supported compression formats and prune
226 # We /could/ compare supported compression formats and prune
229 # non-mutually supported or error if nothing is mutually supported.
227 # non-mutually supported or error if nothing is mutually supported.
230 # For now, send the full list to the server and have it error.
228 # For now, send the full list to the server and have it error.
231 comps = [e.wireprotosupport().name for e in
229 comps = [e.wireprotosupport().name for e in
232 util.compengines.supportedwireengines(util.CLIENTROLE)]
230 util.compengines.supportedwireengines(util.CLIENTROLE)]
233 protoparams.add('comp=%s' % ','.join(comps))
231 protoparams.add('comp=%s' % ','.join(comps))
234
232
235 if protoparams:
233 if protoparams:
236 protoheaders = encodevalueinheaders(' '.join(sorted(protoparams)),
234 protoheaders = encodevalueinheaders(' '.join(sorted(protoparams)),
237 'X-HgProto',
235 'X-HgProto',
238 headersize or 1024)
236 headersize or 1024)
239 for header, value in protoheaders:
237 for header, value in protoheaders:
240 headers[header] = value
238 headers[header] = value
239
240 varyheaders = []
241 for header in headers:
242 if header.lower().startswith(r'x-hg'):
241 varyheaders.append(header)
243 varyheaders.append(header)
242
244
243 if varyheaders:
245 if varyheaders:
244 headers[r'Vary'] = r','.join(varyheaders)
246 headers[r'Vary'] = r','.join(sorted(varyheaders))
245
247
246 req = requestbuilder(pycompat.strurl(cu), data, headers)
248 req = requestbuilder(pycompat.strurl(cu), data, headers)
247
249
248 if data is not None:
250 if data is not None:
249 ui.debug("sending %d bytes\n" % size)
251 ui.debug("sending %d bytes\n" % size)
250 req.add_unredirected_header(r'Content-Length', r'%d' % size)
252 req.add_unredirected_header(r'Content-Length', r'%d' % size)
251
253
252 return req, cu, qs
254 return req, cu, qs
253
255
254 def sendrequest(ui, opener, req):
256 def sendrequest(ui, opener, req):
255 """Send a prepared HTTP request.
257 """Send a prepared HTTP request.
256
258
257 Returns the response object.
259 Returns the response object.
258 """
260 """
259 if (ui.debugflag
261 if (ui.debugflag
260 and ui.configbool('devel', 'debug.peer-request')):
262 and ui.configbool('devel', 'debug.peer-request')):
261 dbg = ui.debug
263 dbg = ui.debug
262 line = 'devel-peer-request: %s\n'
264 line = 'devel-peer-request: %s\n'
263 dbg(line % '%s %s' % (req.get_method(), req.get_full_url()))
265 dbg(line % '%s %s' % (req.get_method(), req.get_full_url()))
264 hgargssize = None
266 hgargssize = None
265
267
266 for header, value in sorted(req.header_items()):
268 for header, value in sorted(req.header_items()):
267 if header.startswith('X-hgarg-'):
269 if header.startswith('X-hgarg-'):
268 if hgargssize is None:
270 if hgargssize is None:
269 hgargssize = 0
271 hgargssize = 0
270 hgargssize += len(value)
272 hgargssize += len(value)
271 else:
273 else:
272 dbg(line % ' %s %s' % (header, value))
274 dbg(line % ' %s %s' % (header, value))
273
275
274 if hgargssize is not None:
276 if hgargssize is not None:
275 dbg(line % ' %d bytes of commands arguments in headers'
277 dbg(line % ' %d bytes of commands arguments in headers'
276 % hgargssize)
278 % hgargssize)
277
279
278 if req.has_data():
280 if req.has_data():
279 data = req.get_data()
281 data = req.get_data()
280 length = getattr(data, 'length', None)
282 length = getattr(data, 'length', None)
281 if length is None:
283 if length is None:
282 length = len(data)
284 length = len(data)
283 dbg(line % ' %d bytes of data' % length)
285 dbg(line % ' %d bytes of data' % length)
284
286
285 start = util.timer()
287 start = util.timer()
286
288
287 try:
289 try:
288 res = opener.open(req)
290 res = opener.open(req)
289 except urlerr.httperror as inst:
291 except urlerr.httperror as inst:
290 if inst.code == 401:
292 if inst.code == 401:
291 raise error.Abort(_('authorization failed'))
293 raise error.Abort(_('authorization failed'))
292 raise
294 raise
293 except httplib.HTTPException as inst:
295 except httplib.HTTPException as inst:
294 ui.debug('http error requesting %s\n' %
296 ui.debug('http error requesting %s\n' %
295 util.hidepassword(req.get_full_url()))
297 util.hidepassword(req.get_full_url()))
296 ui.traceback()
298 ui.traceback()
297 raise IOError(None, inst)
299 raise IOError(None, inst)
298 finally:
300 finally:
299 if ui.configbool('devel', 'debug.peer-request'):
301 if ui.configbool('devel', 'debug.peer-request'):
300 dbg(line % ' finished in %.4f seconds (%s)'
302 dbg(line % ' finished in %.4f seconds (%s)'
301 % (util.timer() - start, res.code))
303 % (util.timer() - start, res.code))
302
304
303 # Insert error handlers for common I/O failures.
305 # Insert error handlers for common I/O failures.
304 _wraphttpresponse(res)
306 _wraphttpresponse(res)
305
307
306 return res
308 return res
307
309
308 def parsev1commandresponse(ui, baseurl, requrl, qs, resp, compressible):
310 def parsev1commandresponse(ui, baseurl, requrl, qs, resp, compressible):
309 # record the url we got redirected to
311 # record the url we got redirected to
310 respurl = pycompat.bytesurl(resp.geturl())
312 respurl = pycompat.bytesurl(resp.geturl())
311 if respurl.endswith(qs):
313 if respurl.endswith(qs):
312 respurl = respurl[:-len(qs)]
314 respurl = respurl[:-len(qs)]
313 if baseurl.rstrip('/') != respurl.rstrip('/'):
315 if baseurl.rstrip('/') != respurl.rstrip('/'):
314 if not ui.quiet:
316 if not ui.quiet:
315 ui.warn(_('real URL is %s\n') % respurl)
317 ui.warn(_('real URL is %s\n') % respurl)
316
318
317 try:
319 try:
318 proto = pycompat.bytesurl(resp.getheader(r'content-type', r''))
320 proto = pycompat.bytesurl(resp.getheader(r'content-type', r''))
319 except AttributeError:
321 except AttributeError:
320 proto = pycompat.bytesurl(resp.headers.get(r'content-type', r''))
322 proto = pycompat.bytesurl(resp.headers.get(r'content-type', r''))
321
323
322 safeurl = util.hidepassword(baseurl)
324 safeurl = util.hidepassword(baseurl)
323 if proto.startswith('application/hg-error'):
325 if proto.startswith('application/hg-error'):
324 raise error.OutOfBandError(resp.read())
326 raise error.OutOfBandError(resp.read())
325
327
326 # Pre 1.0 versions of Mercurial used text/plain and
328 # Pre 1.0 versions of Mercurial used text/plain and
327 # application/hg-changegroup. We don't support such old servers.
329 # application/hg-changegroup. We don't support such old servers.
328 if not proto.startswith('application/mercurial-'):
330 if not proto.startswith('application/mercurial-'):
329 ui.debug("requested URL: '%s'\n" % util.hidepassword(requrl))
331 ui.debug("requested URL: '%s'\n" % util.hidepassword(requrl))
330 raise error.RepoError(
332 raise error.RepoError(
331 _("'%s' does not appear to be an hg repository:\n"
333 _("'%s' does not appear to be an hg repository:\n"
332 "---%%<--- (%s)\n%s\n---%%<---\n")
334 "---%%<--- (%s)\n%s\n---%%<---\n")
333 % (safeurl, proto or 'no content-type', resp.read(1024)))
335 % (safeurl, proto or 'no content-type', resp.read(1024)))
334
336
335 try:
337 try:
336 version = proto.split('-', 1)[1]
338 version = proto.split('-', 1)[1]
337 version_info = tuple([int(n) for n in version.split('.')])
339 version_info = tuple([int(n) for n in version.split('.')])
338 except ValueError:
340 except ValueError:
339 raise error.RepoError(_("'%s' sent a broken Content-Type "
341 raise error.RepoError(_("'%s' sent a broken Content-Type "
340 "header (%s)") % (safeurl, proto))
342 "header (%s)") % (safeurl, proto))
341
343
342 # TODO consider switching to a decompression reader that uses
344 # TODO consider switching to a decompression reader that uses
343 # generators.
345 # generators.
344 if version_info == (0, 1):
346 if version_info == (0, 1):
345 if compressible:
347 if compressible:
346 resp = util.compengines['zlib'].decompressorreader(resp)
348 resp = util.compengines['zlib'].decompressorreader(resp)
347
349
348 elif version_info == (0, 2):
350 elif version_info == (0, 2):
349 # application/mercurial-0.2 always identifies the compression
351 # application/mercurial-0.2 always identifies the compression
350 # engine in the payload header.
352 # engine in the payload header.
351 elen = struct.unpack('B', resp.read(1))[0]
353 elen = struct.unpack('B', resp.read(1))[0]
352 ename = resp.read(elen)
354 ename = resp.read(elen)
353 engine = util.compengines.forwiretype(ename)
355 engine = util.compengines.forwiretype(ename)
354
356
355 resp = engine.decompressorreader(resp)
357 resp = engine.decompressorreader(resp)
356 else:
358 else:
357 raise error.RepoError(_("'%s' uses newer protocol %s") %
359 raise error.RepoError(_("'%s' uses newer protocol %s") %
358 (safeurl, version))
360 (safeurl, version))
359
361
360 return respurl, resp
362 return respurl, resp
361
363
362 class httppeer(wireproto.wirepeer):
364 class httppeer(wireproto.wirepeer):
363 def __init__(self, ui, path, url, opener, requestbuilder, caps):
365 def __init__(self, ui, path, url, opener, requestbuilder, caps):
364 self.ui = ui
366 self.ui = ui
365 self._path = path
367 self._path = path
366 self._url = url
368 self._url = url
367 self._caps = caps
369 self._caps = caps
368 self._urlopener = opener
370 self._urlopener = opener
369 self._requestbuilder = requestbuilder
371 self._requestbuilder = requestbuilder
370
372
371 def __del__(self):
373 def __del__(self):
372 for h in self._urlopener.handlers:
374 for h in self._urlopener.handlers:
373 h.close()
375 h.close()
374 getattr(h, "close_all", lambda: None)()
376 getattr(h, "close_all", lambda: None)()
375
377
376 # Begin of ipeerconnection interface.
378 # Begin of ipeerconnection interface.
377
379
378 def url(self):
380 def url(self):
379 return self._path
381 return self._path
380
382
381 def local(self):
383 def local(self):
382 return None
384 return None
383
385
384 def peer(self):
386 def peer(self):
385 return self
387 return self
386
388
387 def canpush(self):
389 def canpush(self):
388 return True
390 return True
389
391
390 def close(self):
392 def close(self):
391 pass
393 pass
392
394
393 # End of ipeerconnection interface.
395 # End of ipeerconnection interface.
394
396
395 # Begin of ipeercommands interface.
397 # Begin of ipeercommands interface.
396
398
397 def capabilities(self):
399 def capabilities(self):
398 return self._caps
400 return self._caps
399
401
400 # End of ipeercommands interface.
402 # End of ipeercommands interface.
401
403
402 # look up capabilities only when needed
404 # look up capabilities only when needed
403
405
404 def _callstream(self, cmd, _compressible=False, **args):
406 def _callstream(self, cmd, _compressible=False, **args):
405 args = pycompat.byteskwargs(args)
407 args = pycompat.byteskwargs(args)
406
408
407 req, cu, qs = makev1commandrequest(self.ui, self._requestbuilder,
409 req, cu, qs = makev1commandrequest(self.ui, self._requestbuilder,
408 self._caps, self.capable,
410 self._caps, self.capable,
409 self._url, cmd, args)
411 self._url, cmd, args)
410
412
411 resp = sendrequest(self.ui, self._urlopener, req)
413 resp = sendrequest(self.ui, self._urlopener, req)
412
414
413 self._url, resp = parsev1commandresponse(self.ui, self._url, cu, qs,
415 self._url, resp = parsev1commandresponse(self.ui, self._url, cu, qs,
414 resp, _compressible)
416 resp, _compressible)
415
417
416 return resp
418 return resp
417
419
418 def _call(self, cmd, **args):
420 def _call(self, cmd, **args):
419 fp = self._callstream(cmd, **args)
421 fp = self._callstream(cmd, **args)
420 try:
422 try:
421 return fp.read()
423 return fp.read()
422 finally:
424 finally:
423 # if using keepalive, allow connection to be reused
425 # if using keepalive, allow connection to be reused
424 fp.close()
426 fp.close()
425
427
426 def _callpush(self, cmd, cg, **args):
428 def _callpush(self, cmd, cg, **args):
427 # have to stream bundle to a temp file because we do not have
429 # have to stream bundle to a temp file because we do not have
428 # http 1.1 chunked transfer.
430 # http 1.1 chunked transfer.
429
431
430 types = self.capable('unbundle')
432 types = self.capable('unbundle')
431 try:
433 try:
432 types = types.split(',')
434 types = types.split(',')
433 except AttributeError:
435 except AttributeError:
434 # servers older than d1b16a746db6 will send 'unbundle' as a
436 # servers older than d1b16a746db6 will send 'unbundle' as a
435 # boolean capability. They only support headerless/uncompressed
437 # boolean capability. They only support headerless/uncompressed
436 # bundles.
438 # bundles.
437 types = [""]
439 types = [""]
438 for x in types:
440 for x in types:
439 if x in bundle2.bundletypes:
441 if x in bundle2.bundletypes:
440 type = x
442 type = x
441 break
443 break
442
444
443 tempname = bundle2.writebundle(self.ui, cg, None, type)
445 tempname = bundle2.writebundle(self.ui, cg, None, type)
444 fp = httpconnection.httpsendfile(self.ui, tempname, "rb")
446 fp = httpconnection.httpsendfile(self.ui, tempname, "rb")
445 headers = {r'Content-Type': r'application/mercurial-0.1'}
447 headers = {r'Content-Type': r'application/mercurial-0.1'}
446
448
447 try:
449 try:
448 r = self._call(cmd, data=fp, headers=headers, **args)
450 r = self._call(cmd, data=fp, headers=headers, **args)
449 vals = r.split('\n', 1)
451 vals = r.split('\n', 1)
450 if len(vals) < 2:
452 if len(vals) < 2:
451 raise error.ResponseError(_("unexpected response:"), r)
453 raise error.ResponseError(_("unexpected response:"), r)
452 return vals
454 return vals
453 except urlerr.httperror:
455 except urlerr.httperror:
454 # Catch and re-raise these so we don't try and treat them
456 # Catch and re-raise these so we don't try and treat them
455 # like generic socket errors. They lack any values in
457 # like generic socket errors. They lack any values in
456 # .args on Python 3 which breaks our socket.error block.
458 # .args on Python 3 which breaks our socket.error block.
457 raise
459 raise
458 except socket.error as err:
460 except socket.error as err:
459 if err.args[0] in (errno.ECONNRESET, errno.EPIPE):
461 if err.args[0] in (errno.ECONNRESET, errno.EPIPE):
460 raise error.Abort(_('push failed: %s') % err.args[1])
462 raise error.Abort(_('push failed: %s') % err.args[1])
461 raise error.Abort(err.args[1])
463 raise error.Abort(err.args[1])
462 finally:
464 finally:
463 fp.close()
465 fp.close()
464 os.unlink(tempname)
466 os.unlink(tempname)
465
467
466 def _calltwowaystream(self, cmd, fp, **args):
468 def _calltwowaystream(self, cmd, fp, **args):
467 fh = None
469 fh = None
468 fp_ = None
470 fp_ = None
469 filename = None
471 filename = None
470 try:
472 try:
471 # dump bundle to disk
473 # dump bundle to disk
472 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
474 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
473 fh = os.fdopen(fd, r"wb")
475 fh = os.fdopen(fd, r"wb")
474 d = fp.read(4096)
476 d = fp.read(4096)
475 while d:
477 while d:
476 fh.write(d)
478 fh.write(d)
477 d = fp.read(4096)
479 d = fp.read(4096)
478 fh.close()
480 fh.close()
479 # start http push
481 # start http push
480 fp_ = httpconnection.httpsendfile(self.ui, filename, "rb")
482 fp_ = httpconnection.httpsendfile(self.ui, filename, "rb")
481 headers = {r'Content-Type': r'application/mercurial-0.1'}
483 headers = {r'Content-Type': r'application/mercurial-0.1'}
482 return self._callstream(cmd, data=fp_, headers=headers, **args)
484 return self._callstream(cmd, data=fp_, headers=headers, **args)
483 finally:
485 finally:
484 if fp_ is not None:
486 if fp_ is not None:
485 fp_.close()
487 fp_.close()
486 if fh is not None:
488 if fh is not None:
487 fh.close()
489 fh.close()
488 os.unlink(filename)
490 os.unlink(filename)
489
491
490 def _callcompressable(self, cmd, **args):
492 def _callcompressable(self, cmd, **args):
491 return self._callstream(cmd, _compressible=True, **args)
493 return self._callstream(cmd, _compressible=True, **args)
492
494
493 def _abort(self, exception):
495 def _abort(self, exception):
494 raise exception
496 raise exception
495
497
496 # TODO implement interface for version 2 peers
498 # TODO implement interface for version 2 peers
497 class httpv2peer(object):
499 class httpv2peer(object):
498 def __init__(self, ui, repourl, opener):
500 def __init__(self, ui, repourl, opener):
499 self.ui = ui
501 self.ui = ui
500
502
501 if repourl.endswith('/'):
503 if repourl.endswith('/'):
502 repourl = repourl[:-1]
504 repourl = repourl[:-1]
503
505
504 self.url = repourl
506 self.url = repourl
505 self._opener = opener
507 self._opener = opener
506 # This is an its own attribute to facilitate extensions overriding
508 # This is an its own attribute to facilitate extensions overriding
507 # the default type.
509 # the default type.
508 self._requestbuilder = urlreq.request
510 self._requestbuilder = urlreq.request
509
511
510 def close(self):
512 def close(self):
511 pass
513 pass
512
514
513 # TODO require to be part of a batched primitive, use futures.
515 # TODO require to be part of a batched primitive, use futures.
514 def _call(self, name, **args):
516 def _call(self, name, **args):
515 """Call a wire protocol command with arguments."""
517 """Call a wire protocol command with arguments."""
516
518
517 # Having this early has a side-effect of importing wireprotov2server,
519 # Having this early has a side-effect of importing wireprotov2server,
518 # which has the side-effect of ensuring commands are registered.
520 # which has the side-effect of ensuring commands are registered.
519
521
520 # TODO modify user-agent to reflect v2.
522 # TODO modify user-agent to reflect v2.
521 headers = {
523 headers = {
522 r'Accept': wireprotov2server.FRAMINGTYPE,
524 r'Accept': wireprotov2server.FRAMINGTYPE,
523 r'Content-Type': wireprotov2server.FRAMINGTYPE,
525 r'Content-Type': wireprotov2server.FRAMINGTYPE,
524 }
526 }
525
527
526 # TODO permissions should come from capabilities results.
528 # TODO permissions should come from capabilities results.
527 permission = wireproto.commandsv2[name].permission
529 permission = wireproto.commandsv2[name].permission
528 if permission not in ('push', 'pull'):
530 if permission not in ('push', 'pull'):
529 raise error.ProgrammingError('unknown permission type: %s' %
531 raise error.ProgrammingError('unknown permission type: %s' %
530 permission)
532 permission)
531
533
532 permission = {
534 permission = {
533 'push': 'rw',
535 'push': 'rw',
534 'pull': 'ro',
536 'pull': 'ro',
535 }[permission]
537 }[permission]
536
538
537 url = '%s/api/%s/%s/%s' % (self.url, wireprotov2server.HTTPV2,
539 url = '%s/api/%s/%s/%s' % (self.url, wireprotov2server.HTTPV2,
538 permission, name)
540 permission, name)
539
541
540 # TODO this should be part of a generic peer for the frame-based
542 # TODO this should be part of a generic peer for the frame-based
541 # protocol.
543 # protocol.
542 reactor = wireprotoframing.clientreactor(hasmultiplesend=False,
544 reactor = wireprotoframing.clientreactor(hasmultiplesend=False,
543 buffersends=True)
545 buffersends=True)
544
546
545 request, action, meta = reactor.callcommand(name, args)
547 request, action, meta = reactor.callcommand(name, args)
546 assert action == 'noop'
548 assert action == 'noop'
547
549
548 action, meta = reactor.flushcommands()
550 action, meta = reactor.flushcommands()
549 assert action == 'sendframes'
551 assert action == 'sendframes'
550
552
551 body = b''.join(map(bytes, meta['framegen']))
553 body = b''.join(map(bytes, meta['framegen']))
552 req = self._requestbuilder(pycompat.strurl(url), body, headers)
554 req = self._requestbuilder(pycompat.strurl(url), body, headers)
553 req.add_unredirected_header(r'Content-Length', r'%d' % len(body))
555 req.add_unredirected_header(r'Content-Length', r'%d' % len(body))
554
556
555 # TODO unify this code with httppeer.
557 # TODO unify this code with httppeer.
556 try:
558 try:
557 res = self._opener.open(req)
559 res = self._opener.open(req)
558 except urlerr.httperror as e:
560 except urlerr.httperror as e:
559 if e.code == 401:
561 if e.code == 401:
560 raise error.Abort(_('authorization failed'))
562 raise error.Abort(_('authorization failed'))
561
563
562 raise
564 raise
563 except httplib.HTTPException as e:
565 except httplib.HTTPException as e:
564 self.ui.traceback()
566 self.ui.traceback()
565 raise IOError(None, e)
567 raise IOError(None, e)
566
568
567 # TODO validate response type, wrap response to handle I/O errors.
569 # TODO validate response type, wrap response to handle I/O errors.
568 # TODO more robust frame receiver.
570 # TODO more robust frame receiver.
569 results = []
571 results = []
570
572
571 while True:
573 while True:
572 frame = wireprotoframing.readframe(res)
574 frame = wireprotoframing.readframe(res)
573 if frame is None:
575 if frame is None:
574 break
576 break
575
577
576 self.ui.note(_('received %r\n') % frame)
578 self.ui.note(_('received %r\n') % frame)
577
579
578 action, meta = reactor.onframerecv(frame)
580 action, meta = reactor.onframerecv(frame)
579
581
580 if action == 'responsedata':
582 if action == 'responsedata':
581 if meta['cbor']:
583 if meta['cbor']:
582 payload = util.bytesio(meta['data'])
584 payload = util.bytesio(meta['data'])
583
585
584 decoder = cbor.CBORDecoder(payload)
586 decoder = cbor.CBORDecoder(payload)
585 while payload.tell() + 1 < len(meta['data']):
587 while payload.tell() + 1 < len(meta['data']):
586 results.append(decoder.decode())
588 results.append(decoder.decode())
587 else:
589 else:
588 results.append(meta['data'])
590 results.append(meta['data'])
589 else:
591 else:
590 error.ProgrammingError('unhandled action: %s' % action)
592 error.ProgrammingError('unhandled action: %s' % action)
591
593
592 return results
594 return results
593
595
594 def performhandshake(ui, url, opener, requestbuilder):
596 def performhandshake(ui, url, opener, requestbuilder):
595 # The handshake is a request to the capabilities command.
597 # The handshake is a request to the capabilities command.
596
598
597 caps = None
599 caps = None
598 def capable(x):
600 def capable(x):
599 raise error.ProgrammingError('should not be called')
601 raise error.ProgrammingError('should not be called')
600
602
601 req, requrl, qs = makev1commandrequest(ui, requestbuilder, caps,
603 req, requrl, qs = makev1commandrequest(ui, requestbuilder, caps,
602 capable, url, 'capabilities',
604 capable, url, 'capabilities',
603 {})
605 {})
604
606
605 resp = sendrequest(ui, opener, req)
607 resp = sendrequest(ui, opener, req)
606
608
607 respurl, resp = parsev1commandresponse(ui, url, requrl, qs, resp,
609 respurl, resp = parsev1commandresponse(ui, url, requrl, qs, resp,
608 compressible=False)
610 compressible=False)
609
611
610 try:
612 try:
611 rawcaps = resp.read()
613 rawcaps = resp.read()
612 finally:
614 finally:
613 resp.close()
615 resp.close()
614
616
615 return respurl, set(rawcaps.split())
617 return respurl, set(rawcaps.split())
616
618
617 def makepeer(ui, path, opener=None, requestbuilder=urlreq.request):
619 def makepeer(ui, path, opener=None, requestbuilder=urlreq.request):
618 """Construct an appropriate HTTP peer instance.
620 """Construct an appropriate HTTP peer instance.
619
621
620 ``opener`` is an ``url.opener`` that should be used to establish
622 ``opener`` is an ``url.opener`` that should be used to establish
621 connections, perform HTTP requests.
623 connections, perform HTTP requests.
622
624
623 ``requestbuilder`` is the type used for constructing HTTP requests.
625 ``requestbuilder`` is the type used for constructing HTTP requests.
624 It exists as an argument so extensions can override the default.
626 It exists as an argument so extensions can override the default.
625 """
627 """
626 u = util.url(path)
628 u = util.url(path)
627 if u.query or u.fragment:
629 if u.query or u.fragment:
628 raise error.Abort(_('unsupported URL component: "%s"') %
630 raise error.Abort(_('unsupported URL component: "%s"') %
629 (u.query or u.fragment))
631 (u.query or u.fragment))
630
632
631 # urllib cannot handle URLs with embedded user or passwd.
633 # urllib cannot handle URLs with embedded user or passwd.
632 url, authinfo = u.authinfo()
634 url, authinfo = u.authinfo()
633 ui.debug('using %s\n' % url)
635 ui.debug('using %s\n' % url)
634
636
635 opener = opener or urlmod.opener(ui, authinfo)
637 opener = opener or urlmod.opener(ui, authinfo)
636
638
637 respurl, caps = performhandshake(ui, url, opener, requestbuilder)
639 respurl, caps = performhandshake(ui, url, opener, requestbuilder)
638
640
639 return httppeer(ui, path, respurl, opener, requestbuilder, caps)
641 return httppeer(ui, path, respurl, opener, requestbuilder, caps)
640
642
641 def instance(ui, path, create):
643 def instance(ui, path, create):
642 if create:
644 if create:
643 raise error.Abort(_('cannot create new http repository'))
645 raise error.Abort(_('cannot create new http repository'))
644 try:
646 try:
645 if path.startswith('https:') and not urlmod.has_https:
647 if path.startswith('https:') and not urlmod.has_https:
646 raise error.Abort(_('Python support for SSL and HTTPS '
648 raise error.Abort(_('Python support for SSL and HTTPS '
647 'is not installed'))
649 'is not installed'))
648
650
649 inst = makepeer(ui, path)
651 inst = makepeer(ui, path)
650
652
651 return inst
653 return inst
652 except error.RepoError as httpexception:
654 except error.RepoError as httpexception:
653 try:
655 try:
654 r = statichttprepo.instance(ui, "static-" + path, create)
656 r = statichttprepo.instance(ui, "static-" + path, create)
655 ui.note(_('(falling back to static-http)\n'))
657 ui.note(_('(falling back to static-http)\n'))
656 return r
658 return r
657 except error.RepoError:
659 except error.RepoError:
658 raise httpexception # use the original http RepoError instead
660 raise httpexception # use the original http RepoError instead
@@ -1,934 +1,934
1 #require killdaemons serve zstd
1 #require killdaemons serve zstd
2
2
3 Client version is embedded in HTTP request and is effectively dynamic. Pin the
3 Client version is embedded in HTTP request and is effectively dynamic. Pin the
4 version so behavior is deterministic.
4 version so behavior is deterministic.
5
5
6 $ cat > fakeversion.py << EOF
6 $ cat > fakeversion.py << EOF
7 > from mercurial import util
7 > from mercurial import util
8 > util.version = lambda: '4.2'
8 > util.version = lambda: '4.2'
9 > EOF
9 > EOF
10
10
11 $ cat >> $HGRCPATH << EOF
11 $ cat >> $HGRCPATH << EOF
12 > [extensions]
12 > [extensions]
13 > fakeversion = `pwd`/fakeversion.py
13 > fakeversion = `pwd`/fakeversion.py
14 > [devel]
14 > [devel]
15 > legacy.exchange = phases
15 > legacy.exchange = phases
16 > EOF
16 > EOF
17
17
18 $ hg init server0
18 $ hg init server0
19 $ cd server0
19 $ cd server0
20 $ touch foo
20 $ touch foo
21 $ hg -q commit -A -m initial
21 $ hg -q commit -A -m initial
22
22
23 Also disable compression because zstd is optional and causes output to vary
23 Also disable compression because zstd is optional and causes output to vary
24 and because debugging partial responses is hard when compression is involved
24 and because debugging partial responses is hard when compression is involved
25
25
26 $ cat > .hg/hgrc << EOF
26 $ cat > .hg/hgrc << EOF
27 > [extensions]
27 > [extensions]
28 > badserver = $TESTDIR/badserverext.py
28 > badserver = $TESTDIR/badserverext.py
29 > [server]
29 > [server]
30 > compressionengines = none
30 > compressionengines = none
31 > EOF
31 > EOF
32
32
33 Failure to accept() socket should result in connection related error message
33 Failure to accept() socket should result in connection related error message
34
34
35 $ hg serve --config badserver.closebeforeaccept=true -p $HGPORT -d --pid-file=hg.pid
35 $ hg serve --config badserver.closebeforeaccept=true -p $HGPORT -d --pid-file=hg.pid
36 $ cat hg.pid > $DAEMON_PIDS
36 $ cat hg.pid > $DAEMON_PIDS
37
37
38 $ hg clone http://localhost:$HGPORT/ clone
38 $ hg clone http://localhost:$HGPORT/ clone
39 abort: error: $ECONNRESET$
39 abort: error: $ECONNRESET$
40 [255]
40 [255]
41
41
42 (The server exits on its own, but there is a race between that and starting a new server.
42 (The server exits on its own, but there is a race between that and starting a new server.
43 So ensure the process is dead.)
43 So ensure the process is dead.)
44
44
45 $ killdaemons.py $DAEMON_PIDS
45 $ killdaemons.py $DAEMON_PIDS
46
46
47 Failure immediately after accept() should yield connection related error message
47 Failure immediately after accept() should yield connection related error message
48
48
49 $ hg serve --config badserver.closeafteraccept=true -p $HGPORT -d --pid-file=hg.pid
49 $ hg serve --config badserver.closeafteraccept=true -p $HGPORT -d --pid-file=hg.pid
50 $ cat hg.pid > $DAEMON_PIDS
50 $ cat hg.pid > $DAEMON_PIDS
51
51
52 TODO: this usually outputs good results, but sometimes emits abort:
52 TODO: this usually outputs good results, but sometimes emits abort:
53 error: '' on FreeBSD and OS X.
53 error: '' on FreeBSD and OS X.
54 What we ideally want are:
54 What we ideally want are:
55
55
56 abort: error: $ECONNRESET$
56 abort: error: $ECONNRESET$
57
57
58 The flakiness in this output was observable easily with
58 The flakiness in this output was observable easily with
59 --runs-per-test=20 on macOS 10.12 during the freeze for 4.2.
59 --runs-per-test=20 on macOS 10.12 during the freeze for 4.2.
60 $ hg clone http://localhost:$HGPORT/ clone
60 $ hg clone http://localhost:$HGPORT/ clone
61 abort: error: * (glob)
61 abort: error: * (glob)
62 [255]
62 [255]
63
63
64 $ killdaemons.py $DAEMON_PIDS
64 $ killdaemons.py $DAEMON_PIDS
65
65
66 Failure to read all bytes in initial HTTP request should yield connection related error message
66 Failure to read all bytes in initial HTTP request should yield connection related error message
67
67
68 $ hg serve --config badserver.closeafterrecvbytes=1 -p $HGPORT -d --pid-file=hg.pid -E error.log
68 $ hg serve --config badserver.closeafterrecvbytes=1 -p $HGPORT -d --pid-file=hg.pid -E error.log
69 $ cat hg.pid > $DAEMON_PIDS
69 $ cat hg.pid > $DAEMON_PIDS
70
70
71 $ hg clone http://localhost:$HGPORT/ clone
71 $ hg clone http://localhost:$HGPORT/ clone
72 abort: error: bad HTTP status line: ''
72 abort: error: bad HTTP status line: ''
73 [255]
73 [255]
74
74
75 $ killdaemons.py $DAEMON_PIDS
75 $ killdaemons.py $DAEMON_PIDS
76
76
77 $ cat error.log
77 $ cat error.log
78 readline(1 from 65537) -> (1) G
78 readline(1 from 65537) -> (1) G
79 read limit reached; closing socket
79 read limit reached; closing socket
80
80
81 $ rm -f error.log
81 $ rm -f error.log
82
82
83 Same failure, but server reads full HTTP request line
83 Same failure, but server reads full HTTP request line
84
84
85 $ hg serve --config badserver.closeafterrecvbytes=40 -p $HGPORT -d --pid-file=hg.pid -E error.log
85 $ hg serve --config badserver.closeafterrecvbytes=40 -p $HGPORT -d --pid-file=hg.pid -E error.log
86 $ cat hg.pid > $DAEMON_PIDS
86 $ cat hg.pid > $DAEMON_PIDS
87 $ hg clone http://localhost:$HGPORT/ clone
87 $ hg clone http://localhost:$HGPORT/ clone
88 abort: error: bad HTTP status line: ''
88 abort: error: bad HTTP status line: ''
89 [255]
89 [255]
90
90
91 $ killdaemons.py $DAEMON_PIDS
91 $ killdaemons.py $DAEMON_PIDS
92
92
93 $ cat error.log
93 $ cat error.log
94 readline(40 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
94 readline(40 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
95 readline(7 from -1) -> (7) Accept-
95 readline(7 from -1) -> (7) Accept-
96 read limit reached; closing socket
96 read limit reached; closing socket
97
97
98 $ rm -f error.log
98 $ rm -f error.log
99
99
100 Failure on subsequent HTTP request on the same socket (cmd?batch)
100 Failure on subsequent HTTP request on the same socket (cmd?batch)
101
101
102 $ hg serve --config badserver.closeafterrecvbytes=256,223 -p $HGPORT -d --pid-file=hg.pid -E error.log
102 $ hg serve --config badserver.closeafterrecvbytes=256,223 -p $HGPORT -d --pid-file=hg.pid -E error.log
103 $ cat hg.pid > $DAEMON_PIDS
103 $ cat hg.pid > $DAEMON_PIDS
104 $ hg clone http://localhost:$HGPORT/ clone
104 $ hg clone http://localhost:$HGPORT/ clone
105 abort: error: bad HTTP status line: ''
105 abort: error: bad HTTP status line: ''
106 [255]
106 [255]
107
107
108 $ killdaemons.py $DAEMON_PIDS
108 $ killdaemons.py $DAEMON_PIDS
109
109
110 $ cat error.log
110 $ cat error.log
111 readline(256 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
111 readline(256 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
112 readline(223 from -1) -> (27) Accept-Encoding: identity\r\n
112 readline(223 from -1) -> (27) Accept-Encoding: identity\r\n
113 readline(196 from -1) -> (19) vary: X-HgProto-1\r\n
113 readline(196 from -1) -> (19) vary: X-HgProto-1\r\n
114 readline(177 from -1) -> (27) x-hgproto-1: partial-pull\r\n
114 readline(177 from -1) -> (27) x-hgproto-1: partial-pull\r\n
115 readline(150 from -1) -> (35) accept: application/mercurial-0.1\r\n
115 readline(150 from -1) -> (35) accept: application/mercurial-0.1\r\n
116 readline(115 from -1) -> (*) host: localhost:$HGPORT\r\n (glob)
116 readline(115 from -1) -> (*) host: localhost:$HGPORT\r\n (glob)
117 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
117 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
118 readline(* from -1) -> (2) \r\n (glob)
118 readline(* from -1) -> (2) \r\n (glob)
119 write(36) -> HTTP/1.1 200 Script output follows\r\n
119 write(36) -> HTTP/1.1 200 Script output follows\r\n
120 write(23) -> Server: badhttpserver\r\n
120 write(23) -> Server: badhttpserver\r\n
121 write(37) -> Date: $HTTP_DATE$\r\n
121 write(37) -> Date: $HTTP_DATE$\r\n
122 write(41) -> Content-Type: application/mercurial-0.1\r\n
122 write(41) -> Content-Type: application/mercurial-0.1\r\n
123 write(21) -> Content-Length: 436\r\n
123 write(21) -> Content-Length: 436\r\n
124 write(2) -> \r\n
124 write(2) -> \r\n
125 write(436) -> batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
125 write(436) -> batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
126 readline(4? from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n (glob)
126 readline(4? from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n (glob)
127 readline(1? from -1) -> (1?) Accept-Encoding* (glob)
127 readline(1? from -1) -> (1?) Accept-Encoding* (glob)
128 read limit reached; closing socket
128 read limit reached; closing socket
129 readline(223 from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
129 readline(223 from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
130 readline(197 from -1) -> (27) Accept-Encoding: identity\r\n
130 readline(197 from -1) -> (27) Accept-Encoding: identity\r\n
131 readline(170 from -1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
131 readline(170 from -1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
132 readline(141 from -1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
132 readline(141 from -1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
133 readline(100 from -1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
133 readline(100 from -1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
134 readline(39 from -1) -> (35) accept: application/mercurial-0.1\r\n
134 readline(39 from -1) -> (35) accept: application/mercurial-0.1\r\n
135 readline(4 from -1) -> (4) host
135 readline(4 from -1) -> (4) host
136 read limit reached; closing socket
136 read limit reached; closing socket
137
137
138 $ rm -f error.log
138 $ rm -f error.log
139
139
140 Failure to read getbundle HTTP request
140 Failure to read getbundle HTTP request
141
141
142 $ hg serve --config badserver.closeafterrecvbytes=354,317,304 -p $HGPORT -d --pid-file=hg.pid -E error.log
142 $ hg serve --config badserver.closeafterrecvbytes=354,317,304 -p $HGPORT -d --pid-file=hg.pid -E error.log
143 $ cat hg.pid > $DAEMON_PIDS
143 $ cat hg.pid > $DAEMON_PIDS
144 $ hg clone http://localhost:$HGPORT/ clone
144 $ hg clone http://localhost:$HGPORT/ clone
145 requesting all changes
145 requesting all changes
146 abort: error: bad HTTP status line: ''
146 abort: error: bad HTTP status line: ''
147 [255]
147 [255]
148
148
149 $ killdaemons.py $DAEMON_PIDS
149 $ killdaemons.py $DAEMON_PIDS
150
150
151 $ cat error.log
151 $ cat error.log
152 readline(1 from -1) -> (1) x (?)
152 readline(1 from -1) -> (1) x (?)
153 readline(1 from -1) -> (1) x (?)
153 readline(1 from -1) -> (1) x (?)
154 readline(354 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
154 readline(354 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
155 readline(321 from -1) -> (27) Accept-Encoding: identity\r\n
155 readline(321 from -1) -> (27) Accept-Encoding: identity\r\n
156 readline(294 from -1) -> (19) vary: X-HgProto-1\r\n
156 readline(294 from -1) -> (19) vary: X-HgProto-1\r\n
157 readline(275 from -1) -> (27) x-hgproto-1: partial-pull\r\n
157 readline(275 from -1) -> (27) x-hgproto-1: partial-pull\r\n
158 readline(248 from -1) -> (35) accept: application/mercurial-0.1\r\n
158 readline(248 from -1) -> (35) accept: application/mercurial-0.1\r\n
159 readline(213 from -1) -> (*) host: localhost:$HGPORT\r\n (glob)
159 readline(213 from -1) -> (*) host: localhost:$HGPORT\r\n (glob)
160 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
160 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
161 readline(* from -1) -> (2) \r\n (glob)
161 readline(* from -1) -> (2) \r\n (glob)
162 write(36) -> HTTP/1.1 200 Script output follows\r\n
162 write(36) -> HTTP/1.1 200 Script output follows\r\n
163 write(23) -> Server: badhttpserver\r\n
163 write(23) -> Server: badhttpserver\r\n
164 write(37) -> Date: $HTTP_DATE$\r\n
164 write(37) -> Date: $HTTP_DATE$\r\n
165 write(41) -> Content-Type: application/mercurial-0.1\r\n
165 write(41) -> Content-Type: application/mercurial-0.1\r\n
166 write(21) -> Content-Length: 436\r\n
166 write(21) -> Content-Length: 436\r\n
167 write(2) -> \r\n
167 write(2) -> \r\n
168 write(436) -> batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
168 write(436) -> batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
169 readline(13? from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n (glob)
169 readline(13? from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n (glob)
170 readline(1?? from -1) -> (27) Accept-Encoding: identity\r\n (glob)
170 readline(1?? from -1) -> (27) Accept-Encoding: identity\r\n (glob)
171 readline(8? from -1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
171 readline(8? from -1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
172 readline(5? from -1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
172 readline(5? from -1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
173 readline(1? from -1) -> (1?) x-hgproto-1:* (glob)
173 readline(1? from -1) -> (1?) x-hgproto-1:* (glob)
174 read limit reached; closing socket
174 read limit reached; closing socket
175 readline(317 from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
175 readline(317 from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
176 readline(291 from -1) -> (27) Accept-Encoding: identity\r\n
176 readline(291 from -1) -> (27) Accept-Encoding: identity\r\n
177 readline(264 from -1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
177 readline(264 from -1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
178 readline(235 from -1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
178 readline(235 from -1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
179 readline(194 from -1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
179 readline(194 from -1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
180 readline(133 from -1) -> (35) accept: application/mercurial-0.1\r\n
180 readline(133 from -1) -> (35) accept: application/mercurial-0.1\r\n
181 readline(98 from -1) -> (*) host: localhost:$HGPORT\r\n (glob)
181 readline(98 from -1) -> (*) host: localhost:$HGPORT\r\n (glob)
182 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
182 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
183 readline(* from -1) -> (2) \r\n (glob)
183 readline(* from -1) -> (2) \r\n (glob)
184 write(36) -> HTTP/1.1 200 Script output follows\r\n
184 write(36) -> HTTP/1.1 200 Script output follows\r\n
185 write(23) -> Server: badhttpserver\r\n
185 write(23) -> Server: badhttpserver\r\n
186 write(37) -> Date: $HTTP_DATE$\r\n
186 write(37) -> Date: $HTTP_DATE$\r\n
187 write(41) -> Content-Type: application/mercurial-0.1\r\n
187 write(41) -> Content-Type: application/mercurial-0.1\r\n
188 write(20) -> Content-Length: 42\r\n
188 write(20) -> Content-Length: 42\r\n
189 write(2) -> \r\n
189 write(2) -> \r\n
190 write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n;
190 write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n;
191 readline(* from 65537) -> (*) GET /?cmd=getbundle HTTP* (glob)
191 readline(* from 65537) -> (*) GET /?cmd=getbundle HTTP* (glob)
192 read limit reached; closing socket
192 read limit reached; closing socket
193 readline(304 from 65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
193 readline(304 from 65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
194 readline(274 from -1) -> (27) Accept-Encoding: identity\r\n
194 readline(274 from -1) -> (27) Accept-Encoding: identity\r\n
195 readline(247 from -1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
195 readline(247 from -1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
196 readline(218 from -1) -> (218) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtag
196 readline(218 from -1) -> (218) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtag
197 read limit reached; closing socket
197 read limit reached; closing socket
198
198
199 $ rm -f error.log
199 $ rm -f error.log
200
200
201 Now do a variation using POST to send arguments
201 Now do a variation using POST to send arguments
202
202
203 $ hg serve --config experimental.httppostargs=true --config badserver.closeafterrecvbytes=361,330 -p $HGPORT -d --pid-file=hg.pid -E error.log
203 $ hg serve --config experimental.httppostargs=true --config badserver.closeafterrecvbytes=375,344 -p $HGPORT -d --pid-file=hg.pid -E error.log
204 $ cat hg.pid > $DAEMON_PIDS
204 $ cat hg.pid > $DAEMON_PIDS
205
205
206 $ hg clone http://localhost:$HGPORT/ clone
206 $ hg clone http://localhost:$HGPORT/ clone
207 abort: error: bad HTTP status line: ''
207 abort: error: bad HTTP status line: ''
208 [255]
208 [255]
209
209
210 $ killdaemons.py $DAEMON_PIDS
210 $ killdaemons.py $DAEMON_PIDS
211
211
212 $ cat error.log
212 $ cat error.log
213 readline(361 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
213 readline(375 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
214 readline(328 from -1) -> (27) Accept-Encoding: identity\r\n
214 readline(342 from -1) -> (27) Accept-Encoding: identity\r\n
215 readline(301 from -1) -> (19) vary: X-HgProto-1\r\n
215 readline(315 from -1) -> (19) vary: X-HgProto-1\r\n
216 readline(282 from -1) -> (27) x-hgproto-1: partial-pull\r\n
216 readline(296 from -1) -> (27) x-hgproto-1: partial-pull\r\n
217 readline(255 from -1) -> (35) accept: application/mercurial-0.1\r\n
217 readline(269 from -1) -> (35) accept: application/mercurial-0.1\r\n
218 readline(220 from -1) -> (2?) host: localhost:$HGPORT\r\n (glob)
218 readline(234 from -1) -> (2?) host: localhost:$HGPORT\r\n (glob)
219 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
219 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
220 readline(* from -1) -> (2) \r\n (glob)
220 readline(* from -1) -> (2) \r\n (glob)
221 write(36) -> HTTP/1.1 200 Script output follows\r\n
221 write(36) -> HTTP/1.1 200 Script output follows\r\n
222 write(23) -> Server: badhttpserver\r\n
222 write(23) -> Server: badhttpserver\r\n
223 write(37) -> Date: $HTTP_DATE$\r\n
223 write(37) -> Date: $HTTP_DATE$\r\n
224 write(41) -> Content-Type: application/mercurial-0.1\r\n
224 write(41) -> Content-Type: application/mercurial-0.1\r\n
225 write(21) -> Content-Length: 449\r\n
225 write(21) -> Content-Length: 449\r\n
226 write(2) -> \r\n
226 write(2) -> \r\n
227 write(449) -> batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
227 write(449) -> batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
228 readline\(14[67] from 65537\) -> \(2[67]\) POST /\?cmd=batch HTTP/1.1\\r\\n (re)
228 readline(1?? from 65537) -> (27) POST /?cmd=batch HTTP/1.1\r\n (glob)
229 readline\(1(19|20) from -1\) -> \(27\) Accept-Encoding: identity\\r\\n (re)
229 readline(1?? from -1) -> (27) Accept-Encoding: identity\r\n (glob)
230 readline(9? from -1) -> (41) content-type: application/mercurial-0.1\r\n (glob)
230 readline(1?? from -1) -> (41) content-type: application/mercurial-0.1\r\n (glob)
231 readline(5? from -1) -> (19) vary: X-HgProto-1\r\n (glob)
231 readline(6? from -1) -> (33) vary: X-HgArgs-Post,X-HgProto-1\r\n (glob)
232 readline(3? from -1) -> (19) x-hgargs-post: 28\r\n (glob)
232 readline(3? from -1) -> (19) x-hgargs-post: 28\r\n (glob)
233 readline(1? from -1) -> (1?) x-hgproto-1: * (glob)
233 readline(1? from -1) -> (1?) x-hgproto-1: * (glob)
234 read limit reached; closing socket
234 read limit reached; closing socket
235 readline(330 from 65537) -> (27) POST /?cmd=batch HTTP/1.1\r\n
235 readline(344 from 65537) -> (27) POST /?cmd=batch HTTP/1.1\r\n
236 readline(303 from -1) -> (27) Accept-Encoding: identity\r\n
236 readline(317 from -1) -> (27) Accept-Encoding: identity\r\n
237 readline(276 from -1) -> (41) content-type: application/mercurial-0.1\r\n
237 readline(290 from -1) -> (41) content-type: application/mercurial-0.1\r\n
238 readline(235 from -1) -> (19) vary: X-HgProto-1\r\n
238 readline(249 from -1) -> (33) vary: X-HgArgs-Post,X-HgProto-1\r\n
239 readline(216 from -1) -> (19) x-hgargs-post: 28\r\n
239 readline(216 from -1) -> (19) x-hgargs-post: 28\r\n
240 readline(197 from -1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
240 readline(197 from -1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
241 readline(136 from -1) -> (35) accept: application/mercurial-0.1\r\n
241 readline(136 from -1) -> (35) accept: application/mercurial-0.1\r\n
242 readline(101 from -1) -> (20) content-length: 28\r\n
242 readline(101 from -1) -> (20) content-length: 28\r\n
243 readline(81 from -1) -> (*) host: localhost:$HGPORT\r\n (glob)
243 readline(81 from -1) -> (*) host: localhost:$HGPORT\r\n (glob)
244 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
244 readline(* from -1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
245 readline(* from -1) -> (2) \r\n (glob)
245 readline(* from -1) -> (2) \r\n (glob)
246 read(* from 28) -> (*) cmds=* (glob)
246 read(* from 28) -> (*) cmds=* (glob)
247 read limit reached, closing socket
247 read limit reached, closing socket
248 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
248 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
249
249
250 $ rm -f error.log
250 $ rm -f error.log
251
251
252 Now move on to partial server responses
252 Now move on to partial server responses
253
253
254 Server sends a single character from the HTTP response line
254 Server sends a single character from the HTTP response line
255
255
256 $ hg serve --config badserver.closeaftersendbytes=1 -p $HGPORT -d --pid-file=hg.pid -E error.log
256 $ hg serve --config badserver.closeaftersendbytes=1 -p $HGPORT -d --pid-file=hg.pid -E error.log
257 $ cat hg.pid > $DAEMON_PIDS
257 $ cat hg.pid > $DAEMON_PIDS
258
258
259 $ hg clone http://localhost:$HGPORT/ clone
259 $ hg clone http://localhost:$HGPORT/ clone
260 abort: error: bad HTTP status line: H
260 abort: error: bad HTTP status line: H
261 [255]
261 [255]
262
262
263 $ killdaemons.py $DAEMON_PIDS
263 $ killdaemons.py $DAEMON_PIDS
264
264
265 $ cat error.log
265 $ cat error.log
266 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
266 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
267 readline(-1) -> (27) Accept-Encoding: identity\r\n
267 readline(-1) -> (27) Accept-Encoding: identity\r\n
268 readline(-1) -> (19) vary: X-HgProto-1\r\n
268 readline(-1) -> (19) vary: X-HgProto-1\r\n
269 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
269 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
270 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
270 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
271 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
271 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
272 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
272 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
273 readline(-1) -> (2) \r\n
273 readline(-1) -> (2) \r\n
274 write(1 from 36) -> (0) H
274 write(1 from 36) -> (0) H
275 write limit reached; closing socket
275 write limit reached; closing socket
276 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
276 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
277
277
278 $ rm -f error.log
278 $ rm -f error.log
279
279
280 Server sends an incomplete capabilities response body
280 Server sends an incomplete capabilities response body
281
281
282 $ hg serve --config badserver.closeaftersendbytes=180 -p $HGPORT -d --pid-file=hg.pid -E error.log
282 $ hg serve --config badserver.closeaftersendbytes=180 -p $HGPORT -d --pid-file=hg.pid -E error.log
283 $ cat hg.pid > $DAEMON_PIDS
283 $ cat hg.pid > $DAEMON_PIDS
284
284
285 $ hg clone http://localhost:$HGPORT/ clone
285 $ hg clone http://localhost:$HGPORT/ clone
286 abort: HTTP request error (incomplete response; expected 416 bytes got 20)
286 abort: HTTP request error (incomplete response; expected 416 bytes got 20)
287 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
287 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
288 [255]
288 [255]
289
289
290 $ killdaemons.py $DAEMON_PIDS
290 $ killdaemons.py $DAEMON_PIDS
291
291
292 $ cat error.log
292 $ cat error.log
293 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
293 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
294 readline(-1) -> (27) Accept-Encoding: identity\r\n
294 readline(-1) -> (27) Accept-Encoding: identity\r\n
295 readline(-1) -> (19) vary: X-HgProto-1\r\n
295 readline(-1) -> (19) vary: X-HgProto-1\r\n
296 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
296 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
297 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
297 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
298 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
298 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
299 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
299 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
300 readline(-1) -> (2) \r\n
300 readline(-1) -> (2) \r\n
301 write(36 from 36) -> (144) HTTP/1.1 200 Script output follows\r\n
301 write(36 from 36) -> (144) HTTP/1.1 200 Script output follows\r\n
302 write(23 from 23) -> (121) Server: badhttpserver\r\n
302 write(23 from 23) -> (121) Server: badhttpserver\r\n
303 write(37 from 37) -> (84) Date: $HTTP_DATE$\r\n
303 write(37 from 37) -> (84) Date: $HTTP_DATE$\r\n
304 write(41 from 41) -> (43) Content-Type: application/mercurial-0.1\r\n
304 write(41 from 41) -> (43) Content-Type: application/mercurial-0.1\r\n
305 write(21 from 21) -> (22) Content-Length: 436\r\n
305 write(21 from 21) -> (22) Content-Length: 436\r\n
306 write(2 from 2) -> (20) \r\n
306 write(2 from 2) -> (20) \r\n
307 write(20 from 436) -> (0) batch branchmap bund
307 write(20 from 436) -> (0) batch branchmap bund
308 write limit reached; closing socket
308 write limit reached; closing socket
309
309
310 $ rm -f error.log
310 $ rm -f error.log
311
311
312 Server sends incomplete headers for batch request
312 Server sends incomplete headers for batch request
313
313
314 $ hg serve --config badserver.closeaftersendbytes=714 -p $HGPORT -d --pid-file=hg.pid -E error.log
314 $ hg serve --config badserver.closeaftersendbytes=714 -p $HGPORT -d --pid-file=hg.pid -E error.log
315 $ cat hg.pid > $DAEMON_PIDS
315 $ cat hg.pid > $DAEMON_PIDS
316
316
317 TODO this output is horrible
317 TODO this output is horrible
318
318
319 $ hg clone http://localhost:$HGPORT/ clone
319 $ hg clone http://localhost:$HGPORT/ clone
320 abort: 'http://localhost:$HGPORT/' does not appear to be an hg repository:
320 abort: 'http://localhost:$HGPORT/' does not appear to be an hg repository:
321 ---%<--- (applicat)
321 ---%<--- (applicat)
322
322
323 ---%<---
323 ---%<---
324 !
324 !
325 [255]
325 [255]
326
326
327 $ killdaemons.py $DAEMON_PIDS
327 $ killdaemons.py $DAEMON_PIDS
328
328
329 $ cat error.log
329 $ cat error.log
330 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
330 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
331 readline(-1) -> (27) Accept-Encoding: identity\r\n
331 readline(-1) -> (27) Accept-Encoding: identity\r\n
332 readline(-1) -> (19) vary: X-HgProto-1\r\n
332 readline(-1) -> (19) vary: X-HgProto-1\r\n
333 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
333 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
334 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
334 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
335 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
335 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
336 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
336 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
337 readline(-1) -> (2) \r\n
337 readline(-1) -> (2) \r\n
338 write(36 from 36) -> (678) HTTP/1.1 200 Script output follows\r\n
338 write(36 from 36) -> (678) HTTP/1.1 200 Script output follows\r\n
339 write(23 from 23) -> (655) Server: badhttpserver\r\n
339 write(23 from 23) -> (655) Server: badhttpserver\r\n
340 write(37 from 37) -> (618) Date: $HTTP_DATE$\r\n
340 write(37 from 37) -> (618) Date: $HTTP_DATE$\r\n
341 write(41 from 41) -> (577) Content-Type: application/mercurial-0.1\r\n
341 write(41 from 41) -> (577) Content-Type: application/mercurial-0.1\r\n
342 write(21 from 21) -> (556) Content-Length: 436\r\n
342 write(21 from 21) -> (556) Content-Length: 436\r\n
343 write(2 from 2) -> (554) \r\n
343 write(2 from 2) -> (554) \r\n
344 write(436 from 436) -> (118) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
344 write(436 from 436) -> (118) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
345 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
345 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
346 readline(-1) -> (27) Accept-Encoding: identity\r\n
346 readline(-1) -> (27) Accept-Encoding: identity\r\n
347 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
347 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
348 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
348 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
349 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
349 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
350 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
350 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
351 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
351 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
352 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
352 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
353 readline(-1) -> (2) \r\n
353 readline(-1) -> (2) \r\n
354 write(36 from 36) -> (82) HTTP/1.1 200 Script output follows\r\n
354 write(36 from 36) -> (82) HTTP/1.1 200 Script output follows\r\n
355 write(23 from 23) -> (59) Server: badhttpserver\r\n
355 write(23 from 23) -> (59) Server: badhttpserver\r\n
356 write(37 from 37) -> (22) Date: $HTTP_DATE$\r\n
356 write(37 from 37) -> (22) Date: $HTTP_DATE$\r\n
357 write(22 from 41) -> (0) Content-Type: applicat
357 write(22 from 41) -> (0) Content-Type: applicat
358 write limit reached; closing socket
358 write limit reached; closing socket
359 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
359 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
360
360
361 $ rm -f error.log
361 $ rm -f error.log
362
362
363 Server sends an incomplete HTTP response body to batch request
363 Server sends an incomplete HTTP response body to batch request
364
364
365 $ hg serve --config badserver.closeaftersendbytes=779 -p $HGPORT -d --pid-file=hg.pid -E error.log
365 $ hg serve --config badserver.closeaftersendbytes=779 -p $HGPORT -d --pid-file=hg.pid -E error.log
366 $ cat hg.pid > $DAEMON_PIDS
366 $ cat hg.pid > $DAEMON_PIDS
367
367
368 TODO client spews a stack due to uncaught ValueError in batch.results()
368 TODO client spews a stack due to uncaught ValueError in batch.results()
369 #if no-chg
369 #if no-chg
370 $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null
370 $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null
371 [1]
371 [1]
372 #else
372 #else
373 $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null
373 $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null
374 [255]
374 [255]
375 #endif
375 #endif
376
376
377 $ killdaemons.py $DAEMON_PIDS
377 $ killdaemons.py $DAEMON_PIDS
378
378
379 $ cat error.log
379 $ cat error.log
380 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
380 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
381 readline(-1) -> (27) Accept-Encoding: identity\r\n
381 readline(-1) -> (27) Accept-Encoding: identity\r\n
382 readline(-1) -> (19) vary: X-HgProto-1\r\n
382 readline(-1) -> (19) vary: X-HgProto-1\r\n
383 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
383 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
384 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
384 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
385 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
385 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
386 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
386 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
387 readline(-1) -> (2) \r\n
387 readline(-1) -> (2) \r\n
388 write(36 from 36) -> (743) HTTP/1.1 200 Script output follows\r\n
388 write(36 from 36) -> (743) HTTP/1.1 200 Script output follows\r\n
389 write(23 from 23) -> (720) Server: badhttpserver\r\n
389 write(23 from 23) -> (720) Server: badhttpserver\r\n
390 write(37 from 37) -> (683) Date: $HTTP_DATE$\r\n
390 write(37 from 37) -> (683) Date: $HTTP_DATE$\r\n
391 write(41 from 41) -> (642) Content-Type: application/mercurial-0.1\r\n
391 write(41 from 41) -> (642) Content-Type: application/mercurial-0.1\r\n
392 write(21 from 21) -> (621) Content-Length: 436\r\n
392 write(21 from 21) -> (621) Content-Length: 436\r\n
393 write(2 from 2) -> (619) \r\n
393 write(2 from 2) -> (619) \r\n
394 write(436 from 436) -> (183) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
394 write(436 from 436) -> (183) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
395 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
395 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
396 readline(-1) -> (27) Accept-Encoding: identity\r\n
396 readline(-1) -> (27) Accept-Encoding: identity\r\n
397 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
397 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
398 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
398 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
399 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
399 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
400 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
400 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
401 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
401 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
402 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
402 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
403 readline(-1) -> (2) \r\n
403 readline(-1) -> (2) \r\n
404 write(36 from 36) -> (147) HTTP/1.1 200 Script output follows\r\n
404 write(36 from 36) -> (147) HTTP/1.1 200 Script output follows\r\n
405 write(23 from 23) -> (124) Server: badhttpserver\r\n
405 write(23 from 23) -> (124) Server: badhttpserver\r\n
406 write(37 from 37) -> (87) Date: $HTTP_DATE$\r\n
406 write(37 from 37) -> (87) Date: $HTTP_DATE$\r\n
407 write(41 from 41) -> (46) Content-Type: application/mercurial-0.1\r\n
407 write(41 from 41) -> (46) Content-Type: application/mercurial-0.1\r\n
408 write(20 from 20) -> (26) Content-Length: 42\r\n
408 write(20 from 20) -> (26) Content-Length: 42\r\n
409 write(2 from 2) -> (24) \r\n
409 write(2 from 2) -> (24) \r\n
410 write(24 from 42) -> (0) 96ee1d7354c4ad7372047672
410 write(24 from 42) -> (0) 96ee1d7354c4ad7372047672
411 write limit reached; closing socket
411 write limit reached; closing socket
412
412
413 $ rm -f error.log
413 $ rm -f error.log
414
414
415 Server sends incomplete headers for getbundle response
415 Server sends incomplete headers for getbundle response
416
416
417 $ hg serve --config badserver.closeaftersendbytes=926 -p $HGPORT -d --pid-file=hg.pid -E error.log
417 $ hg serve --config badserver.closeaftersendbytes=926 -p $HGPORT -d --pid-file=hg.pid -E error.log
418 $ cat hg.pid > $DAEMON_PIDS
418 $ cat hg.pid > $DAEMON_PIDS
419
419
420 TODO this output is terrible
420 TODO this output is terrible
421
421
422 $ hg clone http://localhost:$HGPORT/ clone
422 $ hg clone http://localhost:$HGPORT/ clone
423 requesting all changes
423 requesting all changes
424 abort: 'http://localhost:$HGPORT/' does not appear to be an hg repository:
424 abort: 'http://localhost:$HGPORT/' does not appear to be an hg repository:
425 ---%<--- (application/mercuri)
425 ---%<--- (application/mercuri)
426
426
427 ---%<---
427 ---%<---
428 !
428 !
429 [255]
429 [255]
430
430
431 $ killdaemons.py $DAEMON_PIDS
431 $ killdaemons.py $DAEMON_PIDS
432
432
433 $ cat error.log
433 $ cat error.log
434 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
434 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
435 readline(-1) -> (27) Accept-Encoding: identity\r\n
435 readline(-1) -> (27) Accept-Encoding: identity\r\n
436 readline(-1) -> (19) vary: X-HgProto-1\r\n
436 readline(-1) -> (19) vary: X-HgProto-1\r\n
437 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
437 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
438 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
438 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
439 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
439 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
440 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
440 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
441 readline(-1) -> (2) \r\n
441 readline(-1) -> (2) \r\n
442 write(36 from 36) -> (890) HTTP/1.1 200 Script output follows\r\n
442 write(36 from 36) -> (890) HTTP/1.1 200 Script output follows\r\n
443 write(23 from 23) -> (867) Server: badhttpserver\r\n
443 write(23 from 23) -> (867) Server: badhttpserver\r\n
444 write(37 from 37) -> (830) Date: $HTTP_DATE$\r\n
444 write(37 from 37) -> (830) Date: $HTTP_DATE$\r\n
445 write(41 from 41) -> (789) Content-Type: application/mercurial-0.1\r\n
445 write(41 from 41) -> (789) Content-Type: application/mercurial-0.1\r\n
446 write(21 from 21) -> (768) Content-Length: 436\r\n
446 write(21 from 21) -> (768) Content-Length: 436\r\n
447 write(2 from 2) -> (766) \r\n
447 write(2 from 2) -> (766) \r\n
448 write(436 from 436) -> (330) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
448 write(436 from 436) -> (330) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
449 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
449 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
450 readline(-1) -> (27) Accept-Encoding: identity\r\n
450 readline(-1) -> (27) Accept-Encoding: identity\r\n
451 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
451 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
452 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
452 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
453 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
453 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
454 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
454 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
455 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
455 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
456 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
456 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
457 readline(-1) -> (2) \r\n
457 readline(-1) -> (2) \r\n
458 write(36 from 36) -> (294) HTTP/1.1 200 Script output follows\r\n
458 write(36 from 36) -> (294) HTTP/1.1 200 Script output follows\r\n
459 write(23 from 23) -> (271) Server: badhttpserver\r\n
459 write(23 from 23) -> (271) Server: badhttpserver\r\n
460 write(37 from 37) -> (234) Date: $HTTP_DATE$\r\n
460 write(37 from 37) -> (234) Date: $HTTP_DATE$\r\n
461 write(41 from 41) -> (193) Content-Type: application/mercurial-0.1\r\n
461 write(41 from 41) -> (193) Content-Type: application/mercurial-0.1\r\n
462 write(20 from 20) -> (173) Content-Length: 42\r\n
462 write(20 from 20) -> (173) Content-Length: 42\r\n
463 write(2 from 2) -> (171) \r\n
463 write(2 from 2) -> (171) \r\n
464 write(42 from 42) -> (129) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n;
464 write(42 from 42) -> (129) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n;
465 readline(65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
465 readline(65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
466 readline(-1) -> (27) Accept-Encoding: identity\r\n
466 readline(-1) -> (27) Accept-Encoding: identity\r\n
467 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
467 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
468 readline(-1) -> (461) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n
468 readline(-1) -> (461) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n
469 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
469 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
470 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
470 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
471 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
471 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
472 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
472 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
473 readline(-1) -> (2) \r\n
473 readline(-1) -> (2) \r\n
474 write(36 from 36) -> (93) HTTP/1.1 200 Script output follows\r\n
474 write(36 from 36) -> (93) HTTP/1.1 200 Script output follows\r\n
475 write(23 from 23) -> (70) Server: badhttpserver\r\n
475 write(23 from 23) -> (70) Server: badhttpserver\r\n
476 write(37 from 37) -> (33) Date: $HTTP_DATE$\r\n
476 write(37 from 37) -> (33) Date: $HTTP_DATE$\r\n
477 write(33 from 41) -> (0) Content-Type: application/mercuri
477 write(33 from 41) -> (0) Content-Type: application/mercuri
478 write limit reached; closing socket
478 write limit reached; closing socket
479 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
479 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
480
480
481 $ rm -f error.log
481 $ rm -f error.log
482
482
483 Server sends empty HTTP body for getbundle
483 Server sends empty HTTP body for getbundle
484
484
485 $ hg serve --config badserver.closeaftersendbytes=964 -p $HGPORT -d --pid-file=hg.pid -E error.log
485 $ hg serve --config badserver.closeaftersendbytes=964 -p $HGPORT -d --pid-file=hg.pid -E error.log
486 $ cat hg.pid > $DAEMON_PIDS
486 $ cat hg.pid > $DAEMON_PIDS
487
487
488 $ hg clone http://localhost:$HGPORT/ clone
488 $ hg clone http://localhost:$HGPORT/ clone
489 requesting all changes
489 requesting all changes
490 abort: HTTP request error (incomplete response)
490 abort: HTTP request error (incomplete response)
491 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
491 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
492 [255]
492 [255]
493
493
494 $ killdaemons.py $DAEMON_PIDS
494 $ killdaemons.py $DAEMON_PIDS
495
495
496 $ cat error.log
496 $ cat error.log
497 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
497 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
498 readline(-1) -> (27) Accept-Encoding: identity\r\n
498 readline(-1) -> (27) Accept-Encoding: identity\r\n
499 readline(-1) -> (19) vary: X-HgProto-1\r\n
499 readline(-1) -> (19) vary: X-HgProto-1\r\n
500 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
500 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
501 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
501 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
502 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
502 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
503 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
503 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
504 readline(-1) -> (2) \r\n
504 readline(-1) -> (2) \r\n
505 write(36 from 36) -> (928) HTTP/1.1 200 Script output follows\r\n
505 write(36 from 36) -> (928) HTTP/1.1 200 Script output follows\r\n
506 write(23 from 23) -> (905) Server: badhttpserver\r\n
506 write(23 from 23) -> (905) Server: badhttpserver\r\n
507 write(37 from 37) -> (868) Date: $HTTP_DATE$\r\n
507 write(37 from 37) -> (868) Date: $HTTP_DATE$\r\n
508 write(41 from 41) -> (827) Content-Type: application/mercurial-0.1\r\n
508 write(41 from 41) -> (827) Content-Type: application/mercurial-0.1\r\n
509 write(21 from 21) -> (806) Content-Length: 436\r\n
509 write(21 from 21) -> (806) Content-Length: 436\r\n
510 write(2 from 2) -> (804) \r\n
510 write(2 from 2) -> (804) \r\n
511 write(436 from 436) -> (368) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
511 write(436 from 436) -> (368) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
512 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
512 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
513 readline(-1) -> (27) Accept-Encoding: identity\r\n
513 readline(-1) -> (27) Accept-Encoding: identity\r\n
514 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
514 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
515 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
515 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
516 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
516 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
517 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
517 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
518 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
518 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
519 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
519 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
520 readline(-1) -> (2) \r\n
520 readline(-1) -> (2) \r\n
521 write(36 from 36) -> (332) HTTP/1.1 200 Script output follows\r\n
521 write(36 from 36) -> (332) HTTP/1.1 200 Script output follows\r\n
522 write(23 from 23) -> (309) Server: badhttpserver\r\n
522 write(23 from 23) -> (309) Server: badhttpserver\r\n
523 write(37 from 37) -> (272) Date: $HTTP_DATE$\r\n
523 write(37 from 37) -> (272) Date: $HTTP_DATE$\r\n
524 write(41 from 41) -> (231) Content-Type: application/mercurial-0.1\r\n
524 write(41 from 41) -> (231) Content-Type: application/mercurial-0.1\r\n
525 write(20 from 20) -> (211) Content-Length: 42\r\n
525 write(20 from 20) -> (211) Content-Length: 42\r\n
526 write(2 from 2) -> (209) \r\n
526 write(2 from 2) -> (209) \r\n
527 write(42 from 42) -> (167) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n;
527 write(42 from 42) -> (167) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n;
528 readline(65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
528 readline(65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
529 readline(-1) -> (27) Accept-Encoding: identity\r\n
529 readline(-1) -> (27) Accept-Encoding: identity\r\n
530 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
530 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
531 readline(-1) -> (461) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n
531 readline(-1) -> (461) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n
532 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
532 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
533 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
533 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
534 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
534 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
535 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
535 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
536 readline(-1) -> (2) \r\n
536 readline(-1) -> (2) \r\n
537 write(36 from 36) -> (131) HTTP/1.1 200 Script output follows\r\n
537 write(36 from 36) -> (131) HTTP/1.1 200 Script output follows\r\n
538 write(23 from 23) -> (108) Server: badhttpserver\r\n
538 write(23 from 23) -> (108) Server: badhttpserver\r\n
539 write(37 from 37) -> (71) Date: $HTTP_DATE$\r\n
539 write(37 from 37) -> (71) Date: $HTTP_DATE$\r\n
540 write(41 from 41) -> (30) Content-Type: application/mercurial-0.2\r\n
540 write(41 from 41) -> (30) Content-Type: application/mercurial-0.2\r\n
541 write(28 from 28) -> (2) Transfer-Encoding: chunked\r\n
541 write(28 from 28) -> (2) Transfer-Encoding: chunked\r\n
542 write(2 from 2) -> (0) \r\n
542 write(2 from 2) -> (0) \r\n
543 write limit reached; closing socket
543 write limit reached; closing socket
544 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
544 write(36) -> HTTP/1.1 500 Internal Server Error\r\n
545
545
546 $ rm -f error.log
546 $ rm -f error.log
547
547
548 Server sends partial compression string
548 Server sends partial compression string
549
549
550 $ hg serve --config badserver.closeaftersendbytes=988 -p $HGPORT -d --pid-file=hg.pid -E error.log
550 $ hg serve --config badserver.closeaftersendbytes=988 -p $HGPORT -d --pid-file=hg.pid -E error.log
551 $ cat hg.pid > $DAEMON_PIDS
551 $ cat hg.pid > $DAEMON_PIDS
552
552
553 $ hg clone http://localhost:$HGPORT/ clone
553 $ hg clone http://localhost:$HGPORT/ clone
554 requesting all changes
554 requesting all changes
555 abort: HTTP request error (incomplete response)
555 abort: HTTP request error (incomplete response)
556 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
556 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
557 [255]
557 [255]
558
558
559 $ killdaemons.py $DAEMON_PIDS
559 $ killdaemons.py $DAEMON_PIDS
560
560
561 $ cat error.log
561 $ cat error.log
562 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
562 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
563 readline(-1) -> (27) Accept-Encoding: identity\r\n
563 readline(-1) -> (27) Accept-Encoding: identity\r\n
564 readline(-1) -> (19) vary: X-HgProto-1\r\n
564 readline(-1) -> (19) vary: X-HgProto-1\r\n
565 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
565 readline(-1) -> (27) x-hgproto-1: partial-pull\r\n
566 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
566 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
567 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
567 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
568 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
568 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
569 readline(-1) -> (2) \r\n
569 readline(-1) -> (2) \r\n
570 write(36 from 36) -> (952) HTTP/1.1 200 Script output follows\r\n
570 write(36 from 36) -> (952) HTTP/1.1 200 Script output follows\r\n
571 write(23 from 23) -> (929) Server: badhttpserver\r\n
571 write(23 from 23) -> (929) Server: badhttpserver\r\n
572 write(37 from 37) -> (892) Date: $HTTP_DATE$\r\n
572 write(37 from 37) -> (892) Date: $HTTP_DATE$\r\n
573 write(41 from 41) -> (851) Content-Type: application/mercurial-0.1\r\n
573 write(41 from 41) -> (851) Content-Type: application/mercurial-0.1\r\n
574 write(21 from 21) -> (830) Content-Length: 436\r\n
574 write(21 from 21) -> (830) Content-Length: 436\r\n
575 write(2 from 2) -> (828) \r\n
575 write(2 from 2) -> (828) \r\n
576 write(436 from 436) -> (392) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
576 write(436 from 436) -> (392) batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
577 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
577 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
578 readline(-1) -> (27) Accept-Encoding: identity\r\n
578 readline(-1) -> (27) Accept-Encoding: identity\r\n
579 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
579 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
580 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
580 readline(-1) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n
581 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
581 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
582 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
582 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
583 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
583 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
584 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
584 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
585 readline(-1) -> (2) \r\n
585 readline(-1) -> (2) \r\n
586 write(36 from 36) -> (356) HTTP/1.1 200 Script output follows\r\n
586 write(36 from 36) -> (356) HTTP/1.1 200 Script output follows\r\n
587 write(23 from 23) -> (333) Server: badhttpserver\r\n
587 write(23 from 23) -> (333) Server: badhttpserver\r\n
588 write(37 from 37) -> (296) Date: $HTTP_DATE$\r\n
588 write(37 from 37) -> (296) Date: $HTTP_DATE$\r\n
589 write(41 from 41) -> (255) Content-Type: application/mercurial-0.1\r\n
589 write(41 from 41) -> (255) Content-Type: application/mercurial-0.1\r\n
590 write(20 from 20) -> (235) Content-Length: 42\r\n
590 write(20 from 20) -> (235) Content-Length: 42\r\n
591 write(2 from 2) -> (233) \r\n
591 write(2 from 2) -> (233) \r\n
592 write(42 from 42) -> (191) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n;
592 write(42 from 42) -> (191) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n;
593 readline(65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
593 readline(65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
594 readline(-1) -> (27) Accept-Encoding: identity\r\n
594 readline(-1) -> (27) Accept-Encoding: identity\r\n
595 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
595 readline(-1) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n
596 readline(-1) -> (461) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n
596 readline(-1) -> (461) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n
597 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
597 readline(-1) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
598 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
598 readline(-1) -> (35) accept: application/mercurial-0.1\r\n
599 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
599 readline(-1) -> (2?) host: localhost:$HGPORT\r\n (glob)
600 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
600 readline(-1) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n
601 readline(-1) -> (2) \r\n
601 readline(-1) -> (2) \r\n
602 write(36 from 36) -> (155) HTTP/1.1 200 Script output follows\r\n
602 write(36 from 36) -> (155) HTTP/1.1 200 Script output follows\r\n
603 write(23 from 23) -> (132) Server: badhttpserver\r\n
603 write(23 from 23) -> (132) Server: badhttpserver\r\n
604 write(37 from 37) -> (95) Date: $HTTP_DATE$\r\n
604 write(37 from 37) -> (95) Date: $HTTP_DATE$\r\n
605 write(41 from 41) -> (54) Content-Type: application/mercurial-0.2\r\n
605 write(41 from 41) -> (54) Content-Type: application/mercurial-0.2\r\n
606 write(28 from 28) -> (26) Transfer-Encoding: chunked\r\n
606 write(28 from 28) -> (26) Transfer-Encoding: chunked\r\n
607 write(2 from 2) -> (24) \r\n
607 write(2 from 2) -> (24) \r\n
608 write(6 from 6) -> (18) 1\\r\\n\x04\\r\\n (esc)
608 write(6 from 6) -> (18) 1\\r\\n\x04\\r\\n (esc)
609 write(9 from 9) -> (9) 4\r\nnone\r\n
609 write(9 from 9) -> (9) 4\r\nnone\r\n
610 write(9 from 9) -> (0) 4\r\nHG20\r\n
610 write(9 from 9) -> (0) 4\r\nHG20\r\n
611 write limit reached; closing socket
611 write limit reached; closing socket
612 write(27) -> 15\r\nInternal Server Error\r\n
612 write(27) -> 15\r\nInternal Server Error\r\n
613
613
614 $ rm -f error.log
614 $ rm -f error.log
615
615
616 Server sends partial bundle2 header magic
616 Server sends partial bundle2 header magic
617
617
618 $ hg serve --config badserver.closeaftersendbytes=985 -p $HGPORT -d --pid-file=hg.pid -E error.log
618 $ hg serve --config badserver.closeaftersendbytes=985 -p $HGPORT -d --pid-file=hg.pid -E error.log
619 $ cat hg.pid > $DAEMON_PIDS
619 $ cat hg.pid > $DAEMON_PIDS
620
620
621 $ hg clone http://localhost:$HGPORT/ clone
621 $ hg clone http://localhost:$HGPORT/ clone
622 requesting all changes
622 requesting all changes
623 abort: HTTP request error (incomplete response; expected 1 bytes got 3)
623 abort: HTTP request error (incomplete response; expected 1 bytes got 3)
624 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
624 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
625 [255]
625 [255]
626
626
627 $ killdaemons.py $DAEMON_PIDS
627 $ killdaemons.py $DAEMON_PIDS
628
628
629 $ tail -7 error.log
629 $ tail -7 error.log
630 write(28 from 28) -> (23) Transfer-Encoding: chunked\r\n
630 write(28 from 28) -> (23) Transfer-Encoding: chunked\r\n
631 write(2 from 2) -> (21) \r\n
631 write(2 from 2) -> (21) \r\n
632 write(6 from 6) -> (15) 1\\r\\n\x04\\r\\n (esc)
632 write(6 from 6) -> (15) 1\\r\\n\x04\\r\\n (esc)
633 write(9 from 9) -> (6) 4\r\nnone\r\n
633 write(9 from 9) -> (6) 4\r\nnone\r\n
634 write(6 from 9) -> (0) 4\r\nHG2
634 write(6 from 9) -> (0) 4\r\nHG2
635 write limit reached; closing socket
635 write limit reached; closing socket
636 write(27) -> 15\r\nInternal Server Error\r\n
636 write(27) -> 15\r\nInternal Server Error\r\n
637
637
638 $ rm -f error.log
638 $ rm -f error.log
639
639
640 Server sends incomplete bundle2 stream params length
640 Server sends incomplete bundle2 stream params length
641
641
642 $ hg serve --config badserver.closeaftersendbytes=994 -p $HGPORT -d --pid-file=hg.pid -E error.log
642 $ hg serve --config badserver.closeaftersendbytes=994 -p $HGPORT -d --pid-file=hg.pid -E error.log
643 $ cat hg.pid > $DAEMON_PIDS
643 $ cat hg.pid > $DAEMON_PIDS
644
644
645 $ hg clone http://localhost:$HGPORT/ clone
645 $ hg clone http://localhost:$HGPORT/ clone
646 requesting all changes
646 requesting all changes
647 abort: HTTP request error (incomplete response; expected 1 bytes got 3)
647 abort: HTTP request error (incomplete response; expected 1 bytes got 3)
648 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
648 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
649 [255]
649 [255]
650
650
651 $ killdaemons.py $DAEMON_PIDS
651 $ killdaemons.py $DAEMON_PIDS
652
652
653 $ tail -8 error.log
653 $ tail -8 error.log
654 write(28 from 28) -> (32) Transfer-Encoding: chunked\r\n
654 write(28 from 28) -> (32) Transfer-Encoding: chunked\r\n
655 write(2 from 2) -> (30) \r\n
655 write(2 from 2) -> (30) \r\n
656 write(6 from 6) -> (24) 1\\r\\n\x04\\r\\n (esc)
656 write(6 from 6) -> (24) 1\\r\\n\x04\\r\\n (esc)
657 write(9 from 9) -> (15) 4\r\nnone\r\n
657 write(9 from 9) -> (15) 4\r\nnone\r\n
658 write(9 from 9) -> (6) 4\r\nHG20\r\n
658 write(9 from 9) -> (6) 4\r\nHG20\r\n
659 write(6 from 9) -> (0) 4\\r\\n\x00\x00\x00 (esc)
659 write(6 from 9) -> (0) 4\\r\\n\x00\x00\x00 (esc)
660 write limit reached; closing socket
660 write limit reached; closing socket
661 write(27) -> 15\r\nInternal Server Error\r\n
661 write(27) -> 15\r\nInternal Server Error\r\n
662
662
663 $ rm -f error.log
663 $ rm -f error.log
664
664
665 Servers stops after bundle2 stream params header
665 Servers stops after bundle2 stream params header
666
666
667 $ hg serve --config badserver.closeaftersendbytes=997 -p $HGPORT -d --pid-file=hg.pid -E error.log
667 $ hg serve --config badserver.closeaftersendbytes=997 -p $HGPORT -d --pid-file=hg.pid -E error.log
668 $ cat hg.pid > $DAEMON_PIDS
668 $ cat hg.pid > $DAEMON_PIDS
669
669
670 $ hg clone http://localhost:$HGPORT/ clone
670 $ hg clone http://localhost:$HGPORT/ clone
671 requesting all changes
671 requesting all changes
672 abort: HTTP request error (incomplete response)
672 abort: HTTP request error (incomplete response)
673 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
673 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
674 [255]
674 [255]
675
675
676 $ killdaemons.py $DAEMON_PIDS
676 $ killdaemons.py $DAEMON_PIDS
677
677
678 $ tail -8 error.log
678 $ tail -8 error.log
679 write(28 from 28) -> (35) Transfer-Encoding: chunked\r\n
679 write(28 from 28) -> (35) Transfer-Encoding: chunked\r\n
680 write(2 from 2) -> (33) \r\n
680 write(2 from 2) -> (33) \r\n
681 write(6 from 6) -> (27) 1\\r\\n\x04\\r\\n (esc)
681 write(6 from 6) -> (27) 1\\r\\n\x04\\r\\n (esc)
682 write(9 from 9) -> (18) 4\r\nnone\r\n
682 write(9 from 9) -> (18) 4\r\nnone\r\n
683 write(9 from 9) -> (9) 4\r\nHG20\r\n
683 write(9 from 9) -> (9) 4\r\nHG20\r\n
684 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
684 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
685 write limit reached; closing socket
685 write limit reached; closing socket
686 write(27) -> 15\r\nInternal Server Error\r\n
686 write(27) -> 15\r\nInternal Server Error\r\n
687
687
688 $ rm -f error.log
688 $ rm -f error.log
689
689
690 Server stops sending after bundle2 part header length
690 Server stops sending after bundle2 part header length
691
691
692 $ hg serve --config badserver.closeaftersendbytes=1006 -p $HGPORT -d --pid-file=hg.pid -E error.log
692 $ hg serve --config badserver.closeaftersendbytes=1006 -p $HGPORT -d --pid-file=hg.pid -E error.log
693 $ cat hg.pid > $DAEMON_PIDS
693 $ cat hg.pid > $DAEMON_PIDS
694
694
695 $ hg clone http://localhost:$HGPORT/ clone
695 $ hg clone http://localhost:$HGPORT/ clone
696 requesting all changes
696 requesting all changes
697 abort: HTTP request error (incomplete response)
697 abort: HTTP request error (incomplete response)
698 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
698 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
699 [255]
699 [255]
700
700
701 $ killdaemons.py $DAEMON_PIDS
701 $ killdaemons.py $DAEMON_PIDS
702
702
703 $ tail -9 error.log
703 $ tail -9 error.log
704 write(28 from 28) -> (44) Transfer-Encoding: chunked\r\n
704 write(28 from 28) -> (44) Transfer-Encoding: chunked\r\n
705 write(2 from 2) -> (42) \r\n
705 write(2 from 2) -> (42) \r\n
706 write(6 from 6) -> (36) 1\\r\\n\x04\\r\\n (esc)
706 write(6 from 6) -> (36) 1\\r\\n\x04\\r\\n (esc)
707 write(9 from 9) -> (27) 4\r\nnone\r\n
707 write(9 from 9) -> (27) 4\r\nnone\r\n
708 write(9 from 9) -> (18) 4\r\nHG20\r\n
708 write(9 from 9) -> (18) 4\r\nHG20\r\n
709 write(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
709 write(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
710 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
710 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
711 write limit reached; closing socket
711 write limit reached; closing socket
712 write(27) -> 15\r\nInternal Server Error\r\n
712 write(27) -> 15\r\nInternal Server Error\r\n
713
713
714 $ rm -f error.log
714 $ rm -f error.log
715
715
716 Server stops sending after bundle2 part header
716 Server stops sending after bundle2 part header
717
717
718 $ hg serve --config badserver.closeaftersendbytes=1053 -p $HGPORT -d --pid-file=hg.pid -E error.log
718 $ hg serve --config badserver.closeaftersendbytes=1053 -p $HGPORT -d --pid-file=hg.pid -E error.log
719 $ cat hg.pid > $DAEMON_PIDS
719 $ cat hg.pid > $DAEMON_PIDS
720
720
721 $ hg clone http://localhost:$HGPORT/ clone
721 $ hg clone http://localhost:$HGPORT/ clone
722 requesting all changes
722 requesting all changes
723 adding changesets
723 adding changesets
724 transaction abort!
724 transaction abort!
725 rollback completed
725 rollback completed
726 abort: HTTP request error (incomplete response)
726 abort: HTTP request error (incomplete response)
727 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
727 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
728 [255]
728 [255]
729
729
730 $ killdaemons.py $DAEMON_PIDS
730 $ killdaemons.py $DAEMON_PIDS
731
731
732 $ tail -10 error.log
732 $ tail -10 error.log
733 write(28 from 28) -> (91) Transfer-Encoding: chunked\r\n
733 write(28 from 28) -> (91) Transfer-Encoding: chunked\r\n
734 write(2 from 2) -> (89) \r\n
734 write(2 from 2) -> (89) \r\n
735 write(6 from 6) -> (83) 1\\r\\n\x04\\r\\n (esc)
735 write(6 from 6) -> (83) 1\\r\\n\x04\\r\\n (esc)
736 write(9 from 9) -> (74) 4\r\nnone\r\n
736 write(9 from 9) -> (74) 4\r\nnone\r\n
737 write(9 from 9) -> (65) 4\r\nHG20\r\n
737 write(9 from 9) -> (65) 4\r\nHG20\r\n
738 write(9 from 9) -> (56) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
738 write(9 from 9) -> (56) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
739 write(9 from 9) -> (47) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
739 write(9 from 9) -> (47) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
740 write(47 from 47) -> (0) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
740 write(47 from 47) -> (0) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
741 write limit reached; closing socket
741 write limit reached; closing socket
742 write(27) -> 15\r\nInternal Server Error\r\n
742 write(27) -> 15\r\nInternal Server Error\r\n
743
743
744 $ rm -f error.log
744 $ rm -f error.log
745
745
746 Server stops after bundle2 part payload chunk size
746 Server stops after bundle2 part payload chunk size
747
747
748 $ hg serve --config badserver.closeaftersendbytes=1074 -p $HGPORT -d --pid-file=hg.pid -E error.log
748 $ hg serve --config badserver.closeaftersendbytes=1074 -p $HGPORT -d --pid-file=hg.pid -E error.log
749 $ cat hg.pid > $DAEMON_PIDS
749 $ cat hg.pid > $DAEMON_PIDS
750
750
751 $ hg clone http://localhost:$HGPORT/ clone
751 $ hg clone http://localhost:$HGPORT/ clone
752 requesting all changes
752 requesting all changes
753 adding changesets
753 adding changesets
754 transaction abort!
754 transaction abort!
755 rollback completed
755 rollback completed
756 abort: HTTP request error (incomplete response; expected 459 bytes got 7)
756 abort: HTTP request error (incomplete response; expected 459 bytes got 7)
757 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
757 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
758 [255]
758 [255]
759
759
760 $ killdaemons.py $DAEMON_PIDS
760 $ killdaemons.py $DAEMON_PIDS
761
761
762 $ tail -11 error.log
762 $ tail -11 error.log
763 write(2 from 2) -> (110) \r\n
763 write(2 from 2) -> (110) \r\n
764 write(6 from 6) -> (104) 1\\r\\n\x04\\r\\n (esc)
764 write(6 from 6) -> (104) 1\\r\\n\x04\\r\\n (esc)
765 write(9 from 9) -> (95) 4\r\nnone\r\n
765 write(9 from 9) -> (95) 4\r\nnone\r\n
766 write(9 from 9) -> (86) 4\r\nHG20\r\n
766 write(9 from 9) -> (86) 4\r\nHG20\r\n
767 write(9 from 9) -> (77) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
767 write(9 from 9) -> (77) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
768 write(9 from 9) -> (68) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
768 write(9 from 9) -> (68) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
769 write(47 from 47) -> (21) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
769 write(47 from 47) -> (21) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
770 write(9 from 9) -> (12) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
770 write(9 from 9) -> (12) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
771 write(12 from 473) -> (0) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1d (esc)
771 write(12 from 473) -> (0) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1d (esc)
772 write limit reached; closing socket
772 write limit reached; closing socket
773 write(27) -> 15\r\nInternal Server Error\r\n
773 write(27) -> 15\r\nInternal Server Error\r\n
774
774
775 $ rm -f error.log
775 $ rm -f error.log
776
776
777 Server stops sending in middle of bundle2 payload chunk
777 Server stops sending in middle of bundle2 payload chunk
778
778
779 $ hg serve --config badserver.closeaftersendbytes=1535 -p $HGPORT -d --pid-file=hg.pid -E error.log
779 $ hg serve --config badserver.closeaftersendbytes=1535 -p $HGPORT -d --pid-file=hg.pid -E error.log
780 $ cat hg.pid > $DAEMON_PIDS
780 $ cat hg.pid > $DAEMON_PIDS
781
781
782 $ hg clone http://localhost:$HGPORT/ clone
782 $ hg clone http://localhost:$HGPORT/ clone
783 requesting all changes
783 requesting all changes
784 adding changesets
784 adding changesets
785 transaction abort!
785 transaction abort!
786 rollback completed
786 rollback completed
787 abort: HTTP request error (incomplete response)
787 abort: HTTP request error (incomplete response)
788 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
788 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
789 [255]
789 [255]
790
790
791 $ killdaemons.py $DAEMON_PIDS
791 $ killdaemons.py $DAEMON_PIDS
792
792
793 $ tail -12 error.log
793 $ tail -12 error.log
794 write(28 from 28) -> (573) Transfer-Encoding: chunked\r\n
794 write(28 from 28) -> (573) Transfer-Encoding: chunked\r\n
795 write(2 from 2) -> (571) \r\n
795 write(2 from 2) -> (571) \r\n
796 write(6 from 6) -> (565) 1\\r\\n\x04\\r\\n (esc)
796 write(6 from 6) -> (565) 1\\r\\n\x04\\r\\n (esc)
797 write(9 from 9) -> (556) 4\r\nnone\r\n
797 write(9 from 9) -> (556) 4\r\nnone\r\n
798 write(9 from 9) -> (547) 4\r\nHG20\r\n
798 write(9 from 9) -> (547) 4\r\nHG20\r\n
799 write(9 from 9) -> (538) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
799 write(9 from 9) -> (538) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
800 write(9 from 9) -> (529) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
800 write(9 from 9) -> (529) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
801 write(47 from 47) -> (482) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
801 write(47 from 47) -> (482) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
802 write(9 from 9) -> (473) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
802 write(9 from 9) -> (473) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
803 write(473 from 473) -> (0) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
803 write(473 from 473) -> (0) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
804 write limit reached; closing socket
804 write limit reached; closing socket
805 write(27) -> 15\r\nInternal Server Error\r\n
805 write(27) -> 15\r\nInternal Server Error\r\n
806
806
807 $ rm -f error.log
807 $ rm -f error.log
808
808
809 Server stops sending after 0 length payload chunk size
809 Server stops sending after 0 length payload chunk size
810
810
811 $ hg serve --config badserver.closeaftersendbytes=1566 -p $HGPORT -d --pid-file=hg.pid -E error.log
811 $ hg serve --config badserver.closeaftersendbytes=1566 -p $HGPORT -d --pid-file=hg.pid -E error.log
812 $ cat hg.pid > $DAEMON_PIDS
812 $ cat hg.pid > $DAEMON_PIDS
813
813
814 $ hg clone http://localhost:$HGPORT/ clone
814 $ hg clone http://localhost:$HGPORT/ clone
815 requesting all changes
815 requesting all changes
816 adding changesets
816 adding changesets
817 adding manifests
817 adding manifests
818 adding file changes
818 adding file changes
819 added 1 changesets with 1 changes to 1 files
819 added 1 changesets with 1 changes to 1 files
820 transaction abort!
820 transaction abort!
821 rollback completed
821 rollback completed
822 abort: HTTP request error (incomplete response; expected 23 bytes got 9)
822 abort: HTTP request error (incomplete response; expected 23 bytes got 9)
823 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
823 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
824 [255]
824 [255]
825
825
826 $ killdaemons.py $DAEMON_PIDS
826 $ killdaemons.py $DAEMON_PIDS
827
827
828 $ tail -13 error.log
828 $ tail -13 error.log
829 write(6 from 6) -> (596) 1\\r\\n\x04\\r\\n (esc)
829 write(6 from 6) -> (596) 1\\r\\n\x04\\r\\n (esc)
830 write(9 from 9) -> (587) 4\r\nnone\r\n
830 write(9 from 9) -> (587) 4\r\nnone\r\n
831 write(9 from 9) -> (578) 4\r\nHG20\r\n
831 write(9 from 9) -> (578) 4\r\nHG20\r\n
832 write(9 from 9) -> (569) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
832 write(9 from 9) -> (569) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
833 write(9 from 9) -> (560) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
833 write(9 from 9) -> (560) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
834 write(47 from 47) -> (513) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
834 write(47 from 47) -> (513) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
835 write(9 from 9) -> (504) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
835 write(9 from 9) -> (504) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
836 write(473 from 473) -> (31) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
836 write(473 from 473) -> (31) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
837 write(9 from 9) -> (22) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
837 write(9 from 9) -> (22) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
838 write(9 from 9) -> (13) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
838 write(9 from 9) -> (13) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
839 write(13 from 38) -> (0) 20\\r\\n\x08LISTKEYS (esc)
839 write(13 from 38) -> (0) 20\\r\\n\x08LISTKEYS (esc)
840 write limit reached; closing socket
840 write limit reached; closing socket
841 write(27) -> 15\r\nInternal Server Error\r\n
841 write(27) -> 15\r\nInternal Server Error\r\n
842
842
843 $ rm -f error.log
843 $ rm -f error.log
844
844
845 Server stops sending after 0 part bundle part header (indicating end of bundle2 payload)
845 Server stops sending after 0 part bundle part header (indicating end of bundle2 payload)
846 This is before the 0 size chunked transfer part that signals end of HTTP response.
846 This is before the 0 size chunked transfer part that signals end of HTTP response.
847
847
848 # $ hg serve --config badserver.closeaftersendbytes=1741 -p $HGPORT -d --pid-file=hg.pid -E error.log
848 # $ hg serve --config badserver.closeaftersendbytes=1741 -p $HGPORT -d --pid-file=hg.pid -E error.log
849 $ hg serve --config badserver.closeaftersendbytes=1848 -p $HGPORT -d --pid-file=hg.pid -E error.log
849 $ hg serve --config badserver.closeaftersendbytes=1848 -p $HGPORT -d --pid-file=hg.pid -E error.log
850 $ cat hg.pid > $DAEMON_PIDS
850 $ cat hg.pid > $DAEMON_PIDS
851
851
852 $ hg clone http://localhost:$HGPORT/ clone
852 $ hg clone http://localhost:$HGPORT/ clone
853 requesting all changes
853 requesting all changes
854 adding changesets
854 adding changesets
855 adding manifests
855 adding manifests
856 adding file changes
856 adding file changes
857 added 1 changesets with 1 changes to 1 files
857 added 1 changesets with 1 changes to 1 files
858 new changesets 96ee1d7354c4
858 new changesets 96ee1d7354c4
859 updating to branch default
859 updating to branch default
860 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
860 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
861
861
862 $ killdaemons.py $DAEMON_PIDS
862 $ killdaemons.py $DAEMON_PIDS
863
863
864 $ tail -22 error.log
864 $ tail -22 error.log
865 write(9 from 9) -> (851) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
865 write(9 from 9) -> (851) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
866 write(9 from 9) -> (842) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
866 write(9 from 9) -> (842) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
867 write(47 from 47) -> (795) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
867 write(47 from 47) -> (795) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
868 write(9 from 9) -> (786) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
868 write(9 from 9) -> (786) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
869 write(473 from 473) -> (313) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
869 write(473 from 473) -> (313) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
870 write(9 from 9) -> (304) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
870 write(9 from 9) -> (304) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
871 write(9 from 9) -> (295) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
871 write(9 from 9) -> (295) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
872 write(38 from 38) -> (257) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
872 write(38 from 38) -> (257) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
873 write(9 from 9) -> (248) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
873 write(9 from 9) -> (248) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
874 write(64 from 64) -> (184) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
874 write(64 from 64) -> (184) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
875 write(9 from 9) -> (175) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
875 write(9 from 9) -> (175) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
876 write(9 from 9) -> (166) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
876 write(9 from 9) -> (166) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
877 write(41 from 41) -> (125) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
877 write(41 from 41) -> (125) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
878 write(9 from 9) -> (116) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
878 write(9 from 9) -> (116) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
879 write(9 from 9) -> (107) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
879 write(9 from 9) -> (107) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
880 write(35 from 35) -> (72) 1d\\r\\n\x16CACHE:REV-BRANCH-CACHE\x00\x00\x00\x03\x00\x00\\r\\n (esc)
880 write(35 from 35) -> (72) 1d\\r\\n\x16CACHE:REV-BRANCH-CACHE\x00\x00\x00\x03\x00\x00\\r\\n (esc)
881 write(9 from 9) -> (63) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
881 write(9 from 9) -> (63) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
882 write(45 from 45) -> (18) 27\\r\\n\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00default\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\\r\\n (esc)
882 write(45 from 45) -> (18) 27\\r\\n\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00default\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\\r\\n (esc)
883 write(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
883 write(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
884 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
884 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
885 write limit reached; closing socket
885 write limit reached; closing socket
886 write(27) -> 15\r\nInternal Server Error\r\n
886 write(27) -> 15\r\nInternal Server Error\r\n
887
887
888 $ rm -f error.log
888 $ rm -f error.log
889 $ rm -rf clone
889 $ rm -rf clone
890
890
891 Server sends a size 0 chunked-transfer size without terminating \r\n
891 Server sends a size 0 chunked-transfer size without terminating \r\n
892
892
893 $ hg serve --config badserver.closeaftersendbytes=1851 -p $HGPORT -d --pid-file=hg.pid -E error.log
893 $ hg serve --config badserver.closeaftersendbytes=1851 -p $HGPORT -d --pid-file=hg.pid -E error.log
894 $ cat hg.pid > $DAEMON_PIDS
894 $ cat hg.pid > $DAEMON_PIDS
895
895
896 $ hg clone http://localhost:$HGPORT/ clone
896 $ hg clone http://localhost:$HGPORT/ clone
897 requesting all changes
897 requesting all changes
898 adding changesets
898 adding changesets
899 adding manifests
899 adding manifests
900 adding file changes
900 adding file changes
901 added 1 changesets with 1 changes to 1 files
901 added 1 changesets with 1 changes to 1 files
902 new changesets 96ee1d7354c4
902 new changesets 96ee1d7354c4
903 updating to branch default
903 updating to branch default
904 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
904 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
905
905
906 $ killdaemons.py $DAEMON_PIDS
906 $ killdaemons.py $DAEMON_PIDS
907
907
908 $ tail -23 error.log
908 $ tail -23 error.log
909 write(9 from 9) -> (854) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
909 write(9 from 9) -> (854) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
910 write(9 from 9) -> (845) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
910 write(9 from 9) -> (845) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
911 write(47 from 47) -> (798) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
911 write(47 from 47) -> (798) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
912 write(9 from 9) -> (789) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
912 write(9 from 9) -> (789) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
913 write(473 from 473) -> (316) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
913 write(473 from 473) -> (316) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
914 write(9 from 9) -> (307) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
914 write(9 from 9) -> (307) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
915 write(9 from 9) -> (298) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
915 write(9 from 9) -> (298) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
916 write(38 from 38) -> (260) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
916 write(38 from 38) -> (260) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
917 write(9 from 9) -> (251) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
917 write(9 from 9) -> (251) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
918 write(64 from 64) -> (187) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
918 write(64 from 64) -> (187) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
919 write(9 from 9) -> (178) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
919 write(9 from 9) -> (178) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
920 write(9 from 9) -> (169) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
920 write(9 from 9) -> (169) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
921 write(41 from 41) -> (128) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
921 write(41 from 41) -> (128) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
922 write(9 from 9) -> (119) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
922 write(9 from 9) -> (119) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
923 write(9 from 9) -> (110) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
923 write(9 from 9) -> (110) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
924 write(35 from 35) -> (75) 1d\\r\\n\x16CACHE:REV-BRANCH-CACHE\x00\x00\x00\x03\x00\x00\\r\\n (esc)
924 write(35 from 35) -> (75) 1d\\r\\n\x16CACHE:REV-BRANCH-CACHE\x00\x00\x00\x03\x00\x00\\r\\n (esc)
925 write(9 from 9) -> (66) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
925 write(9 from 9) -> (66) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
926 write(45 from 45) -> (21) 27\\r\\n\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00default\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\\r\\n (esc)
926 write(45 from 45) -> (21) 27\\r\\n\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00default\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\\r\\n (esc)
927 write(9 from 9) -> (12) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
927 write(9 from 9) -> (12) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
928 write(9 from 9) -> (3) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
928 write(9 from 9) -> (3) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
929 write(3 from 5) -> (0) 0\r\n
929 write(3 from 5) -> (0) 0\r\n
930 write limit reached; closing socket
930 write limit reached; closing socket
931 write(27) -> 15\r\nInternal Server Error\r\n
931 write(27) -> 15\r\nInternal Server Error\r\n
932
932
933 $ rm -f error.log
933 $ rm -f error.log
934 $ rm -rf clone
934 $ rm -rf clone
General Comments 0
You need to be logged in to leave comments. Login now