Fix more bugs in the bindings.
[jelmer/subvertpy.git] / tests / test_repository.py
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2006-2007 Jelmer Vernooij <jelmer@samba.org>
4
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19 """Subversion repository tests."""
20
21 from bzrlib import urlutils
22 from bzrlib.branch import Branch
23 from bzrlib.bzrdir import BzrDir, format_registry
24 from bzrlib.config import GlobalConfig
25 from bzrlib.errors import NoSuchRevision, UninitializableFormat, BzrError
26 from bzrlib.inventory import Inventory
27 from bzrlib.osutils import has_symlinks
28 from bzrlib.repository import Repository
29 from bzrlib.revision import NULL_REVISION, Revision
30 from bzrlib.tests import TestCase
31
32 import os, sys
33
34 import format
35 from mapping import (escape_svn_path, unescape_svn_path, 
36                      SVN_PROP_BZR_REVISION_ID)
37 from mapping3 import (SVN_PROP_BZR_BRANCHING_SCHEME, set_branching_scheme,
38                       set_property_scheme, BzrSvnMappingv3)
39 from mapping3.scheme import (TrunkBranchingScheme, NoBranchingScheme, 
40                     ListBranchingScheme, SingleBranchingScheme)
41 from transport import SvnRaTransport
42 from tests import TestCaseWithSubversionRepository
43 from repository import SvnRepositoryFormat
44
45
46 class TestSubversionRepositoryWorks(TestCaseWithSubversionRepository):
47     def test_format(self):
48         """ Test repository format is correct """
49         bzrdir = self.make_local_bzrdir('a', 'ac')
50         self.assertEqual(bzrdir._format.get_format_string(), \
51                 "Subversion Local Checkout")
52         
53         self.assertEqual(bzrdir._format.get_format_description(), \
54                 "Subversion Local Checkout")
55
56     def test_get_branch_log(self):
57         repos_url = self.make_client("a", "dc")
58         self.build_tree({'dc/foo': "data"})
59         self.client_add("dc/foo")
60         self.client_commit("dc", "My Message")
61
62         repos = Repository.open(repos_url)
63
64         self.assertEqual([
65             ('', {'foo': ('A', None, -1)}, 1), 
66             ('', {'': ('A', None, -1)}, 0)],
67             [(l.branch_path, l.paths, l.revnum) for l in repos.iter_reverse_branch_changes("", 1, NoBranchingScheme())])
68
69     def test_make_working_trees(self):
70         repos_url = self.make_client("a", "dc")
71         repos = Repository.open(repos_url)
72         self.assertFalse(repos.make_working_trees())
73
74     def test_get_config_global_set(self):
75         repos_url = self.make_client("a", "dc")
76         cfg = GlobalConfig()
77         cfg.set_user_option("foo", "Still Life")
78
79         repos = Repository.open(repos_url)
80         self.assertEquals("Still Life", 
81                 repos.get_config().get_user_option("foo"))
82
83     def test_get_config(self):
84         repos_url = self.make_client("a", "dc")
85         repos = Repository.open(repos_url)
86         repos.get_config().set_user_option("foo", "Van Der Graaf Generator")
87
88         repos = Repository.open(repos_url)
89         self.assertEquals("Van Der Graaf Generator", 
90                 repos.get_config().get_user_option("foo"))
91
92
93     def test_get_physical_lock_status(self):
94         repos_url = self.make_client("a", "dc")
95         repos = Repository.open(repos_url)
96         self.assertFalse(repos.get_physical_lock_status())
97
98     def test_iter_changes_parent_rename(self):
99         repos_url = self.make_client("a", "dc")
100         self.build_tree({'dc/foo/bar': None})
101         self.client_add('dc/foo')
102         self.client_commit('dc', 'a')
103         self.client_update('dc')
104         self.client_copy('dc/foo', 'dc/bla')
105         self.client_commit('dc', 'b')
106         repos = Repository.open(repos_url)
107         ret = list(repos.iter_changes('bla/bar', 2, BzrSvnMappingv3(SingleBranchingScheme('bla/bar'))))
108         self.assertEquals(1, len(ret))
109         self.assertEquals("bla/bar", ret[0][0])
110
111     def test_set_make_working_trees(self):
112         repos_url = self.make_client("a", "dc")
113         repos = Repository.open(repos_url)
114         repos.set_make_working_trees(True)
115         self.assertFalse(repos.make_working_trees())
116
117     def test_get_fileid_map(self):
118         repos_url = self.make_client("a", "dc")
119         repos = Repository.open(repos_url)
120         mapping = repos.get_mapping()
121         self.assertEqual({u"": (mapping.generate_file_id(repos.uuid, 0, "", u""), mapping.generate_revision_id(repos.uuid, 0, ""))}, repos.get_fileid_map(0, "", mapping))
122
123     def test_generate_revision_id_forced_revid(self):
124         repos_url = self.make_client("a", "dc")
125         self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID+"none", 
126                              "2 someid\n")
127         self.client_commit("dc", "set id")
128         repos = Repository.open(repos_url)
129         revid = repos.generate_revision_id(1, "", repos.get_mapping())
130         self.assertEquals("someid", revid)
131
132     def test_generate_revision_id_forced_revid_invalid(self):
133         repos_url = self.make_client("a", "dc")
134         self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID+"none", 
135                              "corrupt-id\n")
136         self.client_commit("dc", "set id")
137         repos = Repository.open(repos_url)
138         revid = repos.generate_revision_id(1, "", repos.get_mapping())
139         self.assertEquals(
140                 repos.get_mapping().generate_revision_id(repos.uuid, 1, ""),
141                 revid)
142
143     def test_add_revision(self):
144         repos_url = self.make_client("a", "dc")
145         repos = Repository.open(repos_url)
146         self.assertRaises(NotImplementedError, repos.add_revision, "revid", 
147                 None)
148
149     def test_has_signature_for_revision_id_no(self):
150         repos_url = self.make_client("a", "dc")
151         repos = Repository.open(repos_url)
152         self.assertFalse(repos.has_signature_for_revision_id("foo"))
153
154     def test_set_signature(self):
155         repos_url = self.make_client("a", "dc")
156         repos = Repository.open(repos_url)
157         self.build_tree({"dc/foo": "bar"})
158         self.client_add("dc/foo")
159         self.client_commit("dc", "msg")
160         revid = repos.get_mapping().generate_revision_id(repos.uuid, 1, "")
161         repos.add_signature_text(revid, "TEXT")
162         self.assertTrue(repos.has_signature_for_revision_id(revid))
163         self.assertEquals(repos.get_signature_text(revid), "TEXT")
164
165     def test_repr(self):
166         repos_url = self.make_client("a", "dc")
167         self.build_tree({'dc/foo': "data"})
168         self.client_add("dc/foo")
169         self.client_commit("dc", "My Message")
170
171         repos = Repository.open(repos_url)
172
173         self.assertEqual("SvnRepository('%s/')" % urlutils.local_path_to_url(urlutils.join(self.test_dir, "a")), repos.__repr__())
174
175     def test_get_branch_invalid_revision(self):
176         repos_url = self.make_client("a", "dc")
177         repos = Repository.open(repos_url)
178         self.assertRaises(NoSuchRevision, list, 
179                repos.iter_reverse_branch_changes("/", 20, NoBranchingScheme()))
180
181     def test_follow_branch_switched_parents(self):
182         repos_url = self.make_client('a', 'dc')
183         self.build_tree({'dc/pykleur/trunk/pykleur': None})
184         self.client_add("dc/pykleur")
185         self.client_commit("dc", "initial")
186         self.build_tree({'dc/pykleur/trunk/pykleur/afile': 'contents'})
187         self.client_add("dc/pykleur/trunk/pykleur/afile")
188         self.client_commit("dc", "add file")
189         self.client_copy("dc/pykleur", "dc/pygments", 1)
190         self.client_delete('dc/pykleur')
191         self.client_update("dc")
192         self.client_commit("dc", "commit")
193         repos = Repository.open(repos_url)
194         self.assertEquals([
195             ('pygments/trunk', {'pygments': (u'A', 'pykleur', 1),
196                                 'pygments/trunk': (u'R', 'pykleur/trunk', 2),
197                                 'pykleur': (u'D', None, -1)}, 3),
198             ('pykleur/trunk', {'pykleur/trunk/pykleur/afile': (u'A', None, -1)}, 2),
199             ('pykleur/trunk',
200                     {'pykleur': (u'A', None, -1),
201                      'pykleur/trunk': (u'A', None, -1),
202                      'pykleur/trunk/pykleur': (u'A', None, -1)},
203              1)],
204             [(l.branch_path, l.paths, l.revnum) for l in repos.iter_reverse_branch_changes("pygments/trunk", 3, TrunkBranchingScheme(1))])
205
206     def test_follow_branch_move_single(self):
207         repos_url = self.make_client('a', 'dc')
208         self.build_tree({'dc/pykleur/bla': None})
209         self.client_add("dc/pykleur")
210         self.client_commit("dc", "initial")
211         self.client_copy("dc/pykleur", "dc/pygments", 1)
212         self.client_update("dc")
213         self.client_commit("dc", "commit")
214         repos = Repository.open(repos_url)
215         changes = repos.iter_reverse_branch_changes("pygments", 2, SingleBranchingScheme("pygments"))
216         self.assertEquals([('pygments',
217               {'pygments/bla': ('A', None, -1), 'pygments': ('A', None, -1)},
218                 2)],
219                 [(l.branch_path, l.paths, l.revnum) for l in changes])
220
221     def test_history_all(self):
222         repos_url = self.make_client("a", "dc")
223         self.build_tree({'dc/trunk/file': "data", "dc/foo/file":"data"})
224         self.client_add("dc/trunk")
225         self.client_add("dc/foo")
226         self.client_commit("dc", "My Message")
227
228         repos = Repository.open(repos_url)
229
230         self.assertEqual(2, 
231                    len(list(repos.all_revision_ids(repos.get_layout()))))
232
233     def test_all_revs_empty(self):
234         repos_url = self.make_client("a", "dc")
235         repos = Repository.open(repos_url)
236         set_branching_scheme(repos, TrunkBranchingScheme())
237         self.assertEqual([], list(repos.all_revision_ids()))
238
239     def test_all_revs(self):
240         repos_url = self.make_client("a", "dc")
241         self.build_tree({'dc/trunk/file': "data", "dc/foo/file":"data"})
242         self.client_add("dc/trunk")
243         self.client_commit("dc", "add trunk")
244         self.build_tree({'dc/branches/somebranch/somefile': 'data'})
245         self.client_add("dc/branches")
246         self.client_commit("dc", "add a branch")
247         self.client_delete("dc/branches/somebranch")
248         self.client_commit("dc", "remove branch")
249
250         repos = Repository.open(repos_url)
251         set_branching_scheme(repos, TrunkBranchingScheme())
252         mapping = repos.get_mapping()
253         self.assertEqual([
254             repos.generate_revision_id(1, "trunk", mapping), 
255             repos.generate_revision_id(2, "branches/somebranch", mapping)],
256             list(repos.all_revision_ids()))
257
258     def test_follow_history_empty(self):
259         repos_url = self.make_client("a", "dc")
260         repos = Repository.open(repos_url)
261         self.assertEqual([repos.generate_revision_id(0, '', repos.get_mapping())], 
262               list(repos.all_revision_ids(repos.get_layout())))
263
264     def test_follow_history_empty_branch(self):
265         repos_url = self.make_client("a", "dc")
266         self.build_tree({'dc/trunk/afile': "data", "dc/branches": None})
267         self.client_add("dc/trunk")
268         self.client_add("dc/branches")
269         self.client_commit("dc", "My Message")
270         repos = Repository.open(repos_url)
271         set_branching_scheme(repos, TrunkBranchingScheme())
272         self.assertEqual([repos.generate_revision_id(1, 'trunk', repos.get_mapping())], 
273                 list(repos.all_revision_ids(repos.get_layout())))
274
275     def test_follow_history_follow(self):
276         repos_url = self.make_client("a", "dc")
277         self.build_tree({'dc/trunk/afile': "data", "dc/branches": None})
278         self.client_add("dc/trunk")
279         self.client_add("dc/branches")
280         self.client_commit("dc", "My Message")
281
282         self.client_copy("dc/trunk", "dc/branches/abranch")
283         self.client_commit("dc", "Create branch")
284
285         repos = Repository.open(repos_url)
286         set_branching_scheme(repos, TrunkBranchingScheme())
287
288         items = list(repos.all_revision_ids(repos.get_layout()))
289         self.assertEqual([repos.generate_revision_id(1, 'trunk', repos.get_mapping()),
290                           repos.generate_revision_id(2, 'branches/abranch', repos.get_mapping())
291                           ], items)
292
293     def test_branch_log_specific(self):
294         repos_url = self.make_client("a", "dc")
295         self.build_tree({
296             'dc/branches': None,
297             'dc/branches/brancha': None,
298             'dc/branches/branchab': None,
299             'dc/branches/brancha/data': "data", 
300             "dc/branches/branchab/data":"data"})
301         self.client_add("dc/branches")
302         self.client_commit("dc", "My Message")
303
304         repos = Repository.open(repos_url)
305         set_branching_scheme(repos, TrunkBranchingScheme())
306
307         self.assertEqual(1, len(list(repos.iter_reverse_branch_changes("branches/brancha",
308             1, TrunkBranchingScheme()))))
309
310     def test_branch_log_specific_ignore(self):
311         repos_url = self.make_client("a", "dc")
312         self.build_tree({'dc/branches': None})
313         self.client_add("dc/branches")
314         self.build_tree({
315             'dc/branches/brancha': None,
316             'dc/branches/branchab': None,
317             'dc/branches/brancha/data': "data", 
318             "dc/branches/branchab/data":"data"})
319         self.client_add("dc/branches/brancha")
320         self.client_commit("dc", "My Message")
321
322         self.client_add("dc/branches/branchab")
323         self.client_commit("dc", "My Message2")
324
325         repos = Repository.open(repos_url)
326         set_branching_scheme(repos, TrunkBranchingScheme())
327
328         self.assertEqual(1, len(list(repos.iter_reverse_branch_changes("branches/brancha",
329             2, TrunkBranchingScheme()))))
330
331     def test_find_branches(self):
332         repos_url = self.make_client("a", "dc")
333         self.build_tree({
334             'dc/branches/brancha': None,
335             'dc/branches/branchab': None,
336             'dc/branches/brancha/data': "data", 
337             "dc/branches/branchab/data":"data"})
338         self.client_add("dc/branches")
339         self.client_commit("dc", "My Message")
340         repos = Repository.open(repos_url)
341         set_branching_scheme(repos, TrunkBranchingScheme())
342         branches = repos.find_branches()
343         self.assertEquals(2, len(branches))
344         self.assertEquals(urlutils.join(repos.base, "branches/brancha"), 
345                           branches[1].base)
346         self.assertEquals(urlutils.join(repos.base, "branches/branchab"), 
347                           branches[0].base)
348
349     def test_find_branchpaths_moved(self):
350         repos_url = self.make_client("a", "dc")
351         self.build_tree({
352             'dc/tmp/branches/brancha': None,
353             'dc/tmp/branches/branchab': None,
354             'dc/tmp/branches/brancha/data': "data", 
355             "dc/tmp/branches/branchab/data":"data"})
356         self.client_add("dc/tmp")
357         self.client_commit("dc", "My Message")
358         self.client_copy("dc/tmp/branches", "dc/tags")
359         self.client_commit("dc", "My Message 2")
360
361         repos = Repository.open(repos_url)
362         set_branching_scheme(repos, TrunkBranchingScheme())
363
364         self.assertEqual([("tags/branchab", 2, True), 
365                           ("tags/brancha", 2, True)], 
366                 list(repos.find_branchpaths(TrunkBranchingScheme(), to_revnum=2)))
367
368     def test_find_branchpaths_start_revno(self):
369         repos_url = self.make_client("a", "dc")
370         self.build_tree({'dc/branches/brancha': None})
371         self.client_add("dc/branches")
372         self.client_commit("dc", "My Message")
373         self.build_tree({'dc/branches/branchb': None})
374         self.client_add("dc/branches/branchb")
375         self.client_commit("dc", "My Message 2")
376
377         repos = Repository.open(repos_url)
378         set_branching_scheme(repos, TrunkBranchingScheme())
379
380         self.assertEqual([("branches/branchb", 2, True)],
381                 list(repos.find_branchpaths(TrunkBranchingScheme(), from_revnum=2, 
382                     to_revnum=2)))
383
384     def test_find_branchpaths_file_moved_from_nobranch(self):
385         repos_url = self.make_client("a", "dc")
386         self.build_tree({
387             'dc/tmp/trunk': None,
388             'dc/bla/somefile': "contents"})
389         self.client_add("dc/tmp")
390         self.client_add("dc/bla")
391         self.client_commit("dc", "My Message")
392         self.client_copy("dc/bla", "dc/tmp/branches")
393         self.client_delete("dc/tmp/branches/somefile")
394         self.client_commit("dc", "My Message 2")
395
396         Repository.open(repos_url).find_branchpaths(TrunkBranchingScheme(2))
397
398     def test_find_branchpaths_deleted_from_nobranch(self):
399         repos_url = self.make_client("a", "dc")
400         self.build_tree({
401             'dc/tmp/trunk': None,
402             'dc/bla/somefile': "contents"})
403         self.client_add("dc/tmp")
404         self.client_add("dc/bla")
405         self.client_commit("dc", "My Message")
406         self.client_copy("dc/bla", "dc/tmp/branches")
407         self.client_delete("dc/tmp/branches/somefile")
408         self.client_commit("dc", "My Message 2")
409
410         Repository.open(repos_url).find_branchpaths(TrunkBranchingScheme(1))
411
412     def test_find_branchpaths_moved_nobranch(self):
413         repos_url = self.make_client("a", "dc")
414         self.build_tree({
415             'dc/tmp/nested/foobar': None,
416             'dc/tmp/nested/branches/brancha': None,
417             'dc/tmp/nested/branches/branchab': None,
418             'dc/tmp/nested/branches/brancha/data': "data", 
419             "dc/tmp/nested/branches/branchab/data":"data"})
420         self.client_add("dc/tmp")
421         self.client_commit("dc", "My Message")
422         self.client_copy("dc/tmp/nested", "dc/t2")
423         self.client_commit("dc", "My Message 2")
424
425         repos = Repository.open(repos_url)
426         set_branching_scheme(repos, TrunkBranchingScheme(1))
427
428         self.assertEqual([("t2/branches/brancha", 2, True), 
429                           ("t2/branches/branchab", 2, True)], 
430                 list(repos.find_branchpaths(TrunkBranchingScheme(1), to_revnum=2)))
431
432     def test_find_branchpaths_no(self):
433         repos_url = self.make_client("a", "dc")
434
435         repos = Repository.open(repos_url)
436         set_branching_scheme(repos, NoBranchingScheme())
437
438         self.assertEqual([("", 0, True)], 
439                 list(repos.find_branchpaths(NoBranchingScheme(), to_revnum=0)))
440
441     def test_find_branchpaths_no_later(self):
442         repos_url = self.make_client("a", "dc")
443
444         repos = Repository.open(repos_url)
445         set_branching_scheme(repos, NoBranchingScheme())
446
447         self.assertEqual([("", 0, True)], 
448                 list(repos.find_branchpaths(NoBranchingScheme(), to_revnum=0)))
449
450     def test_find_branchpaths_trunk_empty(self):
451         repos_url = self.make_client("a", "dc")
452
453         repos = Repository.open(repos_url)
454         set_branching_scheme(repos, TrunkBranchingScheme())
455
456         self.assertEqual([], 
457                 list(repos.find_branchpaths(TrunkBranchingScheme(), to_revnum=0)))
458
459     def test_find_branchpaths_trunk_one(self):
460         repos_url = self.make_client("a", "dc")
461
462         repos = Repository.open(repos_url)
463         set_branching_scheme(repos, TrunkBranchingScheme())
464
465         self.build_tree({'dc/trunk/foo': "data"})
466         self.client_add("dc/trunk")
467         self.client_commit("dc", "My Message")
468
469         self.assertEqual([("trunk", 1, True)], 
470                 list(repos.find_branchpaths(TrunkBranchingScheme(), to_revnum=1)))
471
472     def test_find_branchpaths_removed(self):
473         repos_url = self.make_client("a", "dc")
474
475         repos = Repository.open(repos_url)
476         set_branching_scheme(repos, TrunkBranchingScheme())
477
478         self.build_tree({'dc/trunk/foo': "data"})
479         self.client_add("dc/trunk")
480         self.client_commit("dc", "My Message")
481
482         self.client_delete("dc/trunk")
483         self.client_commit("dc", "remove")
484
485         self.assertEqual([("trunk", 1, True)], 
486                 list(repos.find_branchpaths(TrunkBranchingScheme(), to_revnum=1)))
487         self.assertEqual([("trunk", 1, False)], 
488                 list(repos.find_branchpaths(TrunkBranchingScheme(), to_revnum=2)))
489
490     def test_url(self):
491         """ Test repository URL is kept """
492         bzrdir = self.make_local_bzrdir('b', 'bc')
493         self.assertTrue(isinstance(bzrdir, BzrDir))
494
495     def test_uuid(self):
496         """ Test UUID is retrieved correctly """
497         bzrdir = self.make_local_bzrdir('c', 'cc')
498         self.assertTrue(isinstance(bzrdir, BzrDir))
499         repository = bzrdir._find_repository()
500         fs = self.open_fs('c')
501         self.assertEqual(fs.get_uuid(fs), repository.uuid)
502
503     def test_get_inventory_weave(self):
504         bzrdir = self.make_client_and_bzrdir('d', 'dc')
505         repository = bzrdir.find_repository()
506         self.assertRaises(NotImplementedError, repository.get_inventory_weave)
507
508     def test_has_revision(self):
509         bzrdir = self.make_client_and_bzrdir('d', 'dc')
510         repository = bzrdir.find_repository()
511         self.build_tree({'dc/foo': "data"})
512         self.client_add("dc/foo")
513         self.client_commit("dc", "My Message")
514         self.assertTrue(repository.has_revision(
515             repository.generate_revision_id(1, "", repository.get_mapping())))
516         self.assertFalse(repository.has_revision("some-other-revision"))
517
518     def test_has_revision_none(self):
519         bzrdir = self.make_client_and_bzrdir('d', 'dc')
520         repository = bzrdir.find_repository()
521         self.assertTrue(repository.has_revision(None))
522
523     def test_has_revision_future(self):
524         bzrdir = self.make_client_and_bzrdir('d', 'dc')
525         repository = bzrdir.find_repository()
526         self.assertFalse(repository.has_revision(
527             repository.get_mapping().generate_revision_id(repository.uuid, 5, "")))
528
529     def test_get_parent_map(self):
530         repos_url = self.make_client('d', 'dc')
531         self.build_tree({'dc/foo': "data"})
532         self.client_add("dc/foo")
533         self.client_commit("dc", "My Message")
534         self.build_tree({'dc/foo': "data2"})
535         self.client_commit("dc", "Second Message")
536         repository = Repository.open("svn+%s" % repos_url)
537         mapping = repository.get_mapping()
538         revid = repository.generate_revision_id(0, "", mapping)
539         self.assertEqual({revid: (NULL_REVISION,)}, repository.get_parent_map([revid]))
540         revid = repository.generate_revision_id(1, "", mapping)
541         self.assertEqual({revid: (repository.generate_revision_id(0, "", mapping),)}, repository.get_parent_map([revid]))
542         revid = repository.generate_revision_id(2, "", mapping)
543         self.assertEqual({revid: (repository.generate_revision_id(1, "", mapping),)},
544             repository.get_parent_map([revid]))
545         self.assertEqual({}, repository.get_parent_map(["notexisting"]))
546
547     def test_revision_fileidmap(self):
548         repos_url = self.make_client('d', 'dc')
549         self.build_tree({'dc/foo': "data"})
550         self.client_add("dc/foo")
551         self.client_set_prop("dc", "bzr:revision-info", "")
552         self.client_set_prop("dc", "bzr:file-ids", "foo\tsomeid\n")
553         self.client_commit("dc", "My Message")
554         repository = Repository.open("svn+%s" % repos_url)
555         tree = repository.revision_tree(Branch.open(repos_url).last_revision())
556         self.assertEqual("someid", tree.inventory.path2id("foo"))
557         self.assertFalse("1@%s::foo" % repository.uuid in tree.inventory)
558
559     def test_revision_ghost_parents(self):
560         repos_url = self.make_client('d', 'dc')
561         self.build_tree({'dc/foo': "data"})
562         self.client_add("dc/foo")
563         self.client_commit("dc", "My Message")
564         self.client_update("dc")
565         self.build_tree({'dc/foo': "data2"})
566         self.client_set_prop("dc", "bzr:ancestry:v3-none", "ghostparent\n")
567         self.client_commit("dc", "Second Message")
568         repository = Repository.open("svn+%s" % repos_url)
569         mapping = repository.get_mapping()
570         self.assertEqual((),
571                 repository.get_revision(
572                     repository.generate_revision_id(0, "", mapping)).parent_ids)
573         self.assertEqual((repository.generate_revision_id(0, "", mapping),),
574                 repository.get_revision(
575                     repository.generate_revision_id(1, "", mapping)).parent_ids)
576         self.assertEqual((repository.generate_revision_id(1, "", mapping),
577             "ghostparent"), 
578                 repository.get_revision(
579                     repository.generate_revision_id(2, "", mapping)).parent_ids)
580  
581     def test_revision_svk_parent(self):
582         repos_url = self.make_client('d', 'dc')
583         self.build_tree({'dc/trunk/foo': "data", 'dc/branches/foo': None})
584         self.client_add("dc/trunk")
585         self.client_add("dc/branches")
586         self.client_commit("dc", "My Message")
587         self.client_update("dc")
588         self.build_tree({'dc/trunk/foo': "data2"})
589         repository = Repository.open("svn+%s" % repos_url)
590         set_branching_scheme(repository, TrunkBranchingScheme())
591         self.client_set_prop("dc/trunk", "svk:merge", 
592             "%s:/branches/foo:1\n" % repository.uuid)
593         self.client_commit("dc", "Second Message")
594         mapping = repository.get_mapping()
595         self.assertEqual((repository.generate_revision_id(1, "trunk", mapping),
596             repository.generate_revision_id(1, "branches/foo", mapping)), 
597                 repository.get_revision(
598                     repository.generate_revision_id(2, "trunk", mapping)).parent_ids)
599     
600     def test_get_revision(self):
601         repos_url = self.make_client('d', 'dc')
602         repository = Repository.open("svn+%s" % repos_url)
603         self.assertRaises(NoSuchRevision, repository.get_revision, 
604                 "nonexisting")
605         self.build_tree({'dc/foo': "data"})
606         self.client_add("dc/foo")
607         self.client_commit("dc", "My Message")
608         self.client_update("dc")
609         self.build_tree({'dc/foo': "data2"})
610         (num, date, author) = self.client_commit("dc", "Second Message")
611         repository = Repository.open("svn+%s" % repos_url)
612         mapping = repository.get_mapping()
613         rev = repository.get_revision(
614             repository.generate_revision_id(2, "", mapping))
615         self.assertEqual((repository.generate_revision_id(1, "", mapping),),
616                 rev.parent_ids)
617         self.assertEqual(rev.revision_id, 
618                 repository.generate_revision_id(2, "", mapping))
619         self.assertEqual(author, rev.committer)
620         self.assertIsInstance(rev.properties, dict)
621
622     def test_get_revision_id_overriden(self):
623         repos_url = self.make_client('d', 'dc')
624         repository = Repository.open("svn+%s" % repos_url)
625         self.assertRaises(NoSuchRevision, repository.get_revision, "nonexisting")
626         self.build_tree({'dc/foo': "data"})
627         self.client_add("dc/foo")
628         self.client_commit("dc", "My Message")
629         self.build_tree({'dc/foo': "data2"})
630         self.client_set_prop("dc", "bzr:revision-id:v3-none", 
631                             "3 myrevid\n")
632         self.client_update("dc")
633         (num, date, author) = self.client_commit("dc", "Second Message")
634         repository = Repository.open("svn+%s" % repos_url)
635         mapping = repository.get_mapping()
636         revid = mapping.generate_revision_id(repository.uuid, 2, "")
637         rev = repository.get_revision("myrevid")
638         self.assertEqual((repository.generate_revision_id(1, "", mapping),),
639                 rev.parent_ids)
640         self.assertEqual(rev.revision_id, 
641                          repository.generate_revision_id(2, "", mapping))
642         self.assertEqual(author, rev.committer)
643         self.assertIsInstance(rev.properties, dict)
644
645     def test_get_revision_zero(self):
646         repos_url = self.make_client('d', 'dc')
647         repository = Repository.open("svn+%s" % repos_url)
648         mapping = repository.get_mapping()
649         rev = repository.get_revision(
650             repository.generate_revision_id(0, "", mapping))
651         self.assertEqual(repository.generate_revision_id(0, "", mapping), 
652                          rev.revision_id)
653         self.assertEqual("", rev.committer)
654         self.assertEqual({}, rev.properties)
655         self.assertEqual(None, rev.timezone)
656
657     def test_store_branching_scheme(self):
658         repos_url = self.make_client('d', 'dc')
659         repository = Repository.open(repos_url)
660         set_branching_scheme(repository, TrunkBranchingScheme(42))
661         repository = Repository.open(repos_url)
662         self.assertEquals("trunk42", str(repository.get_mapping().scheme))
663
664     def test_get_ancestry(self):
665         repos_url = self.make_client('d', 'dc')
666         repository = Repository.open("svn+%s" % repos_url)
667         self.assertRaises(NoSuchRevision, repository.get_revision, "nonexisting")
668         self.build_tree({'dc/foo': "data"})
669         self.client_add("dc/foo")
670         self.client_commit("dc", "My Message")
671         self.client_update("dc")
672         self.build_tree({'dc/foo': "data2"})
673         self.client_commit("dc", "Second Message")
674         self.client_update("dc")
675         self.build_tree({'dc/foo': "data3"})
676         self.client_commit("dc", "Third Message")
677         self.client_update("dc")
678         repository = Repository.open("svn+%s" % repos_url)
679         mapping = repository.get_mapping()
680         self.assertEqual([None, 
681             repository.generate_revision_id(0, "", mapping),
682             repository.generate_revision_id(1, "", mapping),
683             repository.generate_revision_id(2, "", mapping),
684             repository.generate_revision_id(3, "", mapping)],
685                 repository.get_ancestry(
686                     repository.generate_revision_id(3, "", mapping)))
687         self.assertEqual([None, 
688             repository.generate_revision_id(0, "", mapping),
689             repository.generate_revision_id(1, "", mapping),
690             repository.generate_revision_id(2, "", mapping)],
691                 repository.get_ancestry(
692                     repository.generate_revision_id(2, "", mapping)))
693         self.assertEqual([None,
694                     repository.generate_revision_id(0, "", mapping),
695                     repository.generate_revision_id(1, "", mapping)],
696                 repository.get_ancestry(
697                     repository.generate_revision_id(1, "", mapping)))
698         self.assertEqual([None, repository.generate_revision_id(0, "", mapping)],
699                 repository.get_ancestry(
700                     repository.generate_revision_id(0, "", mapping)))
701         self.assertEqual([None], repository.get_ancestry(NULL_REVISION))
702
703     def test_get_ancestry2(self):
704         repos_url = self.make_client('d', 'dc')
705         self.build_tree({'dc/foo': "data"})
706         self.client_add("dc/foo")
707         self.client_commit("dc", "My Message")
708         self.build_tree({'dc/foo': "data2"})
709         self.client_commit("dc", "Second Message")
710         repository = Repository.open("svn+%s" % repos_url)
711         mapping = repository.get_mapping()
712         self.assertEqual([None, repository.generate_revision_id(0, "", mapping)],
713                 repository.get_ancestry(
714                     repository.generate_revision_id(0, "", mapping)))
715         self.assertEqual([None, repository.generate_revision_id(0, "", mapping),
716             repository.generate_revision_id(1, "", mapping)],
717                 repository.get_ancestry(
718                     repository.generate_revision_id(1, "", mapping)))
719         self.assertEqual([None, 
720             repository.generate_revision_id(0, "", mapping),
721             repository.generate_revision_id(1, "", mapping),
722             repository.generate_revision_id(2, "", mapping)], 
723                 repository.get_ancestry(
724                     repository.generate_revision_id(2, "", mapping)))
725
726     def test_get_ancestry_merged(self):
727         repos_url = self.make_client('d', 'dc')
728         self.build_tree({'dc/foo': "data"})
729         self.client_add("dc/foo")
730         self.client_commit("dc", "My Message")
731         self.client_update("dc")
732         self.client_set_prop("dc", "bzr:ancestry:v3-none", "a-parent\n")
733         self.build_tree({'dc/foo': "data2"})
734         self.client_commit("dc", "Second Message")
735         repository = Repository.open("svn+%s" % repos_url)
736         mapping = repository.get_mapping()
737         self.assertEqual([None, repository.generate_revision_id(0, "", mapping)],
738                 repository.get_ancestry(
739                     repository.generate_revision_id(0, "", mapping)))
740         self.assertEqual([None, repository.generate_revision_id(0, "", mapping),
741             repository.generate_revision_id(1, "", mapping)],
742                 repository.get_ancestry(
743                     repository.generate_revision_id(1, "", mapping)))
744         self.assertEqual([None, 
745             repository.generate_revision_id(0, "", mapping), "a-parent", 
746             repository.generate_revision_id(1, "", mapping), 
747                   repository.generate_revision_id(2, "", mapping)], 
748                 repository.get_ancestry(
749                     repository.generate_revision_id(2, "", mapping)))
750
751     def test_get_inventory(self):
752         repos_url = self.make_client('d', 'dc')
753         repository = Repository.open("svn+%s" % repos_url)
754         self.assertRaises(NoSuchRevision, repository.get_inventory, 
755                 "nonexisting")
756         self.build_tree({'dc/foo': "data", 'dc/blah': "other data"})
757         self.client_add("dc/foo")
758         self.client_add("dc/blah")
759         self.client_commit("dc", "My Message") #1
760         self.client_update("dc")
761         self.build_tree({'dc/foo': "data2", "dc/bar/foo": "data3"})
762         self.client_add("dc/bar")
763         self.client_commit("dc", "Second Message") #2
764         self.client_update("dc")
765         self.build_tree({'dc/foo': "data3"})
766         self.client_commit("dc", "Third Message") #3
767         self.client_update("dc")
768         repository = Repository.open("svn+%s" % repos_url)
769         mapping = repository.get_mapping()
770         inv = repository.get_inventory(
771                 repository.generate_revision_id(1, "", mapping))
772         self.assertIsInstance(inv, Inventory)
773         self.assertIsInstance(inv.path2id("foo"), basestring)
774         inv = repository.get_inventory(
775             repository.generate_revision_id(2, "", mapping))
776         self.assertEqual(repository.generate_revision_id(2, "", mapping), 
777                          inv[inv.path2id("foo")].revision)
778         self.assertEqual(repository.generate_revision_id(1, "", mapping), 
779                          inv[inv.path2id("blah")].revision)
780         self.assertIsInstance(inv, Inventory)
781         self.assertIsInstance(inv.path2id("foo"), basestring)
782         self.assertIsInstance(inv.path2id("bar"), basestring)
783         self.assertIsInstance(inv.path2id("bar/foo"), basestring)
784
785     def test_generate_revision_id(self):
786         repos_url = self.make_client('d', 'dc')
787         self.build_tree({'dc/bla/bloe': None})
788         self.client_add("dc/bla")
789         self.client_commit("dc", "bla")
790         repository = Repository.open("svn+%s" % repos_url)
791         mapping = repository.get_mapping()
792         self.assertEqual(
793                mapping.generate_revision_id(repository.uuid, 1, "bla/bloe"), 
794             repository.generate_revision_id(1, "bla/bloe", mapping))
795
796     def test_generate_revision_id_zero(self):
797         repos_url = self.make_client('d', 'dc')
798         repository = Repository.open("svn+%s" % repos_url)
799         mapping = repository.get_mapping()
800         self.assertEqual(mapping.generate_revision_id(repository.uuid, 0, ""), 
801                 repository.generate_revision_id(0, "", mapping))
802
803     def test_lookup_revision_id(self):
804         repos_url = self.make_client('d', 'dc')
805         self.build_tree({'dc/bloe': None})
806         self.client_add("dc/bloe")
807         self.client_commit("dc", "foobar")
808         repository = Repository.open("svn+%s" % repos_url)
809         self.assertRaises(NoSuchRevision, repository.lookup_revision_id, 
810             "nonexisting")
811         mapping = repository.get_mapping()
812         self.assertEqual(("bloe", 1), 
813             repository.lookup_revision_id(
814                 repository.generate_revision_id(1, "bloe", mapping))[:2])
815
816     def test_lookup_revision_id_overridden(self):
817         repos_url = self.make_client('d', 'dc')
818         self.build_tree({'dc/bloe': None})
819         self.client_add("dc/bloe")
820         self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID+"none", "2 myid\n")
821         self.client_commit("dc", "foobar")
822         repository = Repository.open("svn+%s" % repos_url)
823         mapping = repository.get_mapping()
824         self.assertEqual(("", 1), repository.lookup_revision_id( 
825             mapping.generate_revision_id(repository.uuid, 1, ""))[:2])
826         self.assertEqual(("", 1), 
827                 repository.lookup_revision_id("myid")[:2])
828
829     def test_lookup_revision_id_overridden_invalid(self):
830         repos_url = self.make_client('d', 'dc')
831         self.build_tree({'dc/bloe': None})
832         self.client_add("dc/bloe")
833         self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID+"none", 
834                              "corrupt-entry\n")
835         self.client_commit("dc", "foobar")
836         repository = Repository.open("svn+%s" % repos_url)
837         mapping = repository.get_mapping()
838         self.assertEqual(("", 1), repository.lookup_revision_id( 
839             mapping.generate_revision_id(repository.uuid, 1, ""))[:2])
840         self.assertRaises(NoSuchRevision, repository.lookup_revision_id, 
841             "corrupt-entry")
842
843     def test_lookup_revision_id_overridden_invalid_dup(self):
844         repos_url = self.make_client('d', 'dc')
845         self.build_tree({'dc/bloe': None})
846         self.client_add("dc/bloe")
847         self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID+"none", 
848                              "corrupt-entry\n")
849         self.client_commit("dc", "foobar")
850         self.build_tree({'dc/bla': None})
851         self.client_add("dc/bla")
852         self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID+"none", 
853                 "corrupt-entry\n2 corrupt-entry\n")
854         self.client_commit("dc", "foobar")
855         repository = Repository.open("svn+%s" % repos_url)
856         mapping = repository.get_mapping()
857         self.assertEqual(("", 2), repository.lookup_revision_id( 
858             mapping.generate_revision_id(repository.uuid, 2, ""))[:2])
859         self.assertEqual(("", 1), repository.lookup_revision_id( 
860             mapping.generate_revision_id(repository.uuid, 1, ""))[:2])
861         self.assertEqual(("", 2), repository.lookup_revision_id( 
862             "corrupt-entry")[:2])
863
864     def test_lookup_revision_id_overridden_not_found(self):
865         """Make sure a revision id that is looked up but doesn't exist 
866         doesn't accidently end up in the revid cache."""
867         repos_url = self.make_client('d', 'dc')
868         self.build_tree({'dc/bloe': None})
869         self.client_add("dc/bloe")
870         self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID+"none", "2 myid\n")
871         self.client_commit("dc", "foobar")
872         repository = Repository.open("svn+%s" % repos_url)
873         self.assertRaises(NoSuchRevision, 
874                 repository.lookup_revision_id, "foobar")
875
876     def test_set_branching_scheme_property(self):
877         repos_url = self.make_client('d', 'dc')
878         self.client_set_prop("dc", SVN_PROP_BZR_BRANCHING_SCHEME, 
879             "trunk\nbranches/*\nbranches/tmp/*")
880         self.client_commit("dc", "set scheme")
881         repository = Repository.open("svn+%s" % repos_url)
882         self.assertEquals(ListBranchingScheme(["trunk", "branches/*", "branches/tmp/*"]).branch_list,
883                           repository.get_mapping().scheme.branch_list)
884
885     def test_set_property_scheme(self):
886         repos_url = self.make_client('d', 'dc')
887         repos = Repository.open(repos_url)
888         set_property_scheme(repos, ListBranchingScheme(["bla/*"]))
889         self.client_update("dc")
890         self.assertEquals("bla/*\n", 
891                    self.client_get_prop("dc", SVN_PROP_BZR_BRANCHING_SCHEME))
892         self.assertEquals("Updating branching scheme for Bazaar.", 
893                 self.client_log("dc", 1, 1)[1][3])
894
895     def test_lookup_revision_id_invalid_uuid(self):
896         repos_url = self.make_client('d', 'dc')
897         repository = Repository.open("svn+%s" % repos_url)
898         mapping = repository.get_mapping()
899         self.assertRaises(NoSuchRevision, 
900             repository.lookup_revision_id, 
901                 mapping.generate_revision_id("invaliduuid", 0, ""))
902         
903     def test_check(self):
904         repos_url = self.make_client('d', 'dc')
905         self.build_tree({'dc/foo': "data"})
906         self.client_add("dc/foo")
907         self.client_commit("dc", "My Message")
908         repository = Repository.open("svn+%s" % repos_url)
909         mapping = repository.get_mapping()
910         repository.check([
911             repository.generate_revision_id(0, "", mapping), 
912             repository.generate_revision_id(1, "", mapping)])
913
914     def test_copy_contents_into(self):
915         repos_url = self.make_client('d', 'dc')
916         self.build_tree({'dc/foo/bla': "data"})
917         self.client_add("dc/foo")
918         self.client_commit("dc", "My Message")
919         self.build_tree({'dc/foo/blo': "data2", "dc/bar/foo": "data3", 'dc/foo/bla': "data"})
920         self.client_add("dc/foo/blo")
921         self.client_add("dc/bar")
922         self.client_commit("dc", "Second Message")
923         repository = Repository.open("svn+%s" % repos_url)
924         mapping = repository.get_mapping()
925
926         to_bzrdir = BzrDir.create("e", format.get_rich_root_format())
927         to_repos = to_bzrdir.create_repository()
928
929         repository.copy_content_into(to_repos, 
930                 repository.generate_revision_id(2, "", mapping))
931
932         self.assertTrue(repository.has_revision(
933             repository.generate_revision_id(2, "", mapping)))
934         self.assertTrue(repository.has_revision(
935             repository.generate_revision_id(1, "", mapping)))
936
937     def test_is_shared(self):
938         repos_url = self.make_client('d', 'dc')
939         self.build_tree({'dc/foo/bla': "data"})
940         self.client_add("dc/foo")
941         self.client_commit("dc", "My Message")
942         repository = Repository.open("svn+%s" % repos_url)
943         self.assertTrue(repository.is_shared())
944
945     def test_fetch_property_change_only_trunk(self):
946         repos_url = self.make_client('d', 'dc')
947         self.build_tree({'dc/trunk/bla': "data"})
948         self.client_add("dc/trunk")
949         self.client_commit("dc", "My Message")
950         self.client_set_prop("dc/trunk", "some:property", "some data\n")
951         self.client_commit("dc", "My 3")
952         self.client_set_prop("dc/trunk", "some2:property", "some data\n")
953         self.client_commit("dc", "My 2")
954         self.client_set_prop("dc/trunk", "some:property", "some other data\n")
955         self.client_commit("dc", "My 4")
956         oldrepos = Repository.open("svn+"+repos_url)
957         self.assertEquals([('trunk', {'trunk': (u'M', None, -1)}, 3), 
958                            ('trunk', {'trunk': (u'M', None, -1)}, 2), 
959                            ('trunk', {'trunk/bla': (u'A', None, -1), 'trunk': (u'A', None, -1)}, 1)], 
960                    [(l.branch_path, l.paths, l.revnum) for l in oldrepos.iter_reverse_branch_changes("trunk", 3, TrunkBranchingScheme())])
961
962     def test_control_code_msg(self):
963         repos_url = self.make_client('d', 'dc')
964
965         self.build_tree({'dc/trunk': None})
966         self.client_add("dc/trunk")
967         self.client_commit("dc", "\x24")
968
969         self.build_tree({'dc/trunk/hosts': 'hej2'})
970         self.client_add("dc/trunk/hosts")
971         self.client_commit("dc", "bla\xfcbla") #2
972
973         self.build_tree({'dc/trunk/hosts': 'hej3'})
974         self.client_commit("dc", "a\x0cb") #3
975
976         self.build_tree({'dc/branches/foobranch/file': 'foohosts'})
977         self.client_add("dc/branches")
978         self.client_commit("dc", "foohosts") #4
979
980         oldrepos = Repository.open("svn+"+repos_url)
981         set_branching_scheme(oldrepos, TrunkBranchingScheme())
982         dir = BzrDir.create("f",format=format.get_rich_root_format())
983         newrepos = dir.create_repository()
984         oldrepos.copy_content_into(newrepos)
985
986         mapping = oldrepos.get_mapping()
987
988         self.assertTrue(newrepos.has_revision(
989             oldrepos.generate_revision_id(1, "trunk", mapping)))
990         self.assertTrue(newrepos.has_revision(
991             oldrepos.generate_revision_id(2, "trunk", mapping)))
992         self.assertTrue(newrepos.has_revision(
993             oldrepos.generate_revision_id(3, "trunk", mapping)))
994         self.assertTrue(newrepos.has_revision(
995             oldrepos.generate_revision_id(4, "branches/foobranch", mapping)))
996         self.assertFalse(newrepos.has_revision(
997             oldrepos.generate_revision_id(4, "trunk", mapping)))
998         self.assertFalse(newrepos.has_revision(
999             oldrepos.generate_revision_id(2, "", mapping)))
1000
1001         rev = newrepos.get_revision(oldrepos.generate_revision_id(1, "trunk", mapping))
1002         self.assertEqual("$", rev.message)
1003
1004         rev = newrepos.get_revision(
1005             oldrepos.generate_revision_id(2, "trunk", mapping))
1006         self.assertEqual('bla\xc3\xbcbla', rev.message.encode("utf-8"))
1007
1008         rev = newrepos.get_revision(oldrepos.generate_revision_id(3, "trunk", mapping))
1009         self.assertEqual(u"a\\x0cb", rev.message)
1010
1011     def test_set_branching_scheme(self):
1012         repos_url = self.make_client('d', 'dc')
1013         repos = Repository.open(repos_url)
1014         set_branching_scheme(repos, NoBranchingScheme())
1015
1016     def testlhs_revision_parent_none(self):
1017         repos_url = self.make_client('d', 'dc')
1018         repos = Repository.open(repos_url)
1019         set_branching_scheme(repos, NoBranchingScheme())
1020         self.assertEquals(NULL_REVISION, repos.lhs_revision_parent("", 0, NoBranchingScheme()))
1021
1022     def testlhs_revision_parent_first(self):
1023         repos_url = self.make_client('d', 'dc')
1024         repos = Repository.open(repos_url)
1025         set_branching_scheme(repos, NoBranchingScheme())
1026         self.build_tree({'dc/adir/afile': "data"})
1027         self.client_add("dc/adir")
1028         self.client_commit("dc", "Initial commit")
1029         mapping = repos.get_mapping()
1030         self.assertEquals(repos.generate_revision_id(0, "", mapping), \
1031                 repos.lhs_revision_parent("", 1, mapping))
1032
1033     def testlhs_revision_parent_simple(self):
1034         repos_url = self.make_client('d', 'dc')
1035         self.build_tree({'dc/trunk/adir/afile': "data", 
1036                          'dc/trunk/adir/stationary': None,
1037                          'dc/branches/abranch': None})
1038         self.client_add("dc/trunk")
1039         self.client_add("dc/branches")
1040         self.client_commit("dc", "Initial commit")
1041         self.build_tree({'dc/trunk/adir/afile': "bla"})
1042         self.client_commit("dc", "Incremental commit")
1043         repos = Repository.open(repos_url)
1044         set_branching_scheme(repos, TrunkBranchingScheme())
1045         mapping = repos.get_mapping()
1046         self.assertEquals(repos.generate_revision_id(1, "trunk", mapping), \
1047                 repos.lhs_revision_parent("trunk", 2, mapping))
1048
1049     def testlhs_revision_parent_copied(self):
1050         repos_url = self.make_client('d', 'dc')
1051         self.build_tree({'dc/py/trunk/adir/afile': "data", 
1052                          'dc/py/trunk/adir/stationary': None})
1053         self.client_add("dc/py")
1054         self.client_commit("dc", "Initial commit")
1055         self.client_copy("dc/py", "dc/de")
1056         self.client_commit("dc", "Incremental commit")
1057         self.build_tree({'dc/de/trunk/adir/afile': "bla"})
1058         self.client_commit("dc", "Change de")
1059         repos = Repository.open(repos_url)
1060         set_branching_scheme(repos, TrunkBranchingScheme(1))
1061         mapping = repos.get_mapping()
1062         self.assertEquals(repos.generate_revision_id(1, "py/trunk", mapping), \
1063                 repos.lhs_revision_parent("de/trunk", 3, mapping))
1064
1065     def test_mainline_revision_copied(self):
1066         repos_url = self.make_client('d', 'dc')
1067         self.build_tree({'dc/py/trunk/adir/afile': "data", 
1068                          'dc/py/trunk/adir/stationary': None})
1069         self.client_add("dc/py")
1070         self.client_commit("dc", "Initial commit")
1071         self.build_tree({'dc/de':None})
1072         self.client_add("dc/de")
1073         self.client_copy("dc/py/trunk", "dc/de/trunk")
1074         self.client_commit("dc", "Copy trunk")
1075         repos = Repository.open(repos_url)
1076         set_branching_scheme(repos, TrunkBranchingScheme(1))
1077         mapping = repos.get_mapping()
1078         self.assertEquals(repos.generate_revision_id(1, "py/trunk", mapping), \
1079                 repos.lhs_revision_parent("de/trunk", 2, mapping))
1080
1081     def test_mainline_revision_nested_deleted(self):
1082         repos_url = self.make_client('d', 'dc')
1083         self.build_tree({'dc/py/trunk/adir/afile': "data", 
1084                          'dc/py/trunk/adir/stationary': None})
1085         self.client_add("dc/py")
1086         self.client_commit("dc", "Initial commit")
1087         self.client_copy("dc/py", "dc/de")
1088         self.client_commit("dc", "Incremental commit")
1089         self.client_delete("dc/de/trunk/adir")
1090         self.client_commit("dc", "Another incremental commit")
1091         repos = Repository.open(repos_url)
1092         set_branching_scheme(repos, TrunkBranchingScheme(1))
1093         mapping = repos.get_mapping()
1094         self.assertEquals(repos.generate_revision_id(1, "py/trunk", mapping), \
1095                 repos.lhs_revision_parent("de/trunk", 3, mapping))
1096
1097     def test_mainline_revision_missing(self):
1098         repos_url = self.make_client('d', 'dc')
1099         repos = Repository.open(repos_url)
1100         self.build_tree({'dc/py/trunk/adir/afile': "data", 
1101                          'dc/py/trunk/adir/stationary': None})
1102         self.client_add("dc/py")
1103         self.client_commit("dc", "Initial commit")
1104         self.assertRaises(NoSuchRevision, 
1105                 lambda: repos.lhs_revision_parent("trunk", 2, repos.get_mapping()))
1106
1107
1108 class TestSvnRevisionTree(TestCaseWithSubversionRepository):
1109     def setUp(self):
1110         super(TestSvnRevisionTree, self).setUp()
1111         repos_url = self.make_client('d', 'dc')
1112         self.build_tree({'dc/foo/bla': "data"})
1113         self.client_add("dc/foo")
1114         self.client_commit("dc", "My Message")
1115         self.repos = Repository.open(repos_url)
1116         mapping = self.repos.get_mapping()
1117         self.inventory = self.repos.get_inventory(
1118                 self.repos.generate_revision_id(1, "", mapping))
1119         self.tree = self.repos.revision_tree(
1120                 self.repos.generate_revision_id(1, "", mapping))
1121
1122     def test_inventory(self):
1123         self.assertIsInstance(self.tree.inventory, Inventory)
1124         self.assertEqual(self.inventory, self.tree.inventory)
1125
1126     def test_get_parent_ids(self):
1127         mapping = self.repos.get_mapping()
1128         self.assertEqual((self.repos.generate_revision_id(0, "", mapping),), self.tree.get_parent_ids())
1129
1130     def test_get_parent_ids_zero(self):
1131         mapping = self.repos.get_mapping()
1132         tree = self.repos.revision_tree(
1133                 self.repos.generate_revision_id(0, "", mapping))
1134         self.assertEqual((), tree.get_parent_ids())
1135
1136     def test_get_revision_id(self):
1137         mapping = self.repos.get_mapping()
1138         self.assertEqual(self.repos.generate_revision_id(1, "", mapping),
1139                          self.tree.get_revision_id())
1140
1141     def test_get_file_lines(self):
1142         self.assertEqual(["data"], 
1143                 self.tree.get_file_lines(self.inventory.path2id("foo/bla")))
1144
1145     def test_executable(self):
1146         self.client_set_prop("dc/foo/bla", "svn:executable", "*")
1147         self.client_commit("dc", "My Message")
1148
1149         mapping = self.repos.get_mapping()
1150         
1151         inventory = self.repos.get_inventory(
1152                 self.repos.generate_revision_id(2, "", mapping))
1153
1154         self.assertTrue(inventory[inventory.path2id("foo/bla")].executable)
1155
1156     def test_symlink(self):
1157         if not has_symlinks():
1158             return
1159         os.symlink('foo/bla', 'dc/bar')
1160         self.client_add('dc/bar')
1161         self.client_commit("dc", "My Message")
1162
1163         mapping = self.repos.get_mapping()
1164         
1165         inventory = self.repos.get_inventory(
1166                 self.repos.generate_revision_id(2, "", mapping))
1167
1168         self.assertEqual('symlink', inventory[inventory.path2id("bar")].kind)
1169         self.assertEqual('foo/bla', 
1170                 inventory[inventory.path2id("bar")].symlink_target)
1171
1172     def test_not_executable(self):
1173         self.assertFalse(self.inventory[
1174             self.inventory.path2id("foo/bla")].executable)
1175
1176
1177 class EscapeTest(TestCase):
1178     def test_escape_svn_path_none(self):      
1179         self.assertEqual("", escape_svn_path(""))
1180
1181     def test_escape_svn_path_simple(self):
1182         self.assertEqual("ab", escape_svn_path("ab"))
1183
1184     def test_escape_svn_path_percent(self):
1185         self.assertEqual("a%25b", escape_svn_path("a%b"))
1186
1187     def test_escape_svn_path_whitespace(self):
1188         self.assertEqual("foobar%20", escape_svn_path("foobar "))
1189
1190     def test_escape_svn_path_slash(self):
1191         self.assertEqual("foobar%2F", escape_svn_path("foobar/"))
1192
1193     def test_escape_svn_path_special_char(self):
1194         self.assertEqual("foobar%8A", escape_svn_path("foobar\x8a"))
1195
1196     def test_unescape_svn_path_slash(self):
1197         self.assertEqual("foobar/", unescape_svn_path("foobar%2F"))
1198
1199     def test_unescape_svn_path_none(self):
1200         self.assertEqual("foobar", unescape_svn_path("foobar"))
1201
1202     def test_unescape_svn_path_percent(self):
1203         self.assertEqual("foobar%b", unescape_svn_path("foobar%25b"))
1204
1205     def test_escape_svn_path_nordic(self):
1206         self.assertEqual("foobar%C3%A6", escape_svn_path(u"foobar\xe6".encode("utf-8")))
1207
1208
1209 class SvnRepositoryFormatTests(TestCase):
1210     def setUp(self):
1211         self.format = SvnRepositoryFormat()
1212
1213     def test_initialize(self):
1214         self.assertRaises(UninitializableFormat, self.format.initialize, None)
1215
1216     def test_get_format_description(self):
1217         self.assertEqual("Subversion Repository", 
1218                          self.format.get_format_description())
1219
1220     def test_conversion_target_self(self):
1221         self.assertTrue(self.format.check_conversion_target(self.format))
1222
1223     def test_conversion_target_incompatible(self):
1224         self.assertFalse(self.format.check_conversion_target(
1225               format_registry.make_bzrdir('weave').repository_format))
1226
1227     def test_conversion_target_compatible(self):
1228         self.assertTrue(self.format.check_conversion_target(
1229           format_registry.make_bzrdir('rich-root').repository_format))
1230
1231
1232