1 # Copyright (C) 2006-2007 Jelmer Vernooij <jelmer@samba.org>
3 # 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 by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 from bzrlib.branch import Branch
20 from bzrlib.bzrdir import BzrDir
21 from bzrlib.errors import NoSuchFile, NoSuchRevision, NotBranchError
22 from bzrlib.repository import Repository
23 from bzrlib.trace import mutter
26 from unittest import TestCase
28 from branch import FakeControlFiles, SvnBranchFormat
29 from convert import load_dumpfile
30 from fileids import generate_svn_file_id
31 from repository import MAPPING_VERSION, generate_svn_revision_id, SVN_PROP_BZR_REVISION_ID
32 from tests import TestCaseWithSubversionRepository
34 class WorkingSubversionBranch(TestCaseWithSubversionRepository):
35 def test_last_rev_rev_hist(self):
36 repos_url = self.make_client("a", "dc")
37 branch = Branch.open(repos_url)
38 branch.revision_history()
39 self.assertEqual(branch.generate_revision_id(0), branch.last_revision())
41 def test_get_branch_path_root(self):
42 repos_url = self.make_client("a", "dc")
43 branch = Branch.open(repos_url)
44 self.assertEqual("", branch.get_branch_path())
46 def test_get_branch_path_subdir(self):
47 repos_url = self.make_client("a", "dc")
48 self.build_tree({"dc/trunk": None})
49 self.client_add("dc/trunk")
50 self.client_commit("dc", "Add branch")
51 branch = Branch.open(repos_url+"/trunk")
52 self.assertEqual("/trunk", branch.get_branch_path())
54 def test_open_nonexistant(self):
55 repos_url = self.make_client("a", "dc")
56 self.assertRaises(NotBranchError, Branch.open, repos_url + "/trunk")
58 def test_last_rev_rev_info(self):
59 repos_url = self.make_client("a", "dc")
60 branch = Branch.open(repos_url)
61 self.assertEqual((1, branch.generate_revision_id(0)),
62 branch.last_revision_info())
63 branch.revision_history()
64 self.assertEqual((1, branch.generate_revision_id(0)),
65 branch.last_revision_info())
67 def test_lookup_revision_id_unknown(self):
68 repos_url = self.make_client("a", "dc")
69 branch = Branch.open(repos_url)
70 self.assertRaises(NoSuchRevision,
71 lambda: branch.lookup_revision_id("bla"))
73 def test_lookup_revision_id(self):
74 repos_url = self.make_client("a", "dc")
75 branch = Branch.open(repos_url)
77 branch.lookup_revision_id(branch.last_revision()))
79 def test_set_parent(self):
80 repos_url = self.make_client('a', 'dc')
81 branch = Branch.open(repos_url)
82 branch.set_parent("foobar")
84 def test_num_revnums(self):
85 repos_url = self.make_client('a', 'dc')
86 bzrdir = BzrDir.open("svn+"+repos_url)
87 branch = bzrdir.open_branch()
88 self.assertEqual(branch.generate_revision_id(0),
89 branch.last_revision())
91 self.build_tree({'dc/foo': "data"})
92 self.client_add("dc/foo")
93 self.client_commit("dc", "My Message")
95 bzrdir = BzrDir.open("svn+"+repos_url)
96 branch = bzrdir.open_branch()
97 repos = bzrdir.find_repository()
99 self.assertEqual(repos.generate_revision_id(1, "", "none"),
100 branch.last_revision())
102 self.build_tree({'dc/foo': "data2"})
103 self.client_commit("dc", "My Message")
105 branch = Branch.open("svn+"+repos_url)
106 repos = Repository.open("svn+"+repos_url)
108 self.assertEqual(repos.generate_revision_id(2, "", "none"),
109 branch.last_revision())
111 def test_set_revision_history(self):
112 repos_url = self.make_client('a', 'dc')
113 branch = Branch.open("svn+"+repos_url)
114 self.assertRaises(NotImplementedError, branch.set_revision_history, [])
116 def test_get_root_id_empty(self):
117 repos_url = self.make_client('a', 'dc')
118 branch = Branch.open("svn+"+repos_url)
119 self.assertEqual(generate_svn_file_id(branch.repository.uuid, 0, "", ""), branch.get_root_id())
121 def test_get_root_id_trunk(self):
122 repos_url = self.make_client('a', 'dc')
123 self.build_tree({'dc/trunk': None})
124 self.client_add("dc/trunk")
125 self.client_commit("dc", "msg")
126 branch = Branch.open("svn+"+repos_url+"/trunk")
127 self.assertEqual(generate_svn_file_id(branch.repository.uuid, 1, "trunk", ""), branch.get_root_id())
129 def test_break_lock(self):
130 repos_url = self.make_client('a', 'dc')
131 branch = Branch.open("svn+"+repos_url)
132 branch.control_files.break_lock()
135 repos_url = self.make_client('a', 'dc')
136 branch = Branch.open("svn+"+repos_url)
137 self.assertEqual("SvnBranch('svn+%s')" % repos_url, branch.__repr__())
139 def test_get_physical_lock_status(self):
140 repos_url = self.make_client('a', 'dc')
141 branch = Branch.open("svn+"+repos_url)
142 self.assertFalse(branch.get_physical_lock_status())
144 def test_set_push_location(self):
145 repos_url = self.make_client('a', 'dc')
146 branch = Branch.open("svn+"+repos_url)
147 self.assertRaises(NotImplementedError, branch.set_push_location, [])
149 def test_get_parent(self):
150 repos_url = self.make_client('a', 'dc')
151 branch = Branch.open("svn+"+repos_url)
152 self.assertEqual("svn+"+repos_url, branch.get_parent())
154 def test_append_revision(self):
155 repos_url = self.make_client('a', 'dc')
156 branch = Branch.open("svn+"+repos_url)
157 branch.append_revision([])
159 def test_get_push_location(self):
160 repos_url = self.make_client('a', 'dc')
161 branch = Branch.open("svn+"+repos_url)
162 self.assertIs(None, branch.get_push_location())
164 def test_revision_history(self):
165 repos_url = self.make_client('a', 'dc')
167 branch = Branch.open("svn+"+repos_url)
168 self.assertEqual([branch.generate_revision_id(0)],
169 branch.revision_history())
171 self.build_tree({'dc/foo': "data"})
172 self.client_add("dc/foo")
173 self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID+"none",
175 self.client_commit("dc", "My Message")
177 branch = Branch.open("svn+"+repos_url)
178 repos = Repository.open("svn+"+repos_url)
180 self.assertEqual([repos.generate_revision_id(0, "", "none"),
181 repos.generate_revision_id(1, "", "none")],
182 branch.revision_history())
184 self.build_tree({'dc/foo': "data34"})
185 self.client_commit("dc", "My Message")
187 branch = Branch.open("svn+"+repos_url)
188 repos = Repository.open("svn+"+repos_url)
191 repos.generate_revision_id(0, "", "none"),
193 repos.generate_revision_id(2, "", "none")],
194 branch.revision_history())
196 def test_revision_id_to_revno_none(self):
197 """The None revid should map to revno 0."""
198 repos_url = self.make_client('a', 'dc')
199 branch = Branch.open(repos_url)
200 self.assertEquals(0, branch.revision_id_to_revno(None))
202 def test_revision_id_to_revno_nonexistant(self):
203 """revision_id_to_revno() should raise NoSuchRevision if
204 the specified revision did not exist in the branch history."""
205 repos_url = self.make_client('a', 'dc')
206 branch = Branch.open(repos_url)
207 self.assertRaises(NoSuchRevision, branch.revision_id_to_revno, "bla")
209 def test_revision_id_to_revno_simple(self):
210 repos_url = self.make_client('a', 'dc')
211 self.build_tree({'dc/foo': "data"})
212 self.client_add("dc/foo")
213 self.client_set_prop("dc", "bzr:revision-id-v%d:none" % MAPPING_VERSION,
215 self.client_commit("dc", "My Message")
216 branch = Branch.open(repos_url)
217 self.assertEquals(2, branch.revision_id_to_revno("myrevid"))
219 def test_revision_id_to_revno_older(self):
220 repos_url = self.make_client('a', 'dc')
221 self.build_tree({'dc/foo': "data"})
222 self.client_add("dc/foo")
223 self.client_set_prop("dc", "bzr:revision-id-v%d:none" % MAPPING_VERSION,
225 self.client_commit("dc", "My Message")
226 self.build_tree({'dc/foo': "someotherdata"})
227 self.client_set_prop("dc", "bzr:revision-id-v%d:none" % MAPPING_VERSION,
228 "2 myrevid\n3 mysecondrevid\n")
229 self.client_commit("dc", "My Message")
230 branch = Branch.open(repos_url)
231 self.assertEquals(3, branch.revision_id_to_revno("mysecondrevid"))
232 self.assertEquals(2, branch.revision_id_to_revno("myrevid"))
234 def test_get_nick_none(self):
235 repos_url = self.make_client('a', 'dc')
237 self.build_tree({'dc/foo': "data"})
238 self.client_add("dc/foo")
239 self.client_commit("dc", "My Message")
241 branch = Branch.open("svn+"+repos_url)
243 self.assertIs(None, branch.nick)
245 def test_get_nick_path(self):
246 repos_url = self.make_client('a', 'dc')
248 self.build_tree({'dc/trunk': None})
249 self.client_add("dc/trunk")
250 self.client_commit("dc", "My Message")
252 branch = Branch.open("svn+"+repos_url+"/trunk")
254 self.assertEqual("trunk", branch.nick)
256 def test_get_revprops(self):
257 repos_url = self.make_client('a', 'dc')
259 self.build_tree({'dc/foo': "data"})
260 self.client_add("dc/foo")
261 self.client_set_prop("dc", "bzr:revision-info",
262 "properties: \n\tbranch-nick: mybranch\n")
263 self.client_commit("dc", "My Message")
265 branch = Branch.open("svn+"+repos_url)
267 rev = branch.repository.get_revision(branch.last_revision())
269 self.assertEqual("mybranch", rev.properties["branch-nick"])
271 def test_fetch_replace(self):
272 filename = os.path.join(self.test_dir, "dumpfile")
273 open(filename, 'w').write("""SVN-fs-dump-format-version: 2
275 UUID: 6f95bc5c-e18d-4021-aca8-49ed51dbcb75
278 Prop-content-length: 56
284 2006-07-30T12:41:25.270824Z
288 Prop-content-length: 94
302 2006-07-30T12:41:26.117512Z
308 Prop-content-length: 10
314 Node-path: trunk/hosts
317 Prop-content-length: 10
318 Text-content-length: 4
319 Text-content-md5: 771ec3328c29d17af5aacf7f895dd885
326 Prop-content-length: 94
340 2006-07-30T12:41:27.130044Z
343 Node-path: trunk/hosts
346 Text-content-length: 4
347 Text-content-md5: 6c2479dbb342b8df96d84db7ab92c412
353 Prop-content-length: 94
367 2006-07-30T12:41:28.114350Z
370 Node-path: trunk/hosts
373 Text-content-length: 4
374 Text-content-md5: 368cb8d3db6186e2e83d9434f165c525
380 Prop-content-length: 94
394 2006-07-30T12:41:29.129563Z
400 Prop-content-length: 10
407 Prop-content-length: 94
421 2006-07-30T12:41:31.130508Z
424 Node-path: branches/foobranch
428 Node-copyfrom-path: trunk
432 Prop-content-length: 94
446 2006-07-30T12:41:33.129149Z
449 Node-path: branches/foobranch/hosts
453 Node-path: branches/foobranch/hosts
457 Node-copyfrom-path: trunk/hosts
463 Prop-content-length: 94
477 2006-07-30T12:41:34.136423Z
480 Node-path: branches/foobranch/hosts
483 Text-content-length: 8
484 Text-content-md5: 0e328d3517a333a4879ebf3d88fd82bb
491 load_dumpfile("dumpfile", "old")
493 url = "old/branches/foobranch"
494 mutter('open %r' % url)
495 olddir = BzrDir.open(url)
497 newdir = olddir.sprout("new")
499 newbranch = newdir.open_branch()
501 uuid = "6f95bc5c-e18d-4021-aca8-49ed51dbcb75"
502 tree = newbranch.repository.revision_tree(
503 generate_svn_revision_id(uuid, 7, "branches/foobranch",
506 weave = tree.get_weave(tree.inventory.path2id("hosts"))
508 generate_svn_revision_id(uuid, 6, "branches/foobranch", "trunk0"),
509 generate_svn_revision_id(uuid, 7, "branches/foobranch", "trunk0")],
513 def test_fetch_odd(self):
514 repos_url = self.make_client('d', 'dc')
516 self.build_tree({'dc/trunk': None,
517 'dc/trunk/hosts': 'hej1'})
518 self.client_add("dc/trunk")
519 self.client_commit("dc", "created trunk and added hosts") #1
521 self.build_tree({'dc/trunk/hosts': 'hej2'})
522 self.client_commit("dc", "rev 2") #2
524 self.build_tree({'dc/trunk/hosts': 'hej3'})
525 self.client_commit("dc", "rev 3") #3
527 self.build_tree({'dc/branches': None})
528 self.client_add("dc/branches")
529 self.client_commit("dc", "added branches") #4
531 self.client_copy("dc/trunk", "dc/branches/foobranch")
532 self.client_commit("dc", "added branch foobranch") #5
534 self.build_tree({'dc/branches/foobranch/hosts': 'foohosts'})
535 self.client_commit("dc", "foohosts") #6
539 url = "svn+"+repos_url+"/branches/foobranch"
540 mutter('open %r' % url)
541 olddir = BzrDir.open(url)
543 newdir = olddir.sprout("new")
545 newbranch = newdir.open_branch()
547 uuid = olddir.find_repository().uuid
548 tree = newbranch.repository.revision_tree(
549 generate_svn_revision_id(uuid, 6, "branches/foobranch", "trunk0"))
551 weave = tree.get_weave(tree.inventory.path2id("hosts"))
553 generate_svn_revision_id(uuid, 1, "trunk", "trunk0"),
554 generate_svn_revision_id(uuid, 2, "trunk", "trunk0"),
555 generate_svn_revision_id(uuid, 3, "trunk", "trunk0"),
556 generate_svn_revision_id(uuid, 6, "branches/foobranch", "trunk0")],
559 def test_check(self):
560 self.make_client('d', 'dc')
561 branch = Branch.open('d')
562 result = branch.check()
563 self.assertEqual(branch, result.branch)
565 def test_generate_revision_id(self):
566 self.make_client('d', 'dc')
567 self.build_tree({'dc/bla/bloe': None})
568 self.client_add("dc/bla")
569 self.client_commit("dc", "bla")
570 branch = Branch.open('d')
571 self.assertEqual("svn-v%d-none:%s::1" % (MAPPING_VERSION, branch.repository.uuid), branch.generate_revision_id(1))
573 def test_create_checkout(self):
574 repos_url = self.make_client('d', 'dc')
576 self.build_tree({'dc/trunk': None, 'dc/trunk/hosts': 'hej1'})
577 self.client_add("dc/trunk")
578 self.client_commit("dc", "created trunk and added hosts") #1
580 url = "svn+"+repos_url+"/trunk"
581 oldbranch = Branch.open(url)
583 newtree = self.create_checkout(oldbranch, "e")
584 self.assertTrue(newtree.branch.repository.has_revision(
585 oldbranch.generate_revision_id(1)))
587 self.assertTrue(os.path.exists("e/.bzr"))
588 self.assertFalse(os.path.exists("e/.svn"))
590 def test_create_checkout_lightweight(self):
591 repos_url = self.make_client('d', 'dc')
593 self.build_tree({'dc/trunk': None,
594 'dc/trunk/hosts': 'hej1'})
595 self.client_add("dc/trunk")
596 self.client_commit("dc", "created trunk and added hosts") #1
598 url = "svn+"+repos_url+"/trunk"
599 oldbranch = Branch.open(url)
601 newtree = self.create_checkout(oldbranch, "e", lightweight=True)
602 self.assertEqual(oldbranch.generate_revision_id(1), newtree.base_revid)
603 self.assertTrue(os.path.exists("e/.svn"))
604 self.assertFalse(os.path.exists("e/.bzr"))
606 def test_create_checkout_lightweight_stop_rev(self):
607 repos_url = self.make_client('d', 'dc')
609 self.build_tree({'dc/trunk': None,
610 'dc/trunk/hosts': 'hej1'})
611 self.client_add("dc/trunk")
612 self.client_commit("dc", "created trunk and added hosts") #1
614 self.build_tree({'dc/trunk/hosts': 'bloe'})
615 self.client_commit("dc", "added another revision")
617 url = "svn+"+repos_url+"/trunk"
618 oldbranch = Branch.open(url)
620 newtree = self.create_checkout(oldbranch, "e", revision_id=
621 oldbranch.generate_revision_id(1), lightweight=True)
622 self.assertEqual(oldbranch.generate_revision_id(1),
624 self.assertTrue(os.path.exists("e/.svn"))
625 self.assertFalse(os.path.exists("e/.bzr"))
627 def test_fetch_branch(self):
628 self.make_client('d', 'sc')
630 self.build_tree({'sc/foo/bla': "data"})
631 self.client_add("sc/foo")
632 self.client_commit("sc", "foo")
634 olddir = self.open_checkout_bzrdir("sc")
638 newdir = olddir.sprout('dc')
641 olddir.open_branch().last_revision(),
642 newdir.open_branch().last_revision())
644 def test_fetch_dir_upgrade(self):
645 repos_url = self.make_client('d', 'sc')
647 self.build_tree({'sc/trunk/mylib/bla': "data", "sc/branches": None})
648 self.client_add("sc/trunk")
649 self.client_add("sc/branches")
650 self.client_commit("sc", "foo")
652 self.client_copy("sc/trunk/mylib", "sc/branches/abranch")
653 self.client_commit("sc", "Promote mylib")
655 olddir = self.open_checkout_bzrdir("sc/branches/abranch")
659 newdir = olddir.sprout('dc')
662 olddir.open_branch().last_revision(),
663 newdir.open_branch().last_revision())
665 def test_fetch_branch_downgrade(self):
666 repos_url = self.make_client('d', 'sc')
668 self.build_tree({'sc/trunk': None, "sc/branches/abranch/bla": 'foo'})
669 self.client_add("sc/trunk")
670 self.client_add("sc/branches")
671 self.client_commit("sc", "foo")
673 self.client_copy("sc/branches/abranch", "sc/trunk/mylib")
674 self.client_commit("sc", "Demote mylib")
676 olddir = self.open_checkout_bzrdir("sc/trunk")
680 newdir = olddir.sprout('dc')
683 olddir.open_branch().last_revision(),
684 newdir.open_branch().last_revision())
688 def test_ghost_workingtree(self):
689 # Looks like bazaar has trouble creating a working tree of a
690 # revision that has ghost parents
691 self.make_client('d', 'sc')
693 self.build_tree({'sc/foo/bla': "data"})
694 self.client_add("sc/foo")
695 self.client_set_prop("sc", "bzr:merge", "some-ghost\n")
696 self.client_commit("sc", "foo")
698 olddir = self.open_checkout_bzrdir("sc")
702 newdir = olddir.sprout('dc')
703 newdir.find_repository().get_revision(
704 newdir.open_branch().last_revision())
705 newdir.find_repository().get_revision_inventory(
706 newdir.open_branch().last_revision())
708 class TestFakeControlFiles(TestCase):
709 def test_get_utf8(self):
710 f = FakeControlFiles()
711 self.assertRaises(NoSuchFile, f.get_utf8, "foo")
715 f = FakeControlFiles()
716 self.assertRaises(NoSuchFile, f.get, "foobla")
718 class BranchFormatTests(TestCase):
720 self.format = SvnBranchFormat()
722 def test_initialize(self):
723 self.assertRaises(NotImplementedError, self.format.initialize, None)
725 def test_get_format_string(self):
726 self.assertEqual("Subversion Smart Server",
727 self.format.get_format_string())
729 def test_get_format_description(self):
730 self.assertEqual("Subversion Smart Server",
731 self.format.get_format_description())