Merge documentation improvements.
[jelmer/subvertpy.git] / tests / test_branch.py
1 # Copyright (C) 2006-2007 Jelmer Vernooij <jelmer@samba.org>
2
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.
7
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.
12
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
16
17 """Branch tests."""
18
19 from bzrlib.branch import Branch
20 from bzrlib.bzrdir import BzrDir
21 from bzrlib.errors import NoSuchFile
22 from bzrlib.repository import Repository
23 from bzrlib.trace import mutter
24
25 import os
26 from unittest import TestCase
27
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
32 from tests import TestCaseWithSubversionRepository
33
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())
40
41     def test_set_parent(self):
42         repos_url = self.make_client('a', 'dc')
43         branch = Branch.open(repos_url)
44         branch.set_parent("foobar")
45
46     def test_num_revnums(self):
47         repos_url = self.make_client('a', 'dc')
48         bzrdir = BzrDir.open("svn+"+repos_url)
49         branch = bzrdir.open_branch()
50         self.assertEqual(branch.generate_revision_id(0),
51                          branch.last_revision())
52
53         self.build_tree({'dc/foo': "data"})
54         self.client_add("dc/foo")
55         self.client_commit("dc", "My Message")
56         
57         bzrdir = BzrDir.open("svn+"+repos_url)
58         branch = bzrdir.open_branch()
59         repos = bzrdir.find_repository()
60
61         self.assertEqual(repos.generate_revision_id(1, ""), 
62                 branch.last_revision())
63
64         self.build_tree({'dc/foo': "data2"})
65         self.client_commit("dc", "My Message")
66
67         branch = Branch.open("svn+"+repos_url)
68         repos = Repository.open("svn+"+repos_url)
69
70         self.assertEqual(repos.generate_revision_id(2, ""),
71                 branch.last_revision())
72
73     def test_set_revision_history(self):
74         repos_url = self.make_client('a', 'dc')
75         branch = Branch.open("svn+"+repos_url)
76         self.assertRaises(NotImplementedError, branch.set_revision_history, [])
77
78     def test_get_root_id_empty(self):
79         repos_url = self.make_client('a', 'dc')
80         branch = Branch.open("svn+"+repos_url)
81         self.assertEqual(generate_svn_file_id(branch.repository.uuid, 0, "", ""), branch.get_root_id())
82
83     def test_get_root_id_trunk(self):
84         repos_url = self.make_client('a', 'dc')
85         self.build_tree({'dc/trunk': None})
86         self.client_add("dc/trunk")
87         self.client_commit("dc", "msg")
88         branch = Branch.open("svn+"+repos_url+"/trunk")
89         self.assertEqual(generate_svn_file_id(branch.repository.uuid, 1, "trunk", ""), branch.get_root_id())
90
91     def test_break_lock(self):
92         repos_url = self.make_client('a', 'dc')
93         branch = Branch.open("svn+"+repos_url)
94         branch.control_files.break_lock()
95
96     def test_repr(self):
97         repos_url = self.make_client('a', 'dc')
98         branch = Branch.open("svn+"+repos_url)
99         self.assertEqual("SvnBranch('svn+%s')" % repos_url, branch.__repr__())
100
101     def test_get_physical_lock_status(self):
102         repos_url = self.make_client('a', 'dc')
103         branch = Branch.open("svn+"+repos_url)
104         self.assertFalse(branch.get_physical_lock_status())
105
106     def test_set_push_location(self):
107         repos_url = self.make_client('a', 'dc')
108         branch = Branch.open("svn+"+repos_url)
109         self.assertRaises(NotImplementedError, branch.set_push_location, [])
110
111     def test_get_parent(self):
112         repos_url = self.make_client('a', 'dc')
113         branch = Branch.open("svn+"+repos_url)
114         self.assertEqual("svn+"+repos_url, branch.get_parent())
115
116     def test_append_revision(self):
117         repos_url = self.make_client('a', 'dc')
118         branch = Branch.open("svn+"+repos_url)
119         branch.append_revision([])
120
121     def test_get_push_location(self):
122         repos_url = self.make_client('a', 'dc')
123         branch = Branch.open("svn+"+repos_url)
124         self.assertIs(None, branch.get_push_location())
125
126     def test_revision_history(self):
127         repos_url = self.make_client('a', 'dc')
128
129         branch = Branch.open("svn+"+repos_url)
130         self.assertEqual([branch.generate_revision_id(0)], branch.revision_history())
131
132         self.build_tree({'dc/foo': "data"})
133         self.client_add("dc/foo")
134         self.client_commit("dc", "My Message")
135         
136         branch = Branch.open("svn+"+repos_url)
137         repos = Repository.open("svn+"+repos_url)
138
139         self.assertEqual([repos.generate_revision_id(0, ""), 
140                     repos.generate_revision_id(1, "")], 
141                 branch.revision_history())
142
143         self.build_tree({'dc/foo': "data34"})
144         self.client_commit("dc", "My Message")
145
146         branch = Branch.open("svn+"+repos_url)
147         repos = Repository.open("svn+"+repos_url)
148
149         self.assertEqual([
150             repos.generate_revision_id(0, ""),
151             repos.generate_revision_id(1, ""),
152             repos.generate_revision_id(2, "")],
153             branch.revision_history())
154
155     def test_get_nick_none(self):
156         repos_url = self.make_client('a', 'dc')
157
158         self.build_tree({'dc/foo': "data"})
159         self.client_add("dc/foo")
160         self.client_commit("dc", "My Message")
161
162         branch = Branch.open("svn+"+repos_url)
163
164         self.assertIs(None, branch.nick)
165
166     def test_get_nick_path(self):
167         repos_url = self.make_client('a', 'dc')
168
169         self.build_tree({'dc/trunk': "data"})
170         self.client_add("dc/trunk")
171         self.client_commit("dc", "My Message")
172
173         branch = Branch.open("svn+"+repos_url+"/trunk")
174
175         self.assertEqual("trunk", branch.nick)
176
177     def test_get_revprops(self):
178         repos_url = self.make_client('a', 'dc')
179
180         self.build_tree({'dc/foo': "data"})
181         self.client_add("dc/foo")
182         self.client_set_prop("dc", "bzr:revprop:branch-nick", "mybranch")
183         self.client_commit("dc", "My Message")
184
185         branch = Branch.open("svn+"+repos_url)
186
187         rev = branch.repository.get_revision(branch.last_revision())
188
189         self.assertEqual("mybranch", rev.properties["branch-nick"])
190
191     def test_fetch_replace(self):
192         filename = os.path.join(self.test_dir, "dumpfile")
193         open(filename, 'w').write("""SVN-fs-dump-format-version: 2
194
195 UUID: 6f95bc5c-e18d-4021-aca8-49ed51dbcb75
196
197 Revision-number: 0
198 Prop-content-length: 56
199 Content-length: 56
200
201 K 8
202 svn:date
203 V 27
204 2006-07-30T12:41:25.270824Z
205 PROPS-END
206
207 Revision-number: 1
208 Prop-content-length: 94
209 Content-length: 94
210
211 K 7
212 svn:log
213 V 0
214
215 K 10
216 svn:author
217 V 0
218
219 K 8
220 svn:date
221 V 27
222 2006-07-30T12:41:26.117512Z
223 PROPS-END
224
225 Node-path: trunk
226 Node-kind: dir
227 Node-action: add
228 Prop-content-length: 10
229 Content-length: 10
230
231 PROPS-END
232
233
234 Node-path: trunk/hosts
235 Node-kind: file
236 Node-action: add
237 Prop-content-length: 10
238 Text-content-length: 4
239 Text-content-md5: 771ec3328c29d17af5aacf7f895dd885
240 Content-length: 14
241
242 PROPS-END
243 hej1
244
245 Revision-number: 2
246 Prop-content-length: 94
247 Content-length: 94
248
249 K 7
250 svn:log
251 V 0
252
253 K 10
254 svn:author
255 V 0
256
257 K 8
258 svn:date
259 V 27
260 2006-07-30T12:41:27.130044Z
261 PROPS-END
262
263 Node-path: trunk/hosts
264 Node-kind: file
265 Node-action: change
266 Text-content-length: 4
267 Text-content-md5: 6c2479dbb342b8df96d84db7ab92c412
268 Content-length: 4
269
270 hej2
271
272 Revision-number: 3
273 Prop-content-length: 94
274 Content-length: 94
275
276 K 7
277 svn:log
278 V 0
279
280 K 10
281 svn:author
282 V 0
283
284 K 8
285 svn:date
286 V 27
287 2006-07-30T12:41:28.114350Z
288 PROPS-END
289
290 Node-path: trunk/hosts
291 Node-kind: file
292 Node-action: change
293 Text-content-length: 4
294 Text-content-md5: 368cb8d3db6186e2e83d9434f165c525
295 Content-length: 4
296
297 hej3
298
299 Revision-number: 4
300 Prop-content-length: 94
301 Content-length: 94
302
303 K 7
304 svn:log
305 V 0
306
307 K 10
308 svn:author
309 V 0
310
311 K 8
312 svn:date
313 V 27
314 2006-07-30T12:41:29.129563Z
315 PROPS-END
316
317 Node-path: branches
318 Node-kind: dir
319 Node-action: add
320 Prop-content-length: 10
321 Content-length: 10
322
323 PROPS-END
324
325
326 Revision-number: 5
327 Prop-content-length: 94
328 Content-length: 94
329
330 K 7
331 svn:log
332 V 0
333
334 K 10
335 svn:author
336 V 0
337
338 K 8
339 svn:date
340 V 27
341 2006-07-30T12:41:31.130508Z
342 PROPS-END
343
344 Node-path: branches/foobranch
345 Node-kind: dir
346 Node-action: add
347 Node-copyfrom-rev: 4
348 Node-copyfrom-path: trunk
349
350
351 Revision-number: 6
352 Prop-content-length: 94
353 Content-length: 94
354
355 K 7
356 svn:log
357 V 0
358
359 K 10
360 svn:author
361 V 0
362
363 K 8
364 svn:date
365 V 27
366 2006-07-30T12:41:33.129149Z
367 PROPS-END
368
369 Node-path: branches/foobranch/hosts
370 Node-kind: file
371 Node-action: delete
372
373 Node-path: branches/foobranch/hosts
374 Node-kind: file
375 Node-action: add
376 Node-copyfrom-rev: 2
377 Node-copyfrom-path: trunk/hosts
378
379
380
381
382 Revision-number: 7
383 Prop-content-length: 94
384 Content-length: 94
385
386 K 7
387 svn:log
388 V 0
389
390 K 10
391 svn:author
392 V 0
393
394 K 8
395 svn:date
396 V 27
397 2006-07-30T12:41:34.136423Z
398 PROPS-END
399
400 Node-path: branches/foobranch/hosts
401 Node-kind: file
402 Node-action: change
403 Text-content-length: 8
404 Text-content-md5: 0e328d3517a333a4879ebf3d88fd82bb
405 Content-length: 8
406
407 foohosts""")
408         os.mkdir("new")
409         os.mkdir("old")
410
411         load_dumpfile("dumpfile", "old")
412
413         url = "old/branches/foobranch"
414         mutter('open %r' % url)
415         olddir = BzrDir.open(url)
416
417         newdir = olddir.sprout("new")
418
419         newbranch = newdir.open_branch()
420
421         uuid = "6f95bc5c-e18d-4021-aca8-49ed51dbcb75"
422         tree = newbranch.repository.revision_tree(
423                 generate_svn_revision_id(uuid, 7, "branches/foobranch"))
424
425         weave = tree.get_weave(tree.inventory.path2id("hosts"))
426         self.assertEqual([
427             generate_svn_revision_id(uuid, 6, "branches/foobranch"),
428             generate_svn_revision_id(uuid, 7, "branches/foobranch")],
429                           weave.versions())
430  
431
432     def test_fetch_odd(self):
433         repos_url = self.make_client('d', 'dc')
434
435         self.build_tree({'dc/trunk': None, 
436                          'dc/trunk/hosts': 'hej1'})
437         self.client_add("dc/trunk")
438         self.client_commit("dc", "created trunk and added hosts") #1
439
440         self.build_tree({'dc/trunk/hosts': 'hej2'})
441         self.client_commit("dc", "rev 2") #2
442
443         self.build_tree({'dc/trunk/hosts': 'hej3'})
444         self.client_commit("dc", "rev 3") #3
445
446         self.build_tree({'dc/branches': None})
447         self.client_add("dc/branches")
448         self.client_commit("dc", "added branches") #4
449
450         self.client_copy("dc/trunk", "dc/branches/foobranch")
451         self.client_commit("dc", "added branch foobranch") #5
452
453         self.build_tree({'dc/branches/foobranch/hosts': 'foohosts'})
454         self.client_commit("dc", "foohosts") #6
455
456         os.mkdir("new")
457
458         url = "svn+"+repos_url+"/branches/foobranch"
459         mutter('open %r' % url)
460         olddir = BzrDir.open(url)
461
462         newdir = olddir.sprout("new")
463
464         newbranch = newdir.open_branch()
465
466         uuid = olddir.find_repository().uuid
467         tree = newbranch.repository.revision_tree(
468                 generate_svn_revision_id(uuid, 6, "branches/foobranch"))
469
470         weave = tree.get_weave(tree.inventory.path2id("hosts"))
471         self.assertEqual([
472             generate_svn_revision_id(uuid, 1, "trunk"),
473             generate_svn_revision_id(uuid, 2, "trunk"),
474             generate_svn_revision_id(uuid, 3, "trunk"),
475             generate_svn_revision_id(uuid, 6, "branches/foobranch")],
476                           weave.versions())
477
478     def test_check(self):
479         self.make_client('d', 'dc')
480         branch = Branch.open('d')
481         result = branch.check()
482         self.assertEqual(branch, result.branch) 
483  
484     def test_generate_revision_id(self):
485         self.make_client('d', 'dc')
486         branch = Branch.open('d')
487         self.assertEqual("svn-v%d-undefined:%s::1" % (MAPPING_VERSION, branch.repository.uuid),  branch.generate_revision_id(1))
488
489     def test_create_checkout(self):
490         repos_url = self.make_client('d', 'dc')
491
492         self.build_tree({'dc/trunk': None, 'dc/trunk/hosts': 'hej1'})
493         self.client_add("dc/trunk")
494         self.client_commit("dc", "created trunk and added hosts") #1
495
496         url = "svn+"+repos_url+"/trunk"
497         oldbranch = Branch.open(url)
498
499         newtree = self.create_checkout(oldbranch, "e")
500         self.assertTrue(newtree.branch.repository.has_revision(
501            oldbranch.generate_revision_id(1)))
502
503         self.assertTrue(os.path.exists("e/.bzr"))
504         self.assertFalse(os.path.exists("e/.svn"))
505
506     def test_create_checkout_lightweight(self):
507         repos_url = self.make_client('d', 'dc')
508
509         self.build_tree({'dc/trunk': None, 
510                          'dc/trunk/hosts': 'hej1'})
511         self.client_add("dc/trunk")
512         self.client_commit("dc", "created trunk and added hosts") #1
513
514         url = "svn+"+repos_url+"/trunk"
515         oldbranch = Branch.open(url)
516
517         newtree = self.create_checkout(oldbranch, "e", lightweight=True)
518         self.assertEqual(oldbranch.generate_revision_id(1), newtree.base_revid)
519         self.assertTrue(os.path.exists("e/.svn"))
520         self.assertFalse(os.path.exists("e/.bzr"))
521
522     def test_create_checkout_lightweight_stop_rev(self):
523         repos_url = self.make_client('d', 'dc')
524
525         self.build_tree({'dc/trunk': None, 
526                          'dc/trunk/hosts': 'hej1'})
527         self.client_add("dc/trunk")
528         self.client_commit("dc", "created trunk and added hosts") #1
529         
530         self.build_tree({'dc/trunk/hosts': 'bloe'})
531         self.client_commit("dc", "added another revision")
532
533         url = "svn+"+repos_url+"/trunk"
534         oldbranch = Branch.open(url)
535
536         newtree = self.create_checkout(oldbranch, "e", revision_id=
537            oldbranch.generate_revision_id(1), lightweight=True)
538         self.assertEqual(oldbranch.generate_revision_id(1),
539            newtree.base_revid)
540         self.assertTrue(os.path.exists("e/.svn"))
541         self.assertFalse(os.path.exists("e/.bzr"))
542
543     def test_fetch_branch(self):
544         self.make_client('d', 'sc')
545
546         self.build_tree({'sc/foo/bla': "data"})
547         self.client_add("sc/foo")
548         self.client_commit("sc", "foo")
549
550         olddir = self.open_checkout_bzrdir("sc")
551
552         os.mkdir("dc")
553         
554         newdir = olddir.sprout('dc')
555
556         self.assertEqual(
557                 olddir.open_branch().last_revision(),
558                 newdir.open_branch().last_revision())
559
560     def test_fetch_dir_upgrade(self):
561         repos_url = self.make_client('d', 'sc')
562
563         self.build_tree({'sc/trunk/mylib/bla': "data", "sc/branches": None})
564         self.client_add("sc/trunk")
565         self.client_add("sc/branches")
566         self.client_commit("sc", "foo")
567
568         self.client_copy("sc/trunk/mylib", "sc/branches/abranch")
569         self.client_commit("sc", "Promote mylib")
570
571         olddir = self.open_checkout_bzrdir("sc/branches/abranch")
572
573         os.mkdir("dc")
574         
575         newdir = olddir.sprout('dc')
576
577         self.assertEqual(
578                 olddir.open_branch().last_revision(),
579                 newdir.open_branch().last_revision())
580
581     def test_fetch_branch_downgrade(self):
582         repos_url = self.make_client('d', 'sc')
583
584         self.build_tree({'sc/trunk': None, "sc/branches/abranch/bla": 'foo'})
585         self.client_add("sc/trunk")
586         self.client_add("sc/branches")
587         self.client_commit("sc", "foo")
588
589         self.client_copy("sc/branches/abranch", "sc/trunk/mylib")
590         self.client_commit("sc", "Demote mylib")
591
592         olddir = self.open_checkout_bzrdir("sc/trunk")
593
594         os.mkdir("dc")
595         
596         newdir = olddir.sprout('dc')
597
598         self.assertEqual(
599                 olddir.open_branch().last_revision(),
600                 newdir.open_branch().last_revision())
601
602
603
604     def test_ghost_workingtree(self):
605         # Looks like bazaar has trouble creating a working tree of a 
606         # revision that has ghost parents
607         self.make_client('d', 'sc')
608
609         self.build_tree({'sc/foo/bla': "data"})
610         self.client_add("sc/foo")
611         self.client_set_prop("sc", "bzr:merge", "some-ghost\n")
612         self.client_commit("sc", "foo")
613
614         olddir = self.open_checkout_bzrdir("sc")
615
616         os.mkdir("dc")
617         
618         newdir = olddir.sprout('dc')
619         newdir.find_repository().get_revision(
620                 newdir.open_branch().last_revision())
621         newdir.find_repository().get_revision_inventory(
622                 newdir.open_branch().last_revision())
623
624 class TestFakeControlFiles(TestCase):
625     def test_get_utf8(self):
626         f = FakeControlFiles()
627         self.assertRaises(NoSuchFile, f.get_utf8, "foo")
628
629
630     def test_get(self):
631         f = FakeControlFiles()
632         self.assertRaises(NoSuchFile, f.get, "foobla")
633
634 class BranchFormatTests(TestCase):
635     def setUp(self):
636         self.format = SvnBranchFormat()
637
638     def test_initialize(self):
639         self.assertRaises(NotImplementedError, self.format.initialize, None)
640
641     def test_get_format_string(self):
642         self.assertEqual("Subversion Smart Server", 
643                          self.format.get_format_string())
644
645     def test_get_format_description(self):
646         self.assertEqual("Subversion Smart Server", 
647                          self.format.get_format_description())