14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
17
from bzrlib import (
21
revision as _mod_revision,
30
24
from bzrlib.branch import Branch
31
from bzrlib.bzrdir import BzrDir
32
25
from bzrlib.repofmt import knitrepo
33
26
from bzrlib.tests import TestCaseWithTransport
34
from bzrlib.tests.http_utils import TestCaseWithWebserver
35
27
from bzrlib.tests.test_revision import make_branches
36
from bzrlib.trace import mutter
37
28
from bzrlib.upgrade import Convert
38
29
from bzrlib.workingtree import WorkingTree
45
36
def has_revision(branch, revision_id):
46
37
return branch.repository.has_revision(revision_id)
40
def revision_history(branch):
43
graph = branch.repository.get_graph()
44
history = list(graph.iter_lefthand_ancestry(branch.last_revision(),
45
[_mod_revision.NULL_REVISION]))
48
52
def fetch_steps(self, br_a, br_b, writable_a):
49
53
"""A foreign test method for testing fetch locally and remotely."""
51
55
# TODO RBC 20060201 make this a repository test.
52
56
repo_b = br_b.repository
53
self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
54
self.assertTrue(repo_b.has_revision(br_a.revision_history()[2]))
55
self.assertEquals(len(br_b.revision_history()), 7)
56
br_b.fetch(br_a, br_a.revision_history()[2])
57
self.assertFalse(repo_b.has_revision(revision_history(br_a)[3]))
58
self.assertTrue(repo_b.has_revision(revision_history(br_a)[2]))
59
self.assertEquals(len(revision_history(br_b)), 7)
60
br_b.fetch(br_a, revision_history(br_a)[2])
57
61
# branch.fetch is not supposed to alter the revision history
58
self.assertEquals(len(br_b.revision_history()), 7)
59
self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
62
self.assertEquals(len(revision_history(br_b)), 7)
63
self.assertFalse(repo_b.has_revision(revision_history(br_a)[3]))
61
65
# fetching the next revision up in sample data copies one revision
62
br_b.fetch(br_a, br_a.revision_history()[3])
63
self.assertTrue(repo_b.has_revision(br_a.revision_history()[3]))
64
self.assertFalse(has_revision(br_a, br_b.revision_history()[6]))
65
self.assertTrue(br_a.repository.has_revision(br_b.revision_history()[5]))
66
br_b.fetch(br_a, revision_history(br_a)[3])
67
self.assertTrue(repo_b.has_revision(revision_history(br_a)[3]))
68
self.assertFalse(has_revision(br_a, revision_history(br_b)[6]))
69
self.assertTrue(br_a.repository.has_revision(revision_history(br_b)[5]))
67
71
# When a non-branch ancestor is missing, it should be unlisted...
68
72
# as its not reference from the inventory weave.
72
76
writable_a.fetch(br_b)
73
self.assertTrue(has_revision(br_a, br_b.revision_history()[3]))
74
self.assertTrue(has_revision(br_a, br_b.revision_history()[4]))
77
self.assertTrue(has_revision(br_a, revision_history(br_b)[3]))
78
self.assertTrue(has_revision(br_a, revision_history(br_b)[4]))
76
80
br_b2 = self.make_branch('br_b2')
78
self.assertTrue(has_revision(br_b2, br_b.revision_history()[4]))
79
self.assertTrue(has_revision(br_b2, br_a.revision_history()[2]))
80
self.assertFalse(has_revision(br_b2, br_a.revision_history()[3]))
82
self.assertTrue(has_revision(br_b2, revision_history(br_b)[4]))
83
self.assertTrue(has_revision(br_b2, revision_history(br_a)[2]))
84
self.assertFalse(has_revision(br_b2, revision_history(br_a)[3]))
82
86
br_a2 = self.make_branch('br_a2')
84
self.assertTrue(has_revision(br_a2, br_b.revision_history()[4]))
85
self.assertTrue(has_revision(br_a2, br_a.revision_history()[3]))
86
self.assertTrue(has_revision(br_a2, br_a.revision_history()[2]))
88
self.assertTrue(has_revision(br_a2, revision_history(br_b)[4]))
89
self.assertTrue(has_revision(br_a2, revision_history(br_a)[3]))
90
self.assertTrue(has_revision(br_a2, revision_history(br_a)[2]))
88
92
br_a3 = self.make_branch('br_a3')
89
93
# pulling a branch with no revisions grabs nothing, regardless of
248
252
rev_id).get_file_text('this-file-id'), text)
251
class TestHttpFetch(TestCaseWithWebserver):
252
# FIXME RBC 20060124 this really isn't web specific, perhaps an
253
# instrumented readonly transport? Can we do an instrumented
254
# adapter and use self.get_readonly_url ?
256
def test_fetch(self):
257
#highest indices a: 5, b: 7
258
br_a, br_b = make_branches(self)
259
br_rem_a = Branch.open(self.get_readonly_url('branch1'))
260
fetch_steps(self, br_rem_a, br_b, br_a)
262
def _count_log_matches(self, target, logs):
263
"""Count the number of times the target file pattern was fetched in an http log"""
264
get_succeeds_re = re.compile(
265
'.*"GET .*%s HTTP/1.1" 20[06] - "-" "bzr/%s' %
266
( target, bzrlib.__version__))
269
if get_succeeds_re.match(line):
273
def test_weaves_are_retrieved_once(self):
274
self.build_tree(("source/", "source/file", "target/"))
275
# This test depends on knit dasta storage.
276
wt = self.make_branch_and_tree('source', format='dirstate-tags')
278
wt.add(["file"], ["id"])
279
wt.commit("added file")
280
open("source/file", 'w').write("blah\n")
281
wt.commit("changed file")
282
target = BzrDir.create_branch_and_repo("target/")
283
source = Branch.open(self.get_readonly_url("source/"))
285
# this is the path to the literal file. As format changes
286
# occur it needs to be updated. FIXME: ask the store for the
288
self.log("web server logs are:")
289
http_logs = self.get_readonly_server().logs
290
self.log('\n'.join(http_logs))
291
# unfortunately this log entry is branch format specific. We could
292
# factor out the 'what files does this format use' to a method on the
293
# repository, which would let us to this generically. RBC 20060419
294
# RBC 20080408: Or perhaps we can assert that no files are fully read
296
self.assertEqual(1, self._count_log_matches('/ce/id.kndx', http_logs))
297
self.assertEqual(1, self._count_log_matches('/ce/id.knit', http_logs))
298
self.assertEqual(1, self._count_log_matches('inventory.kndx', http_logs))
299
# this r-h check test will prevent regressions, but it currently already
300
# passes, before the patch to cache-rh is applied :[
301
self.assertTrue(1 >= self._count_log_matches('revision-history',
303
self.assertTrue(1 >= self._count_log_matches('last-revision',
305
# FIXME naughty poking in there.
306
self.get_readonly_server().logs = []
307
# check there is nothing more to fetch. We take care to re-use the
308
# existing transport so that the request logs we're about to examine
309
# aren't cluttered with redundant probes for a smart server.
310
# XXX: Perhaps this further parameterisation: test http with smart
311
# server, and test http without smart server?
312
source = Branch.open(
313
self.get_readonly_url("source/"),
314
possible_transports=[source.bzrdir.root_transport])
316
# should make just two requests
317
http_logs = self.get_readonly_server().logs
318
self.log("web server logs are:")
319
self.log('\n'.join(http_logs))
320
self.assertEqual(1, self._count_log_matches('branch-format', http_logs))
321
self.assertEqual(1, self._count_log_matches('branch/format', http_logs))
322
self.assertEqual(1, self._count_log_matches('repository/format',
324
self.assertEqual(1, self._count_log_matches('revisions.kndx',
326
self.assertTrue(1 >= self._count_log_matches('revision-history',
328
self.assertTrue(1 >= self._count_log_matches('last-revision',
330
self.assertLength(5, http_logs)
333
255
class TestKnitToPackFetch(TestCaseWithTransport):
335
257
def find_get_record_stream(self, calls, expected_count=1):
404
326
source.inventories = versionedfile.RecordingVersionedFilesDecorator(
405
327
source.inventories)
406
328
# XXX: This won't work in general, but for the dirstate format it does.
407
old_fetch_uses_deltas_setting = target._format._fetch_uses_deltas
409
target._format._fetch_uses_deltas = old_fetch_uses_deltas_setting
410
self.addCleanup(restore)
411
target._format._fetch_uses_deltas = False
329
self.overrideAttr(target._format, '_fetch_uses_deltas', False)
412
330
target.fetch(source, revision_id='rev-one')
413
331
self.assertEqual(('get_record_stream', [('file-id', 'rev-one')],
414
332
target._format._fetch_order, True),