Merge lp:~mbp/bzr/integration-2.4 into lp:bzr/2.4

Proposed by Martin Pool
Status: Merged
Merged at revision: 6025
Proposed branch: lp:~mbp/bzr/integration-2.4
Merge into: lp:bzr/2.4
Diff against target: 150 lines (+91/-2)
5 files modified
bzrlib/errors.py (+13/-0)
bzrlib/tests/test_http.py (+66/-0)
bzrlib/transport/http/__init__.py (+1/-1)
bzrlib/transport/http/response.py (+8/-1)
doc/en/release-notes/bzr-2.3.txt (+3/-0)
To merge this branch: bzr merge lp:~mbp/bzr/integration-2.4
Reviewer Review Type Date Requested Status
bzr-core Pending
Review via email: mp+69955@code.launchpad.net

Description of the change

merge up bzr 2.3

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/errors.py'
--- bzrlib/errors.py 2011-06-21 11:34:52 +0000
+++ bzrlib/errors.py 2011-08-01 06:37:14 +0000
@@ -1737,6 +1737,19 @@
1737 InvalidHttpResponse.__init__(self, path, msg)1737 InvalidHttpResponse.__init__(self, path, msg)
17381738
17391739
1740class HttpBoundaryMissing(InvalidHttpResponse):
1741 """A multipart response ends with no boundary marker.
1742
1743 This is a special case caused by buggy proxies, described in
1744 <https://bugs.launchpad.net/bzr/+bug/198646>.
1745 """
1746
1747 _fmt = "HTTP MIME Boundary missing for %(path)s: %(msg)s"
1748
1749 def __init__(self, path, msg):
1750 InvalidHttpResponse.__init__(self, path, msg)
1751
1752
1740class InvalidHttpContentType(InvalidHttpResponse):1753class InvalidHttpContentType(InvalidHttpResponse):
17411754
1742 _fmt = 'Invalid http Content-type "%(ctype)s" for %(path)s: %(msg)s'1755 _fmt = 'Invalid http Content-type "%(ctype)s" for %(path)s: %(msg)s'
17431756
=== modified file 'bzrlib/tests/test_http.py'
--- bzrlib/tests/test_http.py 2011-06-07 12:25:45 +0000
+++ bzrlib/tests/test_http.py 2011-08-01 06:37:14 +0000
@@ -1048,6 +1048,72 @@
1048 self.assertEqual('single', t._range_hint)1048 self.assertEqual('single', t._range_hint)
10491049
10501050
1051class TruncatedBeforeBoundaryRequestHandler(
1052 http_server.TestingHTTPRequestHandler):
1053 """Truncation before a boundary, like in bug 198646"""
1054
1055 _truncated_ranges = 1
1056
1057 def get_multiple_ranges(self, file, file_size, ranges):
1058 self.send_response(206)
1059 self.send_header('Accept-Ranges', 'bytes')
1060 boundary = 'tagada'
1061 self.send_header('Content-Type',
1062 'multipart/byteranges; boundary=%s' % boundary)
1063 boundary_line = '--%s\r\n' % boundary
1064 # Calculate the Content-Length
1065 content_length = 0
1066 for (start, end) in ranges:
1067 content_length += len(boundary_line)
1068 content_length += self._header_line_length(
1069 'Content-type', 'application/octet-stream')
1070 content_length += self._header_line_length(
1071 'Content-Range', 'bytes %d-%d/%d' % (start, end, file_size))
1072 content_length += len('\r\n') # end headers
1073 content_length += end - start # + 1
1074 content_length += len(boundary_line)
1075 self.send_header('Content-length', content_length)
1076 self.end_headers()
1077
1078 # Send the multipart body
1079 cur = 0
1080 for (start, end) in ranges:
1081 if cur + self._truncated_ranges >= len(ranges):
1082 # Abruptly ends the response and close the connection
1083 self.close_connection = 1
1084 return
1085 self.wfile.write(boundary_line)
1086 self.send_header('Content-type', 'application/octet-stream')
1087 self.send_header('Content-Range', 'bytes %d-%d/%d'
1088 % (start, end, file_size))
1089 self.end_headers()
1090 self.send_range_content(file, start, end - start + 1)
1091 cur += 1
1092 # Final boundary
1093 self.wfile.write(boundary_line)
1094
1095
1096class TestTruncatedBeforeBoundary(TestSpecificRequestHandler):
1097 """Tests the case of bug 198646, disconnecting before a boundary."""
1098
1099 _req_handler_class = TruncatedBeforeBoundaryRequestHandler
1100
1101 def setUp(self):
1102 super(TestTruncatedBeforeBoundary, self).setUp()
1103 self.build_tree_contents([('a', '0123456789')],)
1104
1105 def test_readv_with_short_reads(self):
1106 server = self.get_readonly_server()
1107 t = self.get_readonly_transport()
1108 # Force separate ranges for each offset
1109 t._bytes_to_read_before_seek = 0
1110 ireadv = iter(t.readv('a', ((0, 1), (2, 1), (4, 2), (9, 1))))
1111 self.assertEqual((0, '0'), ireadv.next())
1112 self.assertEqual((2, '2'), ireadv.next())
1113 self.assertEqual((4, '45'), ireadv.next())
1114 self.assertEqual((9, '9'), ireadv.next())
1115
1116
1051class LimitedRangeRequestHandler(http_server.TestingHTTPRequestHandler):1117class LimitedRangeRequestHandler(http_server.TestingHTTPRequestHandler):
1052 """Errors out when range specifiers exceed the limit"""1118 """Errors out when range specifiers exceed the limit"""
10531119
10541120
=== modified file 'bzrlib/transport/http/__init__.py'
--- bzrlib/transport/http/__init__.py 2011-05-27 07:39:41 +0000
+++ bzrlib/transport/http/__init__.py 2011-08-01 06:37:14 +0000
@@ -271,7 +271,7 @@
271 cur_offset_and_size = iter_offsets.next()271 cur_offset_and_size = iter_offsets.next()
272272
273 except (errors.ShortReadvError, errors.InvalidRange,273 except (errors.ShortReadvError, errors.InvalidRange,
274 errors.InvalidHttpRange), e:274 errors.InvalidHttpRange, errors.HttpBoundaryMissing), e:
275 mutter('Exception %r: %s during http._readv',e, e)275 mutter('Exception %r: %s during http._readv',e, e)
276 if (not isinstance(e, errors.ShortReadvError)276 if (not isinstance(e, errors.ShortReadvError)
277 or retried_offset == cur_offset_and_size):277 or retried_offset == cur_offset_and_size):
278278
=== modified file 'bzrlib/transport/http/response.py'
--- bzrlib/transport/http/response.py 2009-03-23 14:59:43 +0000
+++ bzrlib/transport/http/response.py 2011-08-01 06:37:14 +0000
@@ -1,4 +1,4 @@
1# Copyright (C) 2006, 2007 Canonical Ltd1# Copyright (C) 2006-2011 Canonical Ltd
2#2#
3# This program is free software; you can redistribute it and/or modify3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by4# it under the terms of the GNU General Public License as published by
@@ -109,6 +109,13 @@
109 # To be on the safe side we allow it before any boundary line109 # To be on the safe side we allow it before any boundary line
110 boundary_line = self._file.readline()110 boundary_line = self._file.readline()
111111
112 if boundary_line == '':
113 # A timeout in the proxy server caused the response to end early.
114 # See launchpad bug 198646.
115 raise errors.HttpBoundaryMissing(
116 self._path,
117 self._boundary)
118
112 if boundary_line != '--' + self._boundary + '\r\n':119 if boundary_line != '--' + self._boundary + '\r\n':
113 # rfc822.unquote() incorrectly unquotes strings enclosed in <>120 # rfc822.unquote() incorrectly unquotes strings enclosed in <>
114 # IIS 6 and 7 incorrectly wrap boundary strings in <>121 # IIS 6 and 7 incorrectly wrap boundary strings in <>
115122
=== modified file 'doc/en/release-notes/bzr-2.3.txt'
--- doc/en/release-notes/bzr-2.3.txt 2011-07-15 08:25:00 +0000
+++ doc/en/release-notes/bzr-2.3.txt 2011-08-01 06:37:14 +0000
@@ -32,6 +32,9 @@
32.. Fixes for situations where bzr would previously crash or give incorrect32.. Fixes for situations where bzr would previously crash or give incorrect
33 or undesirable results.33 or undesirable results.
3434
35* Cope cleanly with buggy HTTP proxies that close the socket in the middle
36 of a multipart response. (Martin Pool, #198646).
37
35Documentation38Documentation
36*************39*************
3740

Subscribers

People subscribed via source and target branches