1
1
# Copyright (C) 2004-2006 by Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
from cStringIO import StringIO
22
from bzrlib import inventory
19
23
from bzrlib.builtins import merge
20
24
from bzrlib.bzrdir import BzrDir
21
25
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
22
26
from bzrlib.bundle.bundle_data import BundleTree
23
27
from bzrlib.bundle.serializer import write_bundle, read_bundle
28
from bzrlib.branch import Branch
24
29
from bzrlib.diff import internal_diff
25
from bzrlib.errors import BzrError, TestamentMismatch, NotABundle, BadBundle
30
from bzrlib.errors import (BzrError, TestamentMismatch, NotABundle, BadBundle,
26
32
from bzrlib.merge import Merge3Merger
27
33
from bzrlib.osutils import has_symlinks, sha_file
28
34
from bzrlib.tests import (TestCaseInTempDir, TestCaseWithTransport,
287
291
def test_iteration(self):
288
292
"""Ensure that iteration through ids works properly"""
289
293
btree = self.make_tree_1()[0]
290
self.assertEqual(self.sorted_ids(btree), ['a', 'b', 'c', 'd'])
294
self.assertEqual(self.sorted_ids(btree),
295
[inventory.ROOT_ID, 'a', 'b', 'c', 'd'])
291
296
btree.note_deletion("grandparent/parent/file")
292
297
btree.note_id("e", "grandparent/alt_parent/fool", kind="directory")
293
298
btree.note_last_changed("grandparent/alt_parent/fool",
294
299
"revisionidiguess")
295
self.assertEqual(self.sorted_ids(btree), ['a', 'b', 'd', 'e'])
298
class BundleTester(TestCaseInTempDir):
300
self.assertEqual(self.sorted_ids(btree),
301
[inventory.ROOT_ID, 'a', 'b', 'd', 'e'])
304
class BundleTester(TestCaseWithTransport):
300
306
def create_bundle_text(self, base_rev_id, rev_id):
301
307
bundle_txt = StringIO()
546
557
open('b1/sub/dir/WithCaps.txt', 'ab').write('\nAdding some text\n')
547
open('b1/sub/dir/trailing space ', 'ab').write('\nAdding some\nDOS format lines\n')
558
open('b1/sub/dir/ pre space', 'ab').write('\r\nAdding some\r\nDOS format lines\r\n')
548
559
open('b1/sub/dir/nolastnewline.txt', 'ab').write('\n')
549
self.tree1.rename_one('sub/dir/trailing space ',
550
'sub/ start and end space ')
560
self.tree1.rename_one('sub/dir/ pre space',
551
562
self.tree1.commit('Modified files', rev_id='a@cset-0-5')
552
563
bundle = self.get_valid_bundle('a@cset-0-4', 'a@cset-0-5')
554
# Handle international characters
556
f = open(u'b1/with Dod\xe9', 'wb')
557
except UnicodeEncodeError:
558
raise TestSkipped("Filesystem doesn't support unicode")
560
u'With international man of mystery\n'
561
u'William Dod\xe9\n').encode('utf-8'))
562
self.tree1.add([u'with Dod\xe9'])
563
# BUG: (sort of) You must set verbose=False, so that python doesn't try
564
# and print the name of William Dode as part of the commit
565
self.tree1.commit(u'i18n commit from William Dod\xe9',
566
rev_id='a@cset-0-6', committer=u'William Dod\xe9',
568
bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
569
565
self.tree1.rename_one('sub/dir/WithCaps.txt', 'temp')
570
566
self.tree1.rename_one('with space.txt', 'WithCaps.txt')
571
567
self.tree1.rename_one('temp', 'with space.txt')
572
self.tree1.commit(u'swap filenames', rev_id='a@cset-0-7',
568
self.tree1.commit(u'swap filenames', rev_id='a@cset-0-6',
570
bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
571
other = self.get_checkout('a@cset-0-5')
572
other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
573
other.commit('rename file', rev_id='a@cset-0-6b')
574
merge([other.basedir, -1], [None, None], this_dir=self.tree1.basedir)
575
self.tree1.commit(u'Merge', rev_id='a@cset-0-7',
574
577
bundle = self.get_valid_bundle('a@cset-0-6', 'a@cset-0-7')
575
other = self.get_checkout('a@cset-0-6')
576
other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
577
other.commit('rename file', rev_id='a@cset-0-7b')
578
merge([other.basedir, -1], [None, None], this_dir=self.tree1.basedir)
579
self.tree1.commit(u'Merge', rev_id='a@cset-0-8',
581
bundle = self.get_valid_bundle('a@cset-0-7', 'a@cset-0-8')
583
579
def test_symlink_bundle(self):
584
580
if not has_symlinks():
616
612
self.tree1 = BzrDir.create_standalone_workingtree('b1')
617
613
self.b1 = self.tree1.branch
618
614
tt = TreeTransform(self.tree1)
619
tt.new_file('file', tt.root, '\x00\xff', 'binary-1')
620
tt.new_file('file2', tt.root, '\x00\xff', 'binary-2')
617
tt.new_file('file', tt.root, '\x00\n\x00\r\x01\n\x02\r\xff', 'binary-1')
618
tt.new_file('file2', tt.root, '\x01\n\x02\r\x03\n\x04\r\xff', 'binary-2')
622
620
self.tree1.commit('add binary', rev_id='b@cset-0-1')
623
621
self.get_valid_bundle(None, 'b@cset-0-1')
624
624
tt = TreeTransform(self.tree1)
625
625
trans_id = tt.trans_id_tree_file_id('binary-1')
626
626
tt.delete_contents(trans_id)
628
628
self.tree1.commit('delete binary', rev_id='b@cset-0-2')
629
629
self.get_valid_bundle('b@cset-0-1', 'b@cset-0-2')
630
632
tt = TreeTransform(self.tree1)
631
633
trans_id = tt.trans_id_tree_file_id('binary-2')
632
634
tt.adjust_path('file3', tt.root, trans_id)
633
635
tt.delete_contents(trans_id)
634
tt.create_file('filecontents\x00', trans_id)
636
tt.create_file('file\rcontents\x00\n\x00', trans_id)
636
638
self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
637
639
self.get_valid_bundle('b@cset-0-2', 'b@cset-0-3')
638
642
tt = TreeTransform(self.tree1)
639
643
trans_id = tt.trans_id_tree_file_id('binary-2')
640
644
tt.delete_contents(trans_id)
641
tt.create_file('\x00filecontents', trans_id)
645
tt.create_file('\x00file\rcontents', trans_id)
643
647
self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
644
648
self.get_valid_bundle('b@cset-0-3', 'b@cset-0-4')
651
self.get_valid_bundle(None, 'b@cset-0-4')
646
653
def test_last_modified(self):
647
654
self.tree1 = BzrDir.create_standalone_workingtree('b1')
648
655
self.b1 = self.tree1.branch
689
696
self.assertContainsRe(bundle_file.getvalue(), 'one')
690
697
self.assertContainsRe(bundle_file.getvalue(), 'three')
699
def test_unicode_bundle(self):
700
# Handle international characters
703
f = open(u'b1/with Dod\xe9', 'wb')
704
except UnicodeEncodeError:
705
raise TestSkipped("Filesystem doesn't support unicode")
707
self.tree1 = self.make_branch_and_tree('b1')
708
self.b1 = self.tree1.branch
711
u'With international man of mystery\n'
712
u'William Dod\xe9\n').encode('utf-8'))
715
self.tree1.add([u'with Dod\xe9'])
716
self.tree1.commit(u'i18n commit from William Dod\xe9',
717
rev_id='i18n-1', committer=u'William Dod\xe9')
720
bundle = self.get_valid_bundle(None, 'i18n-1')
723
f = open(u'b1/with Dod\xe9', 'wb')
724
f.write(u'Modified \xb5\n'.encode('utf8'))
726
self.tree1.commit(u'modified', rev_id='i18n-2')
728
bundle = self.get_valid_bundle('i18n-1', 'i18n-2')
731
self.tree1.rename_one(u'with Dod\xe9', u'B\xe5gfors')
732
self.tree1.commit(u'renamed, the new i18n man', rev_id='i18n-3',
733
committer=u'Erik B\xe5gfors')
735
bundle = self.get_valid_bundle('i18n-2', 'i18n-3')
738
self.tree1.remove([u'B\xe5gfors'])
739
self.tree1.commit(u'removed', rev_id='i18n-4')
741
bundle = self.get_valid_bundle('i18n-3', 'i18n-4')
744
bundle = self.get_valid_bundle(None, 'i18n-4')
747
def test_whitespace_bundle(self):
748
if sys.platform in ('win32', 'cygwin'):
749
raise TestSkipped('Windows doesn\'t support filenames'
750
' with tabs or trailing spaces')
751
self.tree1 = self.make_branch_and_tree('b1')
752
self.b1 = self.tree1.branch
754
self.build_tree(['b1/trailing space '])
755
self.tree1.add(['trailing space '])
756
# TODO: jam 20060701 Check for handling files with '\t' characters
757
# once we actually support them
760
self.tree1.commit('funky whitespace', rev_id='white-1')
762
bundle = self.get_valid_bundle(None, 'white-1')
765
open('b1/trailing space ', 'ab').write('add some text\n')
766
self.tree1.commit('add text', rev_id='white-2')
768
bundle = self.get_valid_bundle('white-1', 'white-2')
771
self.tree1.rename_one('trailing space ', ' start and end space ')
772
self.tree1.commit('rename', rev_id='white-3')
774
bundle = self.get_valid_bundle('white-2', 'white-3')
777
self.tree1.remove([' start and end space '])
778
self.tree1.commit('removed', rev_id='white-4')
780
bundle = self.get_valid_bundle('white-3', 'white-4')
782
# Now test a complet roll-up
783
bundle = self.get_valid_bundle(None, 'white-4')
785
def test_alt_timezone_bundle(self):
786
self.tree1 = self.make_branch_and_tree('b1')
787
self.b1 = self.tree1.branch
789
self.build_tree(['b1/newfile'])
790
self.tree1.add(['newfile'])
792
# Asia/Colombo offset = 5 hours 30 minutes
793
self.tree1.commit('non-hour offset timezone', rev_id='tz-1',
794
timezone=19800, timestamp=1152544886.0)
796
bundle = self.get_valid_bundle(None, 'tz-1')
798
rev = bundle.revisions[0]
799
self.assertEqual('Mon 2006-07-10 20:51:26.000000000 +0530', rev.date)
800
self.assertEqual(19800, rev.timezone)
801
self.assertEqual(1152544886.0, rev.timestamp)
803
def test_bundle_root_id(self):
804
self.tree1 = self.make_branch_and_tree('b1')
805
self.b1 = self.tree1.branch
806
self.tree1.commit('message', rev_id='revid1')
807
bundle = self.get_valid_bundle(None, 'revid1')
808
tree = bundle.revision_tree(self.b1.repository, 'revid1')
809
self.assertEqual('revid1', tree.inventory.root.revision)
693
812
class MungedBundleTester(TestCaseWithTransport):
750
870
# creates a blank line at the end, and fails if that
751
871
# line is stripped
752
872
self.assertEqual('\n\n', raw[-2:])
753
bundle_text = StringIO(raw[:-1])
755
bundle = read_bundle(bundle_txt)
756
self.check_valid(bundle)
873
bundle_txt = StringIO(raw[:-1])
875
bundle = read_bundle(bundle_txt)
876
self.check_valid(bundle)
878
def test_opening_text(self):
879
bundle_txt = self.build_test_bundle()
881
bundle_txt = StringIO("Some random\nemail comments\n"
882
+ bundle_txt.getvalue())
884
bundle = read_bundle(bundle_txt)
885
self.check_valid(bundle)
887
def test_trailing_text(self):
888
bundle_txt = self.build_test_bundle()
890
bundle_txt = StringIO(bundle_txt.getvalue() +
891
"Some trailing\nrandom\ntext\n")
893
bundle = read_bundle(bundle_txt)
894
self.check_valid(bundle)