# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: john@arbash-meinel.com-20081106172721-93ou4yohznuearke # target_branch: http://bzr.arbash-meinel.com/branches/bzr/releases\ # /bzr.1.9 # testament_sha1: aa03f961b58be60802f0beb94727d2520da776e4 # timestamp: 2008-11-06 11:29:14 -0600 # source_branch: http://bzr.arbash-meinel.com/branches/bzr/1.9-\ # dev/sftp_bug_293746 # base_revision_id: pqm@pqm.ubuntu.com-20081031091201-8b83yv5co6o2uuzc # # Begin patch === modified file 'NEWS' --- NEWS 2008-10-31 08:04:35 +0000 +++ NEWS 2008-11-06 17:27:21 +0000 @@ -5,6 +5,16 @@ .. contents:: +IN DEVELOPMENT +-------------- + + BUG FIXES: + + * ``SFTPTransport.readv()`` had a bug when requests were out-of-order. + This only triggers some-of-the-time on Knit format repositories. + (John Arbash Meinel, #293746) + + bzr 1.9 2008-10-31 ------------------ === modified file 'bzrlib/tests/test_sftp_transport.py' --- bzrlib/tests/test_sftp_transport.py 2008-10-15 18:59:07 +0000 +++ bzrlib/tests/test_sftp_transport.py 2008-11-06 17:27:21 +0000 @@ -463,6 +463,17 @@ self.assertAlmostEqual(t2 - t1, 100 + 7) +class ReadvFile(object): + """An object that acts like Paramiko's SFTPFile.readv()""" + + def __init__(self, data): + self._data = data + + def readv(self, requests): + for start, length in requests: + yield self._data[start:start+length] + + class Test_SFTPReadvHelper(tests.TestCase): def checkGetRequests(self, expected_requests, offsets): @@ -485,6 +496,25 @@ [(0, 40000), (40000, 100), (40100, 1900), (42000, 24000)]) + def checkRequestAndYield(self, expected, data, offsets): + helper = _mod_sftp._SFTPReadvHelper(offsets, 'artificial_test') + data_f = ReadvFile(data) + result = list(helper.request_and_yield_offsets(data_f)) + self.assertEqual(expected, result) + + def test_request_and_yield_offsets(self): + data = 'abcdefghijklmnopqrstuvwxyz' + self.checkRequestAndYield([(0, 'a'), (5, 'f'), (10, 'klm')], data, + [(0, 1), (5, 1), (10, 3)]) + # Should combine requests, and split them again + self.checkRequestAndYield([(0, 'a'), (1, 'b'), (10, 'klm')], data, + [(0, 1), (1, 1), (10, 3)]) + # Out of order requests. The requests should get combined, but then be + # yielded out-of-order. We also need one that is at the end of a + # previous range. See bug #293746 + self.checkRequestAndYield([(0, 'a'), (10, 'k'), (4, 'efg'), (1, 'bcd')], + data, [(0, 1), (10, 1), (4, 3), (1, 3)]) + class TestUsesAuthConfig(TestCaseWithSFTPServer): """Test that AuthenticationConfig can supply default usernames.""" === modified file 'bzrlib/transport/sftp.py' --- bzrlib/transport/sftp.py 2008-10-15 18:59:07 +0000 +++ bzrlib/transport/sftp.py 2008-11-06 17:27:21 +0000 @@ -295,7 +295,8 @@ # get the previous node while True: idx = bisect.bisect_left(data_chunks, (cur_offset,)) - if data_chunks[idx][0] == cur_offset: # The data starts here + if idx < len(data_chunks) and data_chunks[idx][0] == cur_offset: + # The data starts here data = data_chunks[idx][1][:cur_size] elif idx > 0: # The data is in a portion of a previous page # Begin bundle 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 lUiBgVQR6r/i7kinChIG/SA84A==