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
17
22
from bzrlib import (
21
revision as _mod_revision,
24
30
from bzrlib.branch import Branch
31
from bzrlib.bzrdir import BzrDir
25
32
from bzrlib.repofmt import knitrepo
26
33
from bzrlib.tests import TestCaseWithTransport
34
from bzrlib.tests.http_utils import TestCaseWithWebserver
27
35
from bzrlib.tests.test_revision import make_branches
36
from bzrlib.trace import mutter
28
37
from bzrlib.upgrade import Convert
29
38
from bzrlib.workingtree import WorkingTree
36
45
def has_revision(branch, revision_id):
37
46
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]))
52
48
def fetch_steps(self, br_a, br_b, writable_a):
53
49
"""A foreign test method for testing fetch locally and remotely."""
55
51
# TODO RBC 20060201 make this a repository test.
56
52
repo_b = br_b.repository
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])
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])
61
57
# branch.fetch is not supposed to alter the revision history
62
self.assertEquals(len(revision_history(br_b)), 7)
63
self.assertFalse(repo_b.has_revision(revision_history(br_a)[3]))
58
self.assertEquals(len(br_b.revision_history()), 7)
59
self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
65
61
# fetching the next revision up in sample data copies one revision
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]))
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]))
71
67
# When a non-branch ancestor is missing, it should be unlisted...
72
68
# as its not reference from the inventory weave.
76
72
writable_a.fetch(br_b)
77
self.assertTrue(has_revision(br_a, revision_history(br_b)[3]))
78
self.assertTrue(has_revision(br_a, revision_history(br_b)[4]))
73
self.assertTrue(has_revision(br_a, br_b.revision_history()[3]))
74
self.assertTrue(has_revision(br_a, br_b.revision_history()[4]))
80
76
br_b2 = self.make_branch('br_b2')
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]))
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]))
86
82
br_a2 = self.make_branch('br_a2')
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]))
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]))
92
88
br_a3 = self.make_branch('br_a3')
93
89
# pulling a branch with no revisions grabs nothing, regardless of
252
248
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)
255
333
class TestKnitToPackFetch(TestCaseWithTransport):
257
335
def find_get_record_stream(self, calls, expected_count=1):