Merge 0.3.2
[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 from bzrlib.branch import Branch
18 from bzrlib.bzrdir import BzrDir, BzrDirTestProviderAdapter, BzrDirFormat
19 from bzrlib.errors import NoSuchFile
20 from bzrlib.inventory import ROOT_ID
21 from bzrlib.repository import Repository
22 from bzrlib.trace import mutter
23
24 import os
25 from unittest import TestCase
26
27 import svn.core, svn.client
28
29 from branch import FakeControlFiles, SvnBranchFormat
30 from convert import load_dumpfile
31 import format
32 from repository import MAPPING_VERSION, generate_svn_revision_id
33 from tests import TestCaseWithSubversionRepository
34
35 class WorkingSubversionBranch(TestCaseWithSubversionRepository):
36     def test_last_rev_rev_hist(self):
37         repos_url = self.make_client("a", "dc")
38         branch = Branch.open(repos_url)
39         branch.revision_history()
40         self.assertEqual(None, branch.last_revision())
41
42     def test_set_parent(self):
43         repos_url = self.make_client('a', 'dc')
44         branch = Branch.open(repos_url)
45         branch.set_parent("foobar")
46
47     def test_num_revnums(self):
48         repos_url = self.make_client('a', 'dc')
49         bzrdir = BzrDir.open("svn+"+repos_url)
50         branch = bzrdir.open_branch()
51         self.assertEqual(None, 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(ROOT_ID, 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(ROOT_ID, 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.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(1, "")], 
140                 branch.revision_history())
141
142         self.build_tree({'dc/foo': "data34"})
143         self.client_commit("dc", "My Message")
144
145         branch = Branch.open("svn+"+repos_url)
146         repos = Repository.open("svn+"+repos_url)
147
148         self.assertEqual([
149             repos.generate_revision_id(1, ""),
150             repos.generate_revision_id(2, "")],
151             branch.revision_history())
152
153     def test_get_nick_none(self):
154         repos_url = self.make_client('a', 'dc')
155
156         self.build_tree({'dc/foo': "data"})
157         self.client_add("dc/foo")
158         self.client_commit("dc", "My Message")
159
160         branch = Branch.open("svn+"+repos_url)
161
162         self.assertIs(None, branch.nick)
163
164     def test_get_nick_path(self):
165         repos_url = self.make_client('a', 'dc')
166
167         self.build_tree({'dc/trunk': "data"})
168         self.client_add("dc/trunk")
169         self.client_commit("dc", "My Message")
170
171         branch = Branch.open("svn+"+repos_url+"/trunk")
172
173         self.assertEqual("trunk", branch.nick)
174
175     def test_get_revprops(self):
176         repos_url = self.make_client('a', 'dc')
177
178         self.build_tree({'dc/foo': "data"})
179         self.client_add("dc/foo")
180         self.client_set_prop("dc", "bzr:revprop:branch-nick", "mybranch")
181         self.client_commit("dc", "My Message")
182
183         branch = Branch.open("svn+"+repos_url)
184
185         rev = branch.repository.get_revision(branch.last_revision())
186
187         self.assertEqual("mybranch", rev.properties["branch-nick"])
188
189     def test_fetch_replace(self):
190         filename = os.path.join(self.test_dir, "dumpfile")
191         open(filename, 'w').write("""SVN-fs-dump-format-version: 2
192
193 UUID: 6f95bc5c-e18d-4021-aca8-49ed51dbcb75
194
195 Revision-number: 0
196 Prop-content-length: 56
197 Content-length: 56
198
199 K 8
200 svn:date
201 V 27
202 2006-07-30T12:41:25.270824Z
203 PROPS-END
204
205 Revision-number: 1
206 Prop-content-length: 94
207 Content-length: 94
208
209 K 7
210 svn:log
211 V 0
212
213 K 10
214 svn:author
215 V 0
216
217 K 8
218 svn:date
219 V 27
220 2006-07-30T12:41:26.117512Z
221 PROPS-END
222
223 Node-path: trunk
224 Node-kind: dir
225 Node-action: add
226 Prop-content-length: 10
227 Content-length: 10
228
229 PROPS-END
230
231
232 Node-path: trunk/hosts
233 Node-kind: file
234 Node-action: add
235 Prop-content-length: 10
236 Text-content-length: 4
237 Text-content-md5: 771ec3328c29d17af5aacf7f895dd885
238 Content-length: 14
239
240 PROPS-END
241 hej1
242
243 Revision-number: 2
244 Prop-content-length: 94
245 Content-length: 94
246
247 K 7
248 svn:log
249 V 0
250
251 K 10
252 svn:author
253 V 0
254
255 K 8
256 svn:date
257 V 27
258 2006-07-30T12:41:27.130044Z
259 PROPS-END
260
261 Node-path: trunk/hosts
262 Node-kind: file
263 Node-action: change
264 Text-content-length: 4
265 Text-content-md5: 6c2479dbb342b8df96d84db7ab92c412
266 Content-length: 4
267
268 hej2
269
270 Revision-number: 3
271 Prop-content-length: 94
272 Content-length: 94
273
274 K 7
275 svn:log
276 V 0
277
278 K 10
279 svn:author
280 V 0
281
282 K 8
283 svn:date
284 V 27
285 2006-07-30T12:41:28.114350Z
286 PROPS-END
287
288 Node-path: trunk/hosts
289 Node-kind: file
290 Node-action: change
291 Text-content-length: 4
292 Text-content-md5: 368cb8d3db6186e2e83d9434f165c525
293 Content-length: 4
294
295 hej3
296
297 Revision-number: 4
298 Prop-content-length: 94
299 Content-length: 94
300
301 K 7
302 svn:log
303 V 0
304
305 K 10
306 svn:author
307 V 0
308
309 K 8
310 svn:date
311 V 27
312 2006-07-30T12:41:29.129563Z
313 PROPS-END
314
315 Node-path: branches
316 Node-kind: dir
317 Node-action: add
318 Prop-content-length: 10
319 Content-length: 10
320
321 PROPS-END
322
323
324 Revision-number: 5
325 Prop-content-length: 94
326 Content-length: 94
327
328 K 7
329 svn:log
330 V 0
331
332 K 10
333 svn:author
334 V 0
335
336 K 8
337 svn:date
338 V 27
339 2006-07-30T12:41:31.130508Z
340 PROPS-END
341
342 Node-path: branches/foobranch
343 Node-kind: dir
344 Node-action: add
345 Node-copyfrom-rev: 4
346 Node-copyfrom-path: trunk
347
348
349 Revision-number: 6
350 Prop-content-length: 94
351 Content-length: 94
352
353 K 7
354 svn:log
355 V 0
356
357 K 10
358 svn:author
359 V 0
360
361 K 8
362 svn:date
363 V 27
364 2006-07-30T12:41:33.129149Z
365 PROPS-END
366
367 Node-path: branches/foobranch/hosts
368 Node-kind: file
369 Node-action: delete
370
371 Node-path: branches/foobranch/hosts
372 Node-kind: file
373 Node-action: add
374 Node-copyfrom-rev: 2
375 Node-copyfrom-path: trunk/hosts
376
377
378
379
380 Revision-number: 7
381 Prop-content-length: 94
382 Content-length: 94
383
384 K 7
385 svn:log
386 V 0
387
388 K 10
389 svn:author
390 V 0
391
392 K 8
393 svn:date
394 V 27
395 2006-07-30T12:41:34.136423Z
396 PROPS-END
397
398 Node-path: branches/foobranch/hosts
399 Node-kind: file
400 Node-action: change
401 Text-content-length: 8
402 Text-content-md5: 0e328d3517a333a4879ebf3d88fd82bb
403 Content-length: 8
404
405 foohosts""")
406         os.mkdir("new")
407         os.mkdir("old")
408
409         load_dumpfile("dumpfile", "old")
410
411         url = "old/branches/foobranch"
412         mutter('open %r' % url)
413         olddir = BzrDir.open(url)
414
415         newdir = olddir.sprout("new")
416
417         newbranch = newdir.open_branch()
418
419         uuid = "6f95bc5c-e18d-4021-aca8-49ed51dbcb75"
420         tree = newbranch.repository.revision_tree(
421                 generate_svn_revision_id(uuid, 7, "branches/foobranch"))
422
423         weave = tree.get_weave(tree.inventory.path2id("hosts"))
424         self.assertEqual([
425             generate_svn_revision_id(uuid, 6, "branches/foobranch"),
426             generate_svn_revision_id(uuid, 7, "branches/foobranch")],
427                           weave.versions())
428  
429
430     def test_fetch_odd(self):
431         repos_url = self.make_client('d', 'dc')
432
433         self.build_tree({'dc/trunk': None, 
434                          'dc/trunk/hosts': 'hej1'})
435         self.client_add("dc/trunk")
436         self.client_commit("dc", "created trunk and added hosts") #1
437
438         self.build_tree({'dc/trunk/hosts': 'hej2'})
439         self.client_commit("dc", "rev 2") #2
440
441         self.build_tree({'dc/trunk/hosts': 'hej3'})
442         self.client_commit("dc", "rev 3") #3
443
444         self.build_tree({'dc/branches': None})
445         self.client_add("dc/branches")
446         self.client_commit("dc", "added branches") #4
447
448         self.client_copy("dc/trunk", "dc/branches/foobranch")
449         self.client_commit("dc", "added branch foobranch") #5
450
451         self.build_tree({'dc/branches/foobranch/hosts': 'foohosts'})
452         self.client_commit("dc", "foohosts") #6
453
454         os.mkdir("new")
455
456         url = "svn+"+repos_url+"/branches/foobranch"
457         mutter('open %r' % url)
458         olddir = BzrDir.open(url)
459
460         newdir = olddir.sprout("new")
461
462         newbranch = newdir.open_branch()
463
464         uuid = olddir.find_repository().uuid
465         tree = newbranch.repository.revision_tree(
466                 generate_svn_revision_id(uuid, 6, "branches/foobranch"))
467
468         weave = tree.get_weave(tree.inventory.path2id("hosts"))
469         self.assertEqual([
470             generate_svn_revision_id(uuid, 1, "trunk"),
471             generate_svn_revision_id(uuid, 2, "trunk"),
472             generate_svn_revision_id(uuid, 3, "trunk"),
473             generate_svn_revision_id(uuid, 6, "branches/foobranch")],
474                           weave.versions())
475
476     def test_check(self):
477         repos_url = self.make_client('d', 'dc')
478         branch = Branch.open('d')
479         result = branch.check()
480         self.assertEqual(branch, result.branch) 
481  
482     def test_generate_revision_id(self):
483         repos_url = self.make_client('d', 'dc')
484         branch = Branch.open('d')
485         self.assertEqual("svn-v%d-undefined:%s::1" % (MAPPING_VERSION, branch.repository.uuid),  branch.generate_revision_id(1))
486
487     def test_create_checkout(self):
488         repos_url = self.make_client('d', 'dc')
489
490         self.build_tree({'dc/trunk': None, 'dc/trunk/hosts': 'hej1'})
491         self.client_add("dc/trunk")
492         self.client_commit("dc", "created trunk and added hosts") #1
493
494         url = "svn+"+repos_url+"/trunk"
495         oldbranch = Branch.open(url)
496
497         newtree = oldbranch.create_checkout("e")
498         self.assertTrue(newtree.branch.repository.has_revision(
499            oldbranch.generate_revision_id(1)))
500
501         self.assertTrue(os.path.exists("e/.bzr"))
502         self.assertFalse(os.path.exists("e/.svn"))
503
504     def test_create_checkout_lightweight(self):
505         repos_url = self.make_client('d', 'dc')
506
507         self.build_tree({'dc/trunk': None, 
508                          'dc/trunk/hosts': 'hej1'})
509         self.client_add("dc/trunk")
510         self.client_commit("dc", "created trunk and added hosts") #1
511
512         url = "svn+"+repos_url+"/trunk"
513         oldbranch = Branch.open(url)
514
515         newtree = oldbranch.create_checkout("e", lightweight=True)
516         self.assertEqual(oldbranch.generate_revision_id(1), newtree.base_revid)
517         self.assertTrue(os.path.exists("e/.svn"))
518         self.assertFalse(os.path.exists("e/.bzr"))
519
520     def test_create_checkout_lightweight_stop_rev(self):
521         repos_url = self.make_client('d', 'dc')
522
523         self.build_tree({'dc/trunk': None, 
524                          'dc/trunk/hosts': 'hej1'})
525         self.client_add("dc/trunk")
526         self.client_commit("dc", "created trunk and added hosts") #1
527         
528         self.build_tree({'dc/trunk/hosts': 'bloe'})
529         self.client_commit("dc", "added another revision")
530
531         url = "svn+"+repos_url+"/trunk"
532         oldbranch = Branch.open(url)
533
534         newtree = oldbranch.create_checkout("e", revision_id=
535            oldbranch.generate_revision_id(1), lightweight=True)
536         self.assertEqual(oldbranch.generate_revision_id(1),
537            newtree.base_revid)
538         self.assertTrue(os.path.exists("e/.svn"))
539         self.assertFalse(os.path.exists("e/.bzr"))
540
541     def test_fetch_branch(self):
542         repos_url = self.make_client('d', 'sc')
543
544         self.build_tree({'sc/foo/bla': "data"})
545         self.client_add("sc/foo")
546         self.client_commit("sc", "foo")
547
548         olddir = BzrDir.open("sc")
549
550         os.mkdir("dc")
551         
552         newdir = olddir.sprout('dc')
553
554         self.assertEqual(
555                 olddir.open_branch().last_revision(),
556                 newdir.open_branch().last_revision())
557
558     def test_ghost_workingtree(self):
559         # Looks like bazaar has trouble creating a working tree of a 
560         # revision that has ghost parents
561         repos_url = self.make_client('d', 'sc')
562
563         self.build_tree({'sc/foo/bla': "data"})
564         self.client_add("sc/foo")
565         self.client_set_prop("sc", "bzr:merge", "some-ghost\n")
566         self.client_commit("sc", "foo")
567
568         olddir = BzrDir.open("sc")
569
570         os.mkdir("dc")
571         
572         newdir = olddir.sprout('dc')
573         newdir.find_repository().get_revision(
574                 newdir.open_branch().last_revision())
575         newdir.find_repository().get_revision_inventory(
576                 newdir.open_branch().last_revision())
577
578 class TestFakeControlFiles(TestCase):
579     def test_get_utf8(self):
580         f = FakeControlFiles()
581         self.assertRaises(NoSuchFile, f.get_utf8, "foo")
582
583
584     def test_get(self):
585         f = FakeControlFiles()
586         self.assertRaises(NoSuchFile, f.get, "foobla")
587
588 class BranchFormatTests(TestCase):
589     def setUp(self):
590         self.format = SvnBranchFormat()
591
592     def test_initialize(self):
593         self.assertRaises(NotImplementedError, self.format.initialize, None)
594
595     def test_get_format_string(self):
596         self.assertEqual("Subversion Smart Server", 
597                          self.format.get_format_string())
598
599     def test_get_format_description(self):
600         self.assertEqual("Subversion Smart Server", 
601                          self.format.get_format_description())