215
291
tree1 = self.make_branch_and_tree('1')
216
292
tree2 = self.make_to_branch_and_tree('2')
217
293
tree1 = self.get_tree_no_parents_no_content(tree1)
218
tree2 = self.get_to_tree_no_parents_abc_content(tree2)
294
tree2 = self.get_tree_no_parents_abc_content(tree2)
295
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
219
296
self.assertRaises(errors.PathsNotVersionedError,
220
297
self.intertree_class(tree1, tree2).compare,
221
298
specific_files=['d'],
222
299
require_versioned=True)
301
def test_default_ignores_unversioned_files(self):
302
tree1 = self.make_branch_and_tree('tree1')
303
tree2 = self.make_to_branch_and_tree('tree2')
304
tree2.set_root_id(tree1.get_root_id())
305
self.build_tree(['tree1/a', 'tree1/c',
306
'tree2/a', 'tree2/b', 'tree2/c'])
307
tree1.add(['a', 'c'], ['a-id', 'c-id'])
308
tree2.add(['a', 'c'], ['a-id', 'c-id'])
310
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
311
d = self.intertree_class(tree1, tree2).compare()
312
self.assertEqual([], d.added)
313
self.assertEqual([(u'a', 'a-id', 'file', True, False),
314
(u'c', 'c-id', 'file', True, False)], d.modified)
315
self.assertEqual([], d.removed)
316
self.assertEqual([], d.renamed)
317
self.assertEqual([], d.unchanged)
318
self.assertEqual([], d.unversioned)
320
def test_unversioned_paths_in_tree(self):
321
tree1 = self.make_branch_and_tree('tree1')
322
tree2 = self.make_to_branch_and_tree('tree2')
323
tree2.set_root_id(tree1.get_root_id())
324
self.build_tree(['tree2/file', 'tree2/dir/'])
326
os.symlink('target', 'tree2/link')
327
links_supported = True
329
links_supported = False
330
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
331
d = self.intertree_class(tree1, tree2).compare(want_unversioned=True)
332
self.assertEqual([], d.added)
333
self.assertEqual([], d.modified)
334
self.assertEqual([], d.removed)
335
self.assertEqual([], d.renamed)
336
self.assertEqual([], d.unchanged)
337
expected_unversioned = [(u'dir', None, 'directory'),
338
(u'file', None, 'file')]
340
expected_unversioned.append((u'link', None, 'symlink'))
341
self.assertEqual(expected_unversioned, d.unversioned)
344
class TestIterChanges(TestCaseWithTwoTrees):
345
"""Test the comparison iterator"""
347
def do_iter_changes(self, tree1, tree2, **extra_args):
348
"""Helper to run iter_changes from tree1 to tree2.
350
:param tree1, tree2: The source and target trees. These will be locked
352
:param **extra_args: Extra args to pass to iter_changes. This is not
353
inspected by this test helper.
358
# sort order of output is not strictly defined
359
return sorted(self.intertree_class(tree1, tree2)
360
.iter_changes(**extra_args))
365
def mutable_trees_to_locked_test_trees(self, tree1, tree2):
366
"""Convert the working trees into test trees.
368
Read lock them, and add the unlock to the cleanup.
370
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
372
self.addCleanup(tree1.unlock)
374
self.addCleanup(tree2.unlock)
377
def make_tree_with_special_names(self):
378
"""Create a tree with filenames chosen to exercise the walk order."""
379
tree1 = self.make_branch_and_tree('tree1')
380
tree2 = self.make_to_branch_and_tree('tree2')
381
tree2.set_root_id(tree1.get_root_id())
382
paths, path_ids = self._create_special_names(tree2, 'tree2')
383
tree2.commit('initial', rev_id='rev-1')
384
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
385
return (tree1, tree2, paths, path_ids)
387
def make_trees_with_special_names(self):
388
"""Both trees will use the special names.
390
But the contents will differ for each file.
392
tree1 = self.make_branch_and_tree('tree1')
393
tree2 = self.make_to_branch_and_tree('tree2')
394
tree2.set_root_id(tree1.get_root_id())
395
paths, path_ids = self._create_special_names(tree1, 'tree1')
396
paths, path_ids = self._create_special_names(tree2, 'tree2')
397
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
398
return (tree1, tree2, paths, path_ids)
400
def _create_special_names(self, tree, base_path):
401
"""Create a tree with paths that expose differences in sort orders."""
402
# Each directory will have a single file named 'f' inside
417
with_slashes.append(base_path + '/' + d + '/')
418
with_slashes.append(base_path + '/' + d + '/f')
421
path_ids.append(d.replace('/', '_') + '-id')
422
path_ids.append(d.replace('/', '_') + '_f-id')
423
self.build_tree(with_slashes)
424
tree.add(paths, path_ids)
425
return paths, path_ids
427
def test_compare_empty_trees(self):
428
tree1 = self.make_branch_and_tree('1')
429
tree2 = self.make_to_branch_and_tree('2')
430
tree1 = self.get_tree_no_parents_no_content(tree1)
431
tree2 = self.get_tree_no_parents_no_content(tree2)
432
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
433
self.assertEqual([], self.do_iter_changes(tree1, tree2))
435
def added(self, tree, file_id):
436
entry = tree.inventory[file_id]
437
path = tree.id2path(file_id)
438
return (file_id, (None, path), True, (False, True), (None, entry.parent_id),
439
(None, entry.name), (None, entry.kind),
440
(None, entry.executable))
442
def content_changed(self, tree, file_id):
443
entry = tree.inventory[file_id]
444
path = tree.id2path(file_id)
445
return (file_id, (path, path), True, (True, True), (entry.parent_id, entry.parent_id),
446
(entry.name, entry.name), (entry.kind, entry.kind),
447
(entry.executable, entry.executable))
449
def kind_changed(self, from_tree, to_tree, file_id):
450
old_entry = from_tree.inventory[file_id]
451
new_entry = to_tree.inventory[file_id]
452
path = to_tree.id2path(file_id)
453
from_path = from_tree.id2path(file_id)
454
return (file_id, (from_path, path), True, (True, True), (old_entry.parent_id, new_entry.parent_id),
455
(old_entry.name, new_entry.name), (old_entry.kind, new_entry.kind),
456
(old_entry.executable, new_entry.executable))
458
def missing(self, file_id, from_path, to_path, parent_id, kind):
459
_, from_basename = os.path.split(from_path)
460
_, to_basename = os.path.split(to_path)
461
# missing files have both paths, but no kind.
462
return (file_id, (from_path, to_path), True, (True, True),
463
(parent_id, parent_id),
464
(from_basename, to_basename), (kind, None), (False, False))
466
def deleted(self, tree, file_id):
467
entry = tree.inventory[file_id]
468
path = tree.id2path(file_id)
469
return (file_id, (path, None), True, (True, False), (entry.parent_id, None),
470
(entry.name, None), (entry.kind, None),
471
(entry.executable, None))
473
def renamed(self, from_tree, to_tree, file_id, content_changed):
474
from_entry = from_tree.inventory[file_id]
475
to_entry = to_tree.inventory[file_id]
476
from_path = from_tree.id2path(file_id)
477
to_path = to_tree.id2path(file_id)
478
return (file_id, (from_path, to_path), content_changed, (True, True),
479
(from_entry.parent_id, to_entry.parent_id),
480
(from_entry.name, to_entry.name),
481
(from_entry.kind, to_entry.kind),
482
(from_entry.executable, to_entry.executable))
484
def unchanged(self, tree, file_id):
485
entry = tree.inventory[file_id]
486
parent = entry.parent_id
489
executable = entry.executable
490
path = tree.id2path(file_id)
491
return (file_id, (path, path), False, (True, True),
492
(parent, parent), (name, name), (kind, kind),
493
(executable, executable))
495
def unversioned(self, tree, path):
496
"""Create an unversioned result."""
497
_, basename = os.path.split(path)
498
kind = file_kind(tree.abspath(path))
499
return (None, (None, path), True, (False, False), (None, None),
500
(None, basename), (None, kind),
503
def test_empty_to_abc_content(self):
504
tree1 = self.make_branch_and_tree('1')
505
tree2 = self.make_to_branch_and_tree('2')
506
tree1 = self.get_tree_no_parents_no_content(tree1)
507
tree2 = self.get_tree_no_parents_abc_content(tree2)
508
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
509
expected_results = sorted([
510
self.added(tree2, 'root-id'),
511
self.added(tree2, 'a-id'),
512
self.added(tree2, 'b-id'),
513
self.added(tree2, 'c-id'),
514
self.deleted(tree1, 'empty-root-id')])
515
self.assertEqual(expected_results, self.do_iter_changes(tree1, tree2))
517
def test_empty_specific_files(self):
518
tree1 = self.make_branch_and_tree('1')
519
tree2 = self.make_to_branch_and_tree('2')
520
tree1 = self.get_tree_no_parents_no_content(tree1)
521
tree2 = self.get_tree_no_parents_abc_content(tree2)
522
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
524
self.do_iter_changes(tree1, tree2, specific_files=[]))
526
def test_no_specific_files(self):
527
tree1 = self.make_branch_and_tree('1')
528
tree2 = self.make_to_branch_and_tree('2')
529
tree1 = self.get_tree_no_parents_no_content(tree1)
530
tree2 = self.get_tree_no_parents_abc_content(tree2)
531
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
532
expected_results = sorted([
533
self.added(tree2, 'root-id'),
534
self.added(tree2, 'a-id'),
535
self.added(tree2, 'b-id'),
536
self.added(tree2, 'c-id'),
537
self.deleted(tree1, 'empty-root-id')])
538
self.assertEqual(expected_results, self.do_iter_changes(tree1, tree2))
540
def test_empty_to_abc_content_a_only(self):
541
tree1 = self.make_branch_and_tree('1')
542
tree2 = self.make_to_branch_and_tree('2')
543
tree1 = self.get_tree_no_parents_no_content(tree1)
544
tree2 = self.get_tree_no_parents_abc_content(tree2)
545
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
547
[self.added(tree2, 'a-id')],
548
self.do_iter_changes(tree1, tree2, specific_files=['a']))
550
def test_abc_content_to_empty_to_abc_content_a_only(self):
551
tree1 = self.make_branch_and_tree('1')
552
tree2 = self.make_to_branch_and_tree('2')
553
tree1 = self.get_tree_no_parents_abc_content(tree1)
554
tree2 = self.get_tree_no_parents_no_content(tree2)
555
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
557
[self.deleted(tree1, 'a-id')],
558
self.do_iter_changes(tree1, tree2, specific_files=['a']))
560
def test_empty_to_abc_content_a_and_c_only(self):
561
tree1 = self.make_branch_and_tree('1')
562
tree2 = self.make_to_branch_and_tree('2')
563
tree1 = self.get_tree_no_parents_no_content(tree1)
564
tree2 = self.get_tree_no_parents_abc_content(tree2)
565
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
566
expected_result = [self.added(tree2, 'a-id'), self.added(tree2, 'c-id')]
567
self.assertEqual(expected_result,
568
self.do_iter_changes(tree1, tree2, specific_files=['a', 'b/c']))
570
def test_abc_content_to_empty(self):
571
tree1 = self.make_branch_and_tree('1')
572
tree2 = self.make_to_branch_and_tree('2')
573
tree1 = self.get_tree_no_parents_abc_content(tree1)
574
tree2 = self.get_tree_no_parents_no_content(tree2)
575
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
576
def deleted(file_id):
577
entry = tree1.inventory[file_id]
578
path = tree1.id2path(file_id)
579
return (file_id, (path, None), True, (True, False),
580
(entry.parent_id, None),
581
(entry.name, None), (entry.kind, None),
582
(entry.executable, None))
583
expected_results = sorted([
584
self.added(tree2, 'empty-root-id'),
585
deleted('root-id'), deleted('a-id'),
586
deleted('b-id'), deleted('c-id')])
589
self.do_iter_changes(tree1, tree2))
591
def test_content_modification(self):
592
tree1 = self.make_branch_and_tree('1')
593
tree2 = self.make_to_branch_and_tree('2')
594
tree1 = self.get_tree_no_parents_abc_content(tree1)
595
tree2 = self.get_tree_no_parents_abc_content_2(tree2)
596
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
597
root_id = tree1.path2id('')
598
self.assertEqual([('a-id', ('a', 'a'), True, (True, True),
599
(root_id, root_id), ('a', 'a'),
600
('file', 'file'), (False, False))],
601
self.do_iter_changes(tree1, tree2))
603
def test_meta_modification(self):
604
tree1 = self.make_branch_and_tree('1')
605
tree2 = self.make_to_branch_and_tree('2')
606
tree1 = self.get_tree_no_parents_abc_content(tree1)
607
tree2 = self.get_tree_no_parents_abc_content_3(tree2)
608
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
609
self.assertEqual([('c-id', ('b/c', 'b/c'), False, (True, True),
610
('b-id', 'b-id'), ('c', 'c'), ('file', 'file'),
612
self.do_iter_changes(tree1, tree2))
614
def test_empty_dir(self):
615
"""an empty dir should not cause glitches to surrounding files."""
616
tree1 = self.make_branch_and_tree('1')
617
tree2 = self.make_to_branch_and_tree('2')
618
tree1 = self.get_tree_no_parents_abc_content(tree1)
619
tree2 = self.get_tree_no_parents_abc_content(tree2)
620
# the pathname is chosen to fall between 'a' and 'b'.
621
self.build_tree(['1/a-empty/', '2/a-empty/'])
622
tree1.add(['a-empty'], ['a-empty'])
623
tree2.add(['a-empty'], ['a-empty'])
624
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
626
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
628
def test_file_rename(self):
629
tree1 = self.make_branch_and_tree('1')
630
tree2 = self.make_to_branch_and_tree('2')
631
tree1 = self.get_tree_no_parents_abc_content(tree1)
632
tree2 = self.get_tree_no_parents_abc_content_4(tree2)
633
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
634
root_id = tree1.path2id('')
635
self.assertEqual([('a-id', ('a', 'd'), False, (True, True),
636
(root_id, root_id), ('a', 'd'), ('file', 'file'),
638
self.do_iter_changes(tree1, tree2))
640
def test_file_rename_and_modification(self):
641
tree1 = self.make_branch_and_tree('1')
642
tree2 = self.make_to_branch_and_tree('2')
643
tree1 = self.get_tree_no_parents_abc_content(tree1)
644
tree2 = self.get_tree_no_parents_abc_content_5(tree2)
645
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
646
root_id = tree1.path2id('')
647
self.assertEqual([('a-id', ('a', 'd'), True, (True, True),
648
(root_id, root_id), ('a', 'd'), ('file', 'file'),
650
self.do_iter_changes(tree1, tree2))
652
def test_file_rename_and_meta_modification(self):
653
tree1 = self.make_branch_and_tree('1')
654
tree2 = self.make_to_branch_and_tree('2')
655
tree1 = self.get_tree_no_parents_abc_content(tree1)
656
tree2 = self.get_tree_no_parents_abc_content_6(tree2)
657
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
658
root_id = tree1.path2id('')
659
self.assertEqual([('c-id', ('b/c', 'e'), False, (True, True),
660
('b-id', root_id), ('c', 'e'), ('file', 'file'),
662
self.do_iter_changes(tree1, tree2))
664
def test_missing_in_target(self):
665
"""Test with the target files versioned but absent from disk."""
666
tree1 = self.make_branch_and_tree('1')
667
tree2 = self.make_to_branch_and_tree('2')
668
tree1 = self.get_tree_no_parents_abc_content(tree1)
669
tree2 = self.get_tree_no_parents_abc_content(tree2)
672
# TODO ? have a symlink here?
673
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
674
root_id = tree1.path2id('')
676
self.missing('a-id', 'a', 'a', root_id, 'file'),
677
self.missing('b-id', 'b', 'b', root_id, 'directory'),
678
self.missing('c-id', 'b/c', 'b/c', 'b-id', 'file'),
680
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
682
def test_missing_and_renamed(self):
683
tree1 = self.make_branch_and_tree('tree1')
684
tree2 = self.make_to_branch_and_tree('tree2')
685
tree2.set_root_id(tree1.get_root_id())
686
self.build_tree(['tree1/file'])
687
tree1.add(['file'], ['file-id'])
688
self.build_tree(['tree2/directory/'])
689
tree2.add(['directory'], ['file-id'])
690
os.rmdir('tree2/directory')
691
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
693
root_id = tree1.path2id('')
695
self.missing('file-id', 'file', 'directory', root_id, 'file'),
697
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
699
def test_only_in_source_and_missing(self):
700
tree1 = self.make_branch_and_tree('tree1')
701
tree2 = self.make_to_branch_and_tree('tree2')
702
tree2.set_root_id(tree1.get_root_id())
703
self.build_tree(['tree1/file'])
704
tree1.add(['file'], ['file-id'])
705
os.unlink('tree1/file')
706
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
707
root_id = tree1.path2id('')
708
if not tree1.path2id('file'):
709
# The locked test trees conversion could not preserve the missing
710
# file status. This is normal (e.g. InterDirstateTree falls back
711
# to InterTree if the basis is not a DirstateRevisionTree, and
712
# revision trees cannot have missing files.
713
raise TestNotApplicable()
714
expected = [('file-id', ('file', None), False, (True, False),
715
(root_id, None), ('file', None), (None, None), (False, None))]
716
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
718
def test_only_in_target_and_missing(self):
719
tree1 = self.make_branch_and_tree('tree1')
720
tree2 = self.make_to_branch_and_tree('tree2')
721
tree2.set_root_id(tree1.get_root_id())
722
self.build_tree(['tree2/file'])
723
tree2.add(['file'], ['file-id'])
724
os.unlink('tree2/file')
725
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
726
root_id = tree1.path2id('')
727
expected = [('file-id', (None, 'file'), False, (False, True),
728
(None, root_id), (None, 'file'), (None, None), (None, False))]
729
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
731
def test_unchanged_with_renames_and_modifications(self):
732
"""want_unchanged should generate a list of unchanged entries."""
733
tree1 = self.make_branch_and_tree('1')
734
tree2 = self.make_to_branch_and_tree('2')
735
tree1 = self.get_tree_no_parents_abc_content(tree1)
736
tree2 = self.get_tree_no_parents_abc_content_5(tree2)
737
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
738
root_id = tree1.path2id('')
740
self.assertEqual(sorted([self.unchanged(tree1, root_id),
741
self.unchanged(tree1, 'b-id'),
742
('a-id', ('a', 'd'), True, (True, True),
743
(root_id, root_id), ('a', 'd'), ('file', 'file'),
744
(False, False)), self.unchanged(tree1, 'c-id')]),
745
self.do_iter_changes(tree1, tree2, include_unchanged=True))
747
def test_compare_subtrees(self):
748
tree1 = self.make_branch_and_tree('1')
749
if not tree1.supports_tree_reference():
751
tree1.set_root_id('root-id')
752
subtree1 = self.make_branch_and_tree('1/sub')
753
subtree1.set_root_id('subtree-id')
754
tree1.add_reference(subtree1)
756
tree2 = self.make_to_branch_and_tree('2')
757
if not tree2.supports_tree_reference():
759
tree2.set_root_id('root-id')
760
subtree2 = self.make_to_branch_and_tree('2/sub')
761
subtree2.set_root_id('subtree-id')
762
tree2.add_reference(subtree2)
763
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
765
self.assertEqual([], list(tree2.iter_changes(tree1)))
766
subtree1.commit('commit', rev_id='commit-a')
774
('directory', 'directory'),
780
('root-id', 'root-id'),
782
('tree-reference', 'tree-reference'),
784
list(tree2.iter_changes(tree1,
785
include_unchanged=True)))
787
def test_disk_in_subtrees_skipped(self):
788
"""subtrees are considered not-in-the-current-tree.
790
This test tests the trivial case, where the basis has no paths in the
791
current trees subtree.
793
tree1 = self.make_branch_and_tree('1')
794
tree1.set_root_id('root-id')
795
tree2 = self.make_to_branch_and_tree('2')
796
if not tree2.supports_tree_reference():
798
tree2.set_root_id('root-id')
799
subtree2 = self.make_to_branch_and_tree('2/sub')
800
subtree2.set_root_id('subtree-id')
801
tree2.add(['sub'], ['subtree-id'])
802
self.build_tree(['2/sub/file'])
803
subtree2.add(['file'])
805
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
806
# this should filter correctly from above
807
self.assertEqual([self.added(tree2, 'subtree-id')],
808
self.do_iter_changes(tree1, tree2, want_unversioned=True))
809
# and when the path is named
810
self.assertEqual([self.added(tree2, 'subtree-id')],
811
self.do_iter_changes(tree1, tree2, specific_files=['sub'],
812
want_unversioned=True))
814
def test_default_ignores_unversioned_files(self):
815
tree1 = self.make_branch_and_tree('tree1')
816
tree2 = self.make_to_branch_and_tree('tree2')
817
tree2.set_root_id(tree1.get_root_id())
818
self.build_tree(['tree1/a', 'tree1/c',
819
'tree2/a', 'tree2/b', 'tree2/c'])
820
tree1.add(['a', 'c'], ['a-id', 'c-id'])
821
tree2.add(['a', 'c'], ['a-id', 'c-id'])
823
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
825
# We should ignore the fact that 'b' exists in tree-2
826
# because the want_unversioned parameter was not given.
828
self.content_changed(tree2, 'a-id'),
829
self.content_changed(tree2, 'c-id'),
831
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
833
def test_unversioned_paths_in_tree(self):
834
tree1 = self.make_branch_and_tree('tree1')
835
tree2 = self.make_to_branch_and_tree('tree2')
836
tree2.set_root_id(tree1.get_root_id())
837
self.build_tree(['tree2/file', 'tree2/dir/'])
839
os.symlink('target', 'tree2/link')
840
links_supported = True
842
links_supported = False
843
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
845
self.unversioned(tree2, 'file'),
846
self.unversioned(tree2, 'dir'),
849
expected.append(self.unversioned(tree2, 'link'))
850
expected = sorted(expected)
851
self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
852
want_unversioned=True))
854
def test_unversioned_paths_in_tree_specific_files(self):
855
tree1 = self.make_branch_and_tree('tree1')
856
tree2 = self.make_to_branch_and_tree('tree2')
857
self.build_tree(['tree2/file', 'tree2/dir/'])
859
os.symlink('target', 'tree2/link')
860
links_supported = True
862
links_supported = False
863
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
865
self.unversioned(tree2, 'file'),
866
self.unversioned(tree2, 'dir'),
868
specific_files=['file', 'dir']
870
expected.append(self.unversioned(tree2, 'link'))
871
specific_files.append('link')
872
expected = sorted(expected)
873
self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
874
specific_files=specific_files, require_versioned=False,
875
want_unversioned=True))
877
def test_unversioned_paths_in_target_matching_source_old_names(self):
878
# its likely that naive implementations of unversioned file support
879
# will fail if the path was versioned, but is not any more,
880
# due to a rename, not due to unversioning it.
881
# That is, if the old tree has a versioned file 'foo', and
882
# the new tree has the same file but versioned as 'bar', and also
883
# has an unknown file 'foo', we should get back output for
885
tree1 = self.make_branch_and_tree('tree1')
886
tree2 = self.make_to_branch_and_tree('tree2')
887
tree2.set_root_id(tree1.get_root_id())
888
self.build_tree(['tree2/file', 'tree2/dir/',
889
'tree1/file', 'tree2/movedfile',
890
'tree1/dir/', 'tree2/moveddir/'])
892
os.symlink('target', 'tree1/link')
893
os.symlink('target', 'tree2/link')
894
os.symlink('target', 'tree2/movedlink')
895
links_supported = True
897
links_supported = False
898
tree1.add(['file', 'dir'], ['file-id', 'dir-id'])
899
tree2.add(['movedfile', 'moveddir'], ['file-id', 'dir-id'])
901
tree1.add(['link'], ['link-id'])
902
tree2.add(['movedlink'], ['link-id'])
903
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
904
root_id = tree1.path2id('')
906
self.renamed(tree1, tree2, 'dir-id', False),
907
self.renamed(tree1, tree2, 'file-id', True),
908
self.unversioned(tree2, 'file'),
909
self.unversioned(tree2, 'dir'),
911
specific_files=['file', 'dir']
913
expected.append(self.renamed(tree1, tree2, 'link-id', False))
914
expected.append(self.unversioned(tree2, 'link'))
915
specific_files.append('link')
916
expected = sorted(expected)
917
# run once with, and once without specific files, to catch
918
# potentially different code paths.
919
self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
920
require_versioned=False,
921
want_unversioned=True))
922
self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
923
specific_files=specific_files, require_versioned=False,
924
want_unversioned=True))
926
def test_similar_filenames(self):
927
"""Test when we have a few files with similar names."""
928
tree1 = self.make_branch_and_tree('tree1')
929
tree2 = self.make_branch_and_tree('tree2')
930
tree2.set_root_id(tree1.get_root_id())
932
# The trees are actually identical, but they happen to contain
933
# similarly named files.
934
self.build_tree(['tree1/a/',
947
tree1.add(['a', 'a/b', 'a/b/c', 'a/b/c/d', 'a-c', 'a-c/e'],
948
['a-id', 'b-id', 'c-id', 'd-id', 'a-c-id', 'e-id'])
949
tree2.add(['a', 'a/b', 'a/b/c', 'a/b/c/d', 'a-c', 'a-c/e'],
950
['a-id', 'b-id', 'c-id', 'd-id', 'a-c-id', 'e-id'])
952
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
954
self.assertEqual([], self.do_iter_changes(tree1, tree2,
955
want_unversioned=True))
957
self.unchanged(tree2, tree2.get_root_id()),
958
self.unchanged(tree2, 'a-id'),
959
self.unchanged(tree2, 'b-id'),
960
self.unchanged(tree2, 'c-id'),
961
self.unchanged(tree2, 'd-id'),
962
self.unchanged(tree2, 'a-c-id'),
963
self.unchanged(tree2, 'e-id'),
965
self.assertEqual(expected,
966
self.do_iter_changes(tree1, tree2,
967
want_unversioned=True,
968
include_unchanged=True))
971
def test_unversioned_subtree_only_emits_root(self):
972
tree1 = self.make_branch_and_tree('tree1')
973
tree2 = self.make_to_branch_and_tree('tree2')
974
tree2.set_root_id(tree1.get_root_id())
975
self.build_tree(['tree2/dir/', 'tree2/dir/file'])
976
tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
978
self.unversioned(tree2, 'dir'),
980
self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
981
want_unversioned=True))
983
def make_trees_with_symlinks(self):
984
tree1 = self.make_branch_and_tree('tree1')
985
tree2 = self.make_to_branch_and_tree('tree2')
986
tree2.set_root_id(tree1.get_root_id())
987
self.build_tree(['tree1/fromfile', 'tree1/fromdir/'])
988
self.build_tree(['tree2/tofile', 'tree2/todir/', 'tree2/unknown'])
989
os.symlink('original', 'tree1/changed')
990
os.symlink('original', 'tree1/removed')
991
os.symlink('original', 'tree1/tofile')
992
os.symlink('original', 'tree1/todir')
993
# we make the unchanged link point at unknown to catch incorrect
994
# symlink-following code in the specified_files test.
995
os.symlink('unknown', 'tree1/unchanged')
996
os.symlink('new', 'tree2/added')
997
os.symlink('new', 'tree2/changed')
998
os.symlink('new', 'tree2/fromfile')
999
os.symlink('new', 'tree2/fromdir')
1000
os.symlink('unknown', 'tree2/unchanged')
1001
from_paths_and_ids = [
1010
to_paths_and_ids = [
1019
tree1.add(from_paths_and_ids, from_paths_and_ids)
1020
tree2.add(to_paths_and_ids, to_paths_and_ids)
1021
return self.mutable_trees_to_locked_test_trees(tree1, tree2)
1023
def test_versioned_symlinks(self):
1024
self.requireFeature(tests.SymlinkFeature)
1025
tree1, tree2 = self.make_trees_with_symlinks()
1026
root_id = tree1.path2id('')
1028
self.unchanged(tree1, tree1.path2id('')),
1029
self.added(tree2, 'added'),
1030
self.content_changed(tree2, 'changed'),
1031
self.kind_changed(tree1, tree2, 'fromdir'),
1032
self.kind_changed(tree1, tree2, 'fromfile'),
1033
self.deleted(tree1, 'removed'),
1034
self.unchanged(tree2, 'unchanged'),
1035
self.unversioned(tree2, 'unknown'),
1036
self.kind_changed(tree1, tree2, 'todir'),
1037
self.kind_changed(tree1, tree2, 'tofile'),
1039
expected = sorted(expected)
1040
self.assertEqual(expected,
1041
self.do_iter_changes(tree1, tree2, include_unchanged=True,
1042
want_unversioned=True))
1044
def test_versioned_symlinks_specific_files(self):
1045
self.requireFeature(tests.SymlinkFeature)
1046
tree1, tree2 = self.make_trees_with_symlinks()
1047
root_id = tree1.path2id('')
1049
self.added(tree2, 'added'),
1050
self.content_changed(tree2, 'changed'),
1051
self.kind_changed(tree1, tree2, 'fromdir'),
1052
self.kind_changed(tree1, tree2, 'fromfile'),
1053
self.deleted(tree1, 'removed'),
1054
self.kind_changed(tree1, tree2, 'todir'),
1055
self.kind_changed(tree1, tree2, 'tofile'),
1057
expected = sorted(expected)
1058
# we should get back just the changed links. We pass in 'unchanged' to
1059
# make sure that it is correctly not returned - and neither is the
1060
# unknown path 'unknown' which it points at.
1061
self.assertEqual(expected, self.do_iter_changes(tree1, tree2,
1062
specific_files=['added', 'changed', 'fromdir', 'fromfile',
1063
'removed', 'unchanged', 'todir', 'tofile']))
1065
def test_tree_with_special_names(self):
1066
tree1, tree2, paths, path_ids = self.make_tree_with_special_names()
1067
expected = sorted(self.added(tree2, f_id) for f_id in path_ids)
1068
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1070
def test_trees_with_special_names(self):
1071
tree1, tree2, paths, path_ids = self.make_trees_with_special_names()
1072
expected = sorted(self.content_changed(tree2, f_id) for f_id in path_ids
1073
if f_id.endswith('_f-id'))
1074
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1076
def test_trees_with_deleted_dir(self):
1077
tree1 = self.make_branch_and_tree('tree1')
1078
tree2 = self.make_to_branch_and_tree('tree2')
1079
tree2.set_root_id(tree1.get_root_id())
1080
self.build_tree(['tree1/a', 'tree1/b/', 'tree1/b/c',
1081
'tree1/b/d/', 'tree1/b/d/e', 'tree1/f/', 'tree1/f/g',
1082
'tree2/a', 'tree2/f/', 'tree2/f/g'])
1083
tree1.add(['a', 'b', 'b/c', 'b/d/', 'b/d/e', 'f', 'f/g'],
1084
['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'f-id', 'g-id'])
1085
tree2.add(['a', 'f', 'f/g'], ['a-id', 'f-id', 'g-id'])
1087
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1088
# We should notice that 'b' and all its children are deleted
1090
self.content_changed(tree2, 'a-id'),
1091
self.content_changed(tree2, 'g-id'),
1092
self.deleted(tree1, 'b-id'),
1093
self.deleted(tree1, 'c-id'),
1094
self.deleted(tree1, 'd-id'),
1095
self.deleted(tree1, 'e-id'),
1097
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1099
def test_added_unicode(self):
1100
tree1 = self.make_branch_and_tree('tree1')
1101
tree2 = self.make_to_branch_and_tree('tree2')
1102
root_id = tree1.get_root_id()
1103
tree2.set_root_id(root_id)
1105
# u'\u03b1' == GREEK SMALL LETTER ALPHA
1106
# u'\u03c9' == GREEK SMALL LETTER OMEGA
1107
a_id = u'\u03b1-id'.encode('utf8')
1108
added_id = u'\u03c9_added_id'.encode('utf8')
1110
self.build_tree([u'tree1/\u03b1/',
1112
u'tree2/\u03b1/\u03c9-added',
1114
except UnicodeError:
1115
raise tests.TestSkipped("Could not create Unicode files.")
1116
tree1.add([u'\u03b1'], [a_id])
1117
tree2.add([u'\u03b1', u'\u03b1/\u03c9-added'], [a_id, added_id])
1119
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1121
self.assertEqual([self.added(tree2, added_id)],
1122
self.do_iter_changes(tree1, tree2))
1123
self.assertEqual([self.added(tree2, added_id)],
1124
self.do_iter_changes(tree1, tree2,
1125
specific_files=[u'\u03b1']))
1127
def test_deleted_unicode(self):
1128
tree1 = self.make_branch_and_tree('tree1')
1129
tree2 = self.make_to_branch_and_tree('tree2')
1130
root_id = tree1.get_root_id()
1131
tree2.set_root_id(root_id)
1133
# u'\u03b1' == GREEK SMALL LETTER ALPHA
1134
# u'\u03c9' == GREEK SMALL LETTER OMEGA
1135
a_id = u'\u03b1-id'.encode('utf8')
1136
deleted_id = u'\u03c9_deleted_id'.encode('utf8')
1138
self.build_tree([u'tree1/\u03b1/',
1139
u'tree1/\u03b1/\u03c9-deleted',
1142
except UnicodeError:
1143
raise tests.TestSkipped("Could not create Unicode files.")
1144
tree1.add([u'\u03b1', u'\u03b1/\u03c9-deleted'], [a_id, deleted_id])
1145
tree2.add([u'\u03b1'], [a_id])
1147
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1149
self.assertEqual([self.deleted(tree1, deleted_id)],
1150
self.do_iter_changes(tree1, tree2))
1151
self.assertEqual([self.deleted(tree1, deleted_id)],
1152
self.do_iter_changes(tree1, tree2,
1153
specific_files=[u'\u03b1']))
1155
def test_modified_unicode(self):
1156
tree1 = self.make_branch_and_tree('tree1')
1157
tree2 = self.make_to_branch_and_tree('tree2')
1158
root_id = tree1.get_root_id()
1159
tree2.set_root_id(root_id)
1161
# u'\u03b1' == GREEK SMALL LETTER ALPHA
1162
# u'\u03c9' == GREEK SMALL LETTER OMEGA
1163
a_id = u'\u03b1-id'.encode('utf8')
1164
mod_id = u'\u03c9_mod_id'.encode('utf8')
1166
self.build_tree([u'tree1/\u03b1/',
1167
u'tree1/\u03b1/\u03c9-modified',
1169
u'tree2/\u03b1/\u03c9-modified',
1171
except UnicodeError:
1172
raise tests.TestSkipped("Could not create Unicode files.")
1173
tree1.add([u'\u03b1', u'\u03b1/\u03c9-modified'], [a_id, mod_id])
1174
tree2.add([u'\u03b1', u'\u03b1/\u03c9-modified'], [a_id, mod_id])
1176
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1178
self.assertEqual([self.content_changed(tree1, mod_id)],
1179
self.do_iter_changes(tree1, tree2))
1180
self.assertEqual([self.content_changed(tree1, mod_id)],
1181
self.do_iter_changes(tree1, tree2,
1182
specific_files=[u'\u03b1']))
1184
def test_renamed_unicode(self):
1185
tree1 = self.make_branch_and_tree('tree1')
1186
tree2 = self.make_to_branch_and_tree('tree2')
1187
root_id = tree1.get_root_id()
1188
tree2.set_root_id(root_id)
1190
# u'\u03b1' == GREEK SMALL LETTER ALPHA
1191
# u'\u03c9' == GREEK SMALL LETTER OMEGA
1192
a_id = u'\u03b1-id'.encode('utf8')
1193
rename_id = u'\u03c9_rename_id'.encode('utf8')
1195
self.build_tree([u'tree1/\u03b1/',
1198
except UnicodeError:
1199
raise tests.TestSkipped("Could not create Unicode files.")
1200
self.build_tree_contents([(u'tree1/\u03c9-source', 'contents\n'),
1201
(u'tree2/\u03b1/\u03c9-target', 'contents\n'),
1203
tree1.add([u'\u03b1', u'\u03c9-source'], [a_id, rename_id])
1204
tree2.add([u'\u03b1', u'\u03b1/\u03c9-target'], [a_id, rename_id])
1206
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1208
self.assertEqual([self.renamed(tree1, tree2, rename_id, False)],
1209
self.do_iter_changes(tree1, tree2))
1210
self.assertEqual([self.renamed(tree1, tree2, rename_id, False)],
1211
self.do_iter_changes(tree1, tree2,
1212
specific_files=[u'\u03b1']))
1214
def test_unchanged_unicode(self):
1215
tree1 = self.make_branch_and_tree('tree1')
1216
tree2 = self.make_to_branch_and_tree('tree2')
1217
root_id = tree1.get_root_id()
1218
tree2.set_root_id(root_id)
1219
# u'\u03b1' == GREEK SMALL LETTER ALPHA
1220
# u'\u03c9' == GREEK SMALL LETTER OMEGA
1221
a_id = u'\u03b1-id'.encode('utf8')
1222
subfile_id = u'\u03c9-subfile-id'.encode('utf8')
1223
rootfile_id = u'\u03c9-root-id'.encode('utf8')
1225
self.build_tree([u'tree1/\u03b1/',
1228
except UnicodeError:
1229
raise tests.TestSkipped("Could not create Unicode files.")
1230
self.build_tree_contents([
1231
(u'tree1/\u03b1/\u03c9-subfile', 'sub contents\n'),
1232
(u'tree2/\u03b1/\u03c9-subfile', 'sub contents\n'),
1233
(u'tree1/\u03c9-rootfile', 'root contents\n'),
1234
(u'tree2/\u03c9-rootfile', 'root contents\n'),
1236
tree1.add([u'\u03b1', u'\u03b1/\u03c9-subfile', u'\u03c9-rootfile'],
1237
[a_id, subfile_id, rootfile_id])
1238
tree2.add([u'\u03b1', u'\u03b1/\u03c9-subfile', u'\u03c9-rootfile'],
1239
[a_id, subfile_id, rootfile_id])
1241
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1244
self.unchanged(tree1, root_id),
1245
self.unchanged(tree1, a_id),
1246
self.unchanged(tree1, subfile_id),
1247
self.unchanged(tree1, rootfile_id),
1249
self.assertEqual(expected,
1250
self.do_iter_changes(tree1, tree2,
1251
include_unchanged=True))
1253
# We should also be able to select just a subset
1255
self.unchanged(tree1, a_id),
1256
self.unchanged(tree1, subfile_id),
1258
self.assertEqual(expected,
1259
self.do_iter_changes(tree1, tree2,
1260
specific_files=[u'\u03b1'],
1261
include_unchanged=True))
1263
def test_unknown_unicode(self):
1264
tree1 = self.make_branch_and_tree('tree1')
1265
tree2 = self.make_to_branch_and_tree('tree2')
1266
root_id = tree1.get_root_id()
1267
tree2.set_root_id(root_id)
1268
# u'\u03b1' == GREEK SMALL LETTER ALPHA
1269
# u'\u03c9' == GREEK SMALL LETTER OMEGA
1270
a_id = u'\u03b1-id'.encode('utf8')
1272
self.build_tree([u'tree1/\u03b1/',
1274
u'tree2/\u03b1/unknown_dir/',
1275
u'tree2/\u03b1/unknown_file',
1276
u'tree2/\u03b1/unknown_dir/file',
1277
u'tree2/\u03c9-unknown_root_file',
1279
except UnicodeError:
1280
raise tests.TestSkipped("Could not create Unicode files.")
1281
tree1.add([u'\u03b1'], [a_id])
1282
tree2.add([u'\u03b1'], [a_id])
1284
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1287
self.unversioned(tree2, u'\u03b1/unknown_dir'),
1288
self.unversioned(tree2, u'\u03b1/unknown_file'),
1289
self.unversioned(tree2, u'\u03c9-unknown_root_file'),
1290
# a/unknown_dir/file should not be included because we should not
1291
# recurse into unknown_dir
1292
# self.unversioned(tree2, 'a/unknown_dir/file'),
1294
self.assertEqual(expected,
1295
self.do_iter_changes(tree1, tree2,
1296
require_versioned=False,
1297
want_unversioned=True))
1298
self.assertEqual([], # Without want_unversioned we should get nothing
1299
self.do_iter_changes(tree1, tree2))
1301
# We should also be able to select just a subset
1303
self.unversioned(tree2, u'\u03b1/unknown_dir'),
1304
self.unversioned(tree2, u'\u03b1/unknown_file'),
1306
self.assertEqual(expected,
1307
self.do_iter_changes(tree1, tree2,
1308
specific_files=[u'\u03b1'],
1309
require_versioned=False,
1310
want_unversioned=True))
1311
self.assertEqual([], # Without want_unversioned we should get nothing
1312
self.do_iter_changes(tree1, tree2,
1313
specific_files=[u'\u03b1']))
1315
def test_unknown_empty_dir(self):
1316
tree1 = self.make_branch_and_tree('tree1')
1317
tree2 = self.make_to_branch_and_tree('tree2')
1318
root_id = tree1.get_root_id()
1319
tree2.set_root_id(root_id)
1321
# Start with 2 identical trees
1322
self.build_tree(['tree1/a/', 'tree1/b/',
1323
'tree2/a/', 'tree2/b/'])
1324
self.build_tree_contents([('tree1/b/file', 'contents\n'),
1325
('tree2/b/file', 'contents\n')])
1326
tree1.add(['a', 'b', 'b/file'], ['a-id', 'b-id', 'b-file-id'])
1327
tree2.add(['a', 'b', 'b/file'], ['a-id', 'b-id', 'b-file-id'])
1329
# Now create some unknowns in tree2
1330
# We should find both a/file and a/dir as unknown, but we shouldn't
1331
# recurse into a/dir to find that a/dir/subfile is also unknown.
1332
self.build_tree(['tree2/a/file', 'tree2/a/dir/', 'tree2/a/dir/subfile'])
1334
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1337
self.unversioned(tree2, u'a/file'),
1338
self.unversioned(tree2, u'a/dir'),
1340
self.assertEqual(expected,
1341
self.do_iter_changes(tree1, tree2,
1342
require_versioned=False,
1343
want_unversioned=True))
1345
def test_rename_over_deleted(self):
1346
tree1 = self.make_branch_and_tree('tree1')
1347
tree2 = self.make_to_branch_and_tree('tree2')
1348
root_id = tree1.get_root_id()
1349
tree2.set_root_id(root_id)
1351
# The final changes should be:
1358
self.build_tree_contents([
1359
('tree1/a', 'a contents\n'),
1360
('tree1/b', 'b contents\n'),
1361
('tree1/c', 'c contents\n'),
1362
('tree1/d', 'd contents\n'),
1363
('tree2/a', 'b contents\n'),
1364
('tree2/d', 'c contents\n'),
1366
tree1.add(['a', 'b', 'c', 'd'], ['a-id', 'b-id', 'c-id', 'd-id'])
1367
tree2.add(['a', 'd'], ['b-id', 'c-id'])
1369
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1372
self.deleted(tree1, 'a-id'),
1373
self.deleted(tree1, 'd-id'),
1374
self.renamed(tree1, tree2, 'b-id', False),
1375
self.renamed(tree1, tree2, 'c-id', False),
1377
self.assertEqual(expected,
1378
self.do_iter_changes(tree1, tree2))
1380
def test_deleted_and_unknown(self):
1381
"""Test a file marked removed, but still present on disk."""
1382
tree1 = self.make_branch_and_tree('tree1')
1383
tree2 = self.make_to_branch_and_tree('tree2')
1384
root_id = tree1.get_root_id()
1385
tree2.set_root_id(root_id)
1387
# The final changes should be:
1390
self.build_tree_contents([
1391
('tree1/a', 'a contents\n'),
1392
('tree1/b', 'b contents\n'),
1393
('tree1/c', 'c contents\n'),
1394
('tree2/a', 'a contents\n'),
1395
('tree2/b', 'b contents\n'),
1396
('tree2/c', 'c contents\n'),
1398
tree1.add(['a', 'b', 'c'], ['a-id', 'b-id', 'c-id'])
1399
tree2.add(['a', 'c'], ['a-id', 'c-id'])
1401
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1404
self.deleted(tree1, 'b-id'),
1405
self.unversioned(tree2, 'b'),
1407
self.assertEqual(expected,
1408
self.do_iter_changes(tree1, tree2,
1409
want_unversioned=True))
1411
self.deleted(tree1, 'b-id'),
1413
self.assertEqual(expected,
1414
self.do_iter_changes(tree1, tree2,
1415
want_unversioned=False))
1417
def test_renamed_and_added(self):
1418
"""Test when we have renamed a file, and put another in its place."""
1419
tree1 = self.make_branch_and_tree('tree1')
1420
tree2 = self.make_to_branch_and_tree('tree2')
1421
root_id = tree1.get_root_id()
1422
tree2.set_root_id(root_id)
1424
# The final changes are:
1430
self.build_tree_contents([
1431
('tree1/b', 'b contents\n'),
1432
('tree1/c', 'c contents\n'),
1433
('tree2/a', 'b contents\n'),
1434
('tree2/b', 'new b contents\n'),
1435
('tree2/c', 'new c contents\n'),
1436
('tree2/d', 'c contents\n'),
1438
tree1.add(['b', 'c'], ['b1-id', 'c1-id'])
1439
tree2.add(['a', 'b', 'c', 'd'], ['b1-id', 'b2-id', 'c2-id', 'c1-id'])
1441
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1444
self.renamed(tree1, tree2, 'b1-id', False),
1445
self.renamed(tree1, tree2, 'c1-id', False),
1446
self.added(tree2, 'b2-id'),
1447
self.added(tree2, 'c2-id'),
1449
self.assertEqual(expected,
1450
self.do_iter_changes(tree1, tree2,
1451
want_unversioned=True))
1453
def test_renamed_and_unknown(self):
1454
"""A file was moved on the filesystem, but not in bzr."""
1455
tree1 = self.make_branch_and_tree('tree1')
1456
tree2 = self.make_to_branch_and_tree('tree2')
1457
root_id = tree1.get_root_id()
1458
tree2.set_root_id(root_id)
1460
# The final changes are:
1464
self.build_tree_contents([
1465
('tree1/a', 'a contents\n'),
1466
('tree1/b', 'b contents\n'),
1467
('tree2/a', 'a contents\n'),
1468
('tree2/b', 'b contents\n'),
1470
tree1.add(['a', 'b'], ['a-id', 'b-id'])
1471
tree2.add(['a', 'b'], ['a-id', 'b-id'])
1472
os.rename('tree2/a', 'tree2/a2')
1474
tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1477
self.missing('a-id', 'a', 'a', tree2.get_root_id(), 'file'),
1478
self.unversioned(tree2, 'a2'),
1480
self.assertEqual(expected,
1481
self.do_iter_changes(tree1, tree2,
1482
want_unversioned=True))