/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_merge_core.py

  • Committer: Robert Collins
  • Date: 2007-07-04 08:08:13 UTC
  • mfrom: (2572 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2587.
  • Revision ID: robertc@robertcollins.net-20070704080813-wzebx0r88fvwj5rq
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
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
 
1
17
import os
2
18
import stat
3
19
import sys
4
20
 
5
21
import bzrlib
 
22
from bzrlib import (
 
23
    generate_ids,
 
24
    osutils,
 
25
    )
6
26
from bzrlib.add import smart_add_tree
7
27
from bzrlib.builtins import merge
8
28
from bzrlib.conflicts import ContentsConflict, TextConflict, PathConflict
10
30
                           WorkingTreeNotRevision, BzrCommandError, NoDiff3)
11
31
import bzrlib.inventory as inventory
12
32
from bzrlib.merge import Merge3Merger, Diff3Merger, WeaveMerger
13
 
from bzrlib.osutils import (file_kind, getcwd, mkdtemp, pathjoin, rename, rmtree,
14
 
                            sha_file, 
 
33
from bzrlib.osutils import (file_kind, getcwd, pathjoin, rename,
 
34
                            sha_file,
15
35
                            )
16
36
from bzrlib.transform import TreeTransform
17
37
from bzrlib.tests import TestCaseWithTransport, TestCase, TestSkipped
20
40
 
21
41
class MergeBuilder(object):
22
42
    def __init__(self, dir=None):
23
 
        self.dir = mkdtemp(prefix="merge-test", dir=dir)
 
43
        self.dir = osutils.mkdtemp(prefix="merge-test", dir=dir)
 
44
        self.tree_root = generate_ids.gen_root_id()
24
45
        def wt(name):
25
46
           path = pathjoin(self.dir, name)
26
47
           os.mkdir(path)
27
48
           wt = bzrlib.bzrdir.BzrDir.create_standalone_workingtree(path)
28
49
           # the tests perform pulls, so need a branch that is writeable.
29
50
           wt.lock_write()
 
51
           wt.set_root_id(self.tree_root)
 
52
           wt.flush()
30
53
           tt = TreeTransform(wt)
31
54
           return wt, tt
32
55
        self.base, self.base_tt = wt('base')
55
78
            # why does this not do wt.pull() ?
56
79
            wt.branch.pull(self.base.branch)
57
80
            wt.set_parent_ids([wt.branch.last_revision()])
 
81
            wt.flush()
 
82
            # We maintain a write lock, so make sure changes are flushed to
 
83
            # disk first
58
84
            tt.apply()
59
85
            wt.commit('branch commit')
 
86
            wt.flush()
60
87
            assert len(wt.branch.revision_history()) == 2
61
88
        self.this.branch.fetch(self.other.branch)
62
89
        other_basis = self.other.branch.basis_tree()
164
191
            new_inventory[file_id] = path
165
192
        return new_inventory
166
193
 
167
 
    def cleanup(self):
 
194
    def unlock(self):
168
195
        self.base.unlock()
169
196
        self.this.unlock()
170
197
        self.other.unlock()
171
 
        rmtree(self.dir)
 
198
 
 
199
    def cleanup(self):
 
200
        self.unlock()
 
201
        osutils.rmtree(self.dir)
172
202
 
173
203
 
174
204
class MergeTest(TestCaseWithTransport):
176
206
    def test_change_name(self):
177
207
        """Test renames"""
178
208
        builder = MergeBuilder(getcwd())
179
 
        builder.add_file("1", "TREE_ROOT", "name1", "hello1", True)
 
209
        builder.add_file("1", builder.tree_root, "name1", "hello1", True)
180
210
        builder.change_name("1", other="name2")
181
 
        builder.add_file("2", "TREE_ROOT", "name3", "hello2", True)
 
211
        builder.add_file("2", builder.tree_root, "name3", "hello2", True)
182
212
        builder.change_name("2", base="name4")
183
 
        builder.add_file("3", "TREE_ROOT", "name5", "hello3", True)
 
213
        builder.add_file("3", builder.tree_root, "name5", "hello3", True)
184
214
        builder.change_name("3", this="name6")
185
215
        builder.merge()
186
216
        builder.cleanup()
187
217
        builder = MergeBuilder(getcwd())
188
 
        builder.add_file("1", "TREE_ROOT", "name1", "hello1", False)
 
218
        builder.add_file("1", builder.tree_root, "name1", "hello1", False)
189
219
        builder.change_name("1", other="name2", this="name3")
190
220
        conflicts = builder.merge()
191
221
        self.assertEqual(conflicts, [PathConflict('name3', 'name2', '1')])
193
223
 
194
224
    def test_merge_one(self):
195
225
        builder = MergeBuilder(getcwd())
196
 
        builder.add_file("1", "TREE_ROOT", "name1", "hello1", True)
 
226
        builder.add_file("1", builder.tree_root, "name1", "hello1", True)
197
227
        builder.change_contents("1", other="text4")
198
 
        builder.add_file("2", "TREE_ROOT", "name2", "hello1", True)
 
228
        builder.add_file("2", builder.tree_root, "name2", "hello1", True)
199
229
        builder.change_contents("2", other="text4")
200
230
        builder.merge(interesting_ids=["1"])
201
231
        self.assertEqual(builder.this.get_file("1").read(), "text4" )
205
235
    def test_file_moves(self):
206
236
        """Test moves"""
207
237
        builder = MergeBuilder(getcwd())
208
 
        builder.add_dir("1", "TREE_ROOT", "dir1")
209
 
        builder.add_dir("2", "TREE_ROOT", "dir2")
 
238
        builder.add_dir("1", builder.tree_root, "dir1")
 
239
        builder.add_dir("2", builder.tree_root, "dir2")
210
240
        builder.add_file("3", "1", "file1", "hello1", True)
211
241
        builder.add_file("4", "1", "file2", "hello2", True)
212
242
        builder.add_file("5", "1", "file3", "hello3", True)
217
247
        builder.cleanup()
218
248
 
219
249
        builder = MergeBuilder(getcwd())
220
 
        builder.add_dir("1", "TREE_ROOT", "dir1")
221
 
        builder.add_dir("2", "TREE_ROOT", "dir2")
222
 
        builder.add_dir("3", "TREE_ROOT", "dir3")
 
250
        builder.add_dir("1", builder.tree_root, "dir1")
 
251
        builder.add_dir("2", builder.tree_root, "dir2")
 
252
        builder.add_dir("3", builder.tree_root, "dir3")
223
253
        builder.add_file("4", "1", "file1", "hello1", False)
224
254
        builder.change_parent("4", other="2", this="3")
225
255
        conflicts = builder.merge()
234
264
 
235
265
    def test_contents_merge2(self):
236
266
        """Test diff3 merging"""
 
267
        if sys.platform == 'win32':
 
268
            raise TestSkipped("diff3 does not have --binary flag"
 
269
                              " and therefore always fails on win32")
237
270
        try:
238
271
            self.do_contents_test(Diff3Merger)
239
272
        except NoDiff3:
246
279
    def test_reprocess_weave(self):
247
280
        # Reprocess works on weaves, and behaves as expected
248
281
        builder = MergeBuilder(getcwd())
249
 
        builder.add_file('a', 'TREE_ROOT', 'blah', 'a', False)
 
282
        builder.add_file('a', builder.tree_root, 'blah', 'a', False)
250
283
        builder.change_contents('a', this='b\nc\nd\ne\n', other='z\nc\nd\ny\n')
251
284
        builder.merge(WeaveMerger, reprocess=True)
252
285
        expected = """<<<<<<< TREE
273
306
 
274
307
    def contents_test_success(self, merge_factory):
275
308
        builder = MergeBuilder(getcwd())
276
 
        builder.add_file("1", "TREE_ROOT", "name1", "text1", True)
 
309
        builder.add_file("1", builder.tree_root, "name1", "text1", True)
277
310
        builder.change_contents("1", other="text4")
278
 
        builder.add_file("2", "TREE_ROOT", "name3", "text2", False)
 
311
        builder.add_file("2", builder.tree_root, "name3", "text2", False)
279
312
        builder.change_contents("2", base="text5")
280
 
        builder.add_file("3", "TREE_ROOT", "name5", "text3", True)
281
 
        builder.add_file("4", "TREE_ROOT", "name6", "text4", True)
 
313
        builder.add_file("3", builder.tree_root, "name5", "text3", True)
 
314
        builder.add_file("4", builder.tree_root, "name6", "text4", True)
282
315
        builder.remove_file("4", base=True)
283
 
        builder.add_file("5", "TREE_ROOT", "name7", "a\nb\nc\nd\ne\nf\n", True)
 
316
        builder.add_file("5", builder.tree_root, "name7", "a\nb\nc\nd\ne\nf\n",
 
317
                         True)
284
318
        builder.change_contents("5", other="a\nz\nc\nd\ne\nf\n", 
285
319
                                     this="a\nb\nc\nd\ne\nz\n")
286
 
        builder.merge(merge_factory)
287
 
        self.assertEqual(builder.this.get_file("1").read(), "text4" )
288
 
        self.assertEqual(builder.this.get_file("2").read(), "text2" )
289
 
        self.assertEqual(builder.this.get_file("5").read(), 
290
 
                         "a\nz\nc\nd\ne\nz\n")
291
 
        self.assertIs(builder.this.is_executable("1"), True)
292
 
        self.assertIs(builder.this.is_executable("2"), False)
293
 
        self.assertIs(builder.this.is_executable("3"), True)
 
320
        conflicts = builder.merge(merge_factory)
 
321
        try:
 
322
            self.assertEqual([], conflicts)
 
323
            self.assertEqual("text4", builder.this.get_file("1").read())
 
324
            self.assertEqual("text2", builder.this.get_file("2").read())
 
325
            self.assertEqual("a\nz\nc\nd\ne\nz\n", 
 
326
                             builder.this.get_file("5").read())
 
327
            self.assertTrue(builder.this.is_executable("1"))
 
328
            self.assertFalse(builder.this.is_executable("2"))
 
329
            self.assertTrue(builder.this.is_executable("3"))
 
330
        except:
 
331
            builder.unlock()
 
332
            raise
294
333
        return builder
295
334
 
296
335
    def contents_test_conflicts(self, merge_factory):
297
336
        builder = MergeBuilder(getcwd())
298
 
        builder.add_file("1", "TREE_ROOT", "name1", "text1", True)
 
337
        builder.add_file("1", builder.tree_root, "name1", "text1", True)
299
338
        builder.change_contents("1", other="text4", this="text3")
300
 
        builder.add_file("2", "TREE_ROOT", "name2", "text1", True)
 
339
        builder.add_file("2", builder.tree_root, "name2", "text1", True)
301
340
        builder.change_contents("2", other="\x00", this="text3")
302
 
        builder.add_file("3", "TREE_ROOT", "name3", "text5", False)
 
341
        builder.add_file("3", builder.tree_root, "name3", "text5", False)
303
342
        builder.change_perms("3", this=True)
304
343
        builder.change_contents('3', this='moretext')
305
344
        builder.remove_file('3', other=True)
313
352
    def test_symlink_conflicts(self):
314
353
        if sys.platform != "win32":
315
354
            builder = MergeBuilder(getcwd())
316
 
            builder.add_symlink("2", "TREE_ROOT", "name2", "target1")
 
355
            builder.add_symlink("2", builder.tree_root, "name2", "target1")
317
356
            builder.change_target("2", other="target4", base="text3")
318
357
            conflicts = builder.merge()
319
358
            self.assertEqual(conflicts, [ContentsConflict('name2', 
323
362
    def test_symlink_merge(self):
324
363
        if sys.platform != "win32":
325
364
            builder = MergeBuilder(getcwd())
326
 
            builder.add_symlink("1", "TREE_ROOT", "name1", "target1")
327
 
            builder.add_symlink("2", "TREE_ROOT", "name2", "target1")
328
 
            builder.add_symlink("3", "TREE_ROOT", "name3", "target1")
 
365
            builder.add_symlink("1", builder.tree_root, "name1", "target1")
 
366
            builder.add_symlink("2", builder.tree_root, "name2", "target1")
 
367
            builder.add_symlink("3", builder.tree_root, "name3", "target1")
329
368
            builder.change_target("1", this="target2")
330
369
            builder.change_target("2", base="target2")
331
370
            builder.change_target("3", other="target2")
337
376
 
338
377
    def test_no_passive_add(self):
339
378
        builder = MergeBuilder(getcwd())
340
 
        builder.add_file("1", "TREE_ROOT", "name1", "text1", True)
 
379
        builder.add_file("1", builder.tree_root, "name1", "text1", True)
341
380
        builder.remove_file("1", this=True)
342
381
        builder.merge()
343
382
        builder.cleanup()
344
383
 
345
384
    def test_perms_merge(self):
346
385
        builder = MergeBuilder(getcwd())
347
 
        builder.add_file("1", "TREE_ROOT", "name1", "text1", True)
 
386
        builder.add_file("1", builder.tree_root, "name1", "text1", True)
348
387
        builder.change_perms("1", other=False)
349
 
        builder.add_file("2", "TREE_ROOT", "name2", "text2", True)
 
388
        builder.add_file("2", builder.tree_root, "name2", "text2", True)
350
389
        builder.change_perms("2", base=False)
351
 
        builder.add_file("3", "TREE_ROOT", "name3", "text3", True)
 
390
        builder.add_file("3", builder.tree_root, "name3", "text3", True)
352
391
        builder.change_perms("3", this=False)
353
 
        builder.add_file('4', 'TREE_ROOT', 'name4', 'text4', False)
 
392
        builder.add_file('4', builder.tree_root, 'name4', 'text4', False)
354
393
        builder.change_perms('4', this=True)
355
394
        builder.remove_file('4', base=True)
356
395
        builder.merge()
361
400
 
362
401
    def test_new_suffix(self):
363
402
        builder = MergeBuilder(getcwd())
364
 
        builder.add_file("1", "TREE_ROOT", "name1", "text1", True)
 
403
        builder.add_file("1", builder.tree_root, "name1", "text1", True)
365
404
        builder.change_contents("1", other="text3")
366
 
        builder.add_file("2", "TREE_ROOT", "name1.new", "text2", True)
 
405
        builder.add_file("2", builder.tree_root, "name1.new", "text2", True)
367
406
        builder.merge()
368
407
        os.lstat(builder.this.id2abspath("2"))
369
408
        builder.cleanup()
370
409
 
371
410
    def test_spurious_conflict(self):
372
411
        builder = MergeBuilder(getcwd())
373
 
        builder.add_file("1", "TREE_ROOT", "name1", "text1", False)
 
412
        builder.add_file("1", builder.tree_root, "name1", "text1", False)
374
413
        builder.remove_file("1", other=True)
375
 
        builder.add_file("2", "TREE_ROOT", "name1", "text1", False, this=False, 
376
 
                         base=False)
 
414
        builder.add_file("2", builder.tree_root, "name1", "text1", False, 
 
415
                         this=False, base=False)
377
416
        conflicts = builder.merge()
378
417
        self.assertEqual(conflicts, []) 
379
418
        builder.cleanup()
483
522
        file('a/file', 'wb').write('contents\n')
484
523
        wta.add('file')
485
524
        wta.commit('a_revision', allow_pointless=False)
486
 
        self.run_bzr('branch', 'a', 'b')
 
525
        self.run_bzr(['branch', 'a', 'b'])
487
526
        os.remove('a/file')
488
527
        wta.commit('removed file', allow_pointless=False)
489
528
        file('b/file', 'wb').write('changed contents\n')
498
537
        file('a/file', 'wb').write('contents\n')
499
538
        a_wt.add('file')
500
539
        a_wt.commit('r0')
501
 
        self.run_bzr('branch', 'a', 'b')
 
540
        self.run_bzr(['branch', 'a', 'b'])
502
541
        b_wt = WorkingTree.open('b')
503
542
        os.chmod('b/file', 0755)
504
543
        os.remove('a/file')
513
552
        a_wt = self.make_branch_and_tree('a')
514
553
        file('a/un','wb').write('UN')
515
554
        file('a/deux','wb').write('DEUX')
516
 
        a_wt.add('un', 'un')
517
 
        a_wt.add('deux', 'deux')
 
555
        a_wt.add('un', 'un-id')
 
556
        a_wt.add('deux', 'deux-id')
518
557
        a_wt.commit('r0', rev_id='r0')
519
 
        self.run_bzr('branch', 'a', 'b')
 
558
        self.run_bzr(['branch', 'a', 'b'])
520
559
        b_wt = WorkingTree.open('b')
521
560
        b_wt.rename_one('un','tmp')
522
561
        b_wt.rename_one('deux','un')
534
573
        file('a/file', 'wb').write('THIS')
535
574
        a_wt.add('file')
536
575
        a_wt.commit('r0')
537
 
        self.run_bzr('branch', 'a', 'b')
 
576
        self.run_bzr(['branch', 'a', 'b'])
538
577
        b_wt = WorkingTree.open('b')
539
578
        os.remove('b/file')
540
579
        b_wt.commit('r1')
563
602
        file('a/foo', 'wb').write('A/FOO')
564
603
        a_wt.add('foo')
565
604
        a_wt.commit('added foo')
566
 
        self.run_bzr('branch', 'a', 'b')
 
605
        self.run_bzr(['branch', 'a', 'b'])
567
606
        b_wt = WorkingTree.open('b')
568
607
        b_wt.rename_one('foo', 'bar')
569
608
        file('b/foo', 'wb').write('B/FOO')
591
630
        file('a/foo', 'wb').write('A/FOO')
592
631
        a_wt.add('foo')
593
632
        a_wt.commit('added foo')
594
 
        self.run_bzr('branch', 'a', 'b')
 
633
        self.run_bzr('branch a b')
595
634
        b_wt = WorkingTree.open('b')
596
635
        os.mkdir('b/bar')
597
636
        b_wt.add('bar')
620
659
        a_wt.add('foo')
621
660
        a_wt.add('foo/bar')
622
661
        a_wt.commit('added foo/bar')
623
 
        self.run_bzr('branch', 'a', 'b')
 
662
        self.run_bzr(['branch', 'a', 'b'])
624
663
        b_wt = WorkingTree.open('b')
625
664
        b_wt.rename_one('foo/bar', 'bar')
626
665
        os.rmdir('b/foo')
649
688
        a_wt.add('foo')
650
689
        a_wt.add('bar')
651
690
        a_wt.commit('added foo and bar')
652
 
        self.run_bzr('branch', 'a', 'b')
 
691
        self.run_bzr(['branch', 'a', 'b'])
653
692
        b_wt = WorkingTree.open('b')
654
693
        os.unlink('b/foo')
655
694
        b_wt.remove('foo')