1
# Copyright (C) 2005, 2006 by Canonical Ltd
1
# Copyright (C) 2005 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
21
from bzrlib import errors, inventory, osutils
22
20
from bzrlib.branch import Branch
21
import bzrlib.errors as errors
23
22
from bzrlib.diff import internal_diff
24
23
from bzrlib.inventory import (Inventory, ROOT_ID, InventoryFile,
25
24
InventoryDirectory, InventoryEntry)
26
from bzrlib.osutils import (has_symlinks, rename, pathjoin, is_inside_any,
27
is_inside_or_parent_of_any)
25
import bzrlib.inventory as inventory
26
from bzrlib.osutils import has_symlinks, rename, pathjoin
28
27
from bzrlib.tests import TestCase, TestCaseWithTransport
29
28
from bzrlib.transform import TreeTransform
30
29
from bzrlib.uncommit import uncommit
44
44
for dirs, fn in [(['src'], 'srccontrol'),
45
45
(['src'], 'srccontrol/foo')]:
46
46
self.assertFalse(is_inside_any(dirs, fn))
48
def test_is_within_or_parent(self):
49
for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
50
(['src'], 'src/foo.c'),
51
(['src/bar.c'], 'src'),
52
(['src/bar.c', 'bla/foo.c'], 'src'),
55
self.assert_(is_inside_or_parent_of_any(dirs, fn))
57
for dirs, fn in [(['src'], 'srccontrol'),
58
(['srccontrol/foo.c'], 'src'),
59
(['src'], 'srccontrol/foo')]:
60
self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
62
48
def test_ids(self):
63
49
"""Test detection of files within selected directories."""
94
79
('src/hello.c', 'hello-id'),
95
80
], [(path, ie.file_id) for path, ie in inv.iter_entries()])
97
def test_iter_entries_by_dir(self):
100
for args in [('src', 'directory', 'src-id'),
101
('doc', 'directory', 'doc-id'),
102
('src/hello.c', 'file', 'hello-id'),
103
('src/bye.c', 'file', 'bye-id'),
104
('zz', 'file', 'zz-id'),
105
('src/sub/', 'directory', 'sub-id'),
106
('src/zz.c', 'file', 'zzc-id'),
107
('src/sub/a', 'file', 'a-id'),
108
('Makefile', 'file', 'makefile-id')]:
113
('Makefile', 'makefile-id'),
117
('src/bye.c', 'bye-id'),
118
('src/hello.c', 'hello-id'),
119
('src/sub', 'sub-id'),
120
('src/zz.c', 'zzc-id'),
121
('src/sub/a', 'a-id'),
122
], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir()])
124
82
def test_version(self):
125
83
"""Inventory remembers the text's version."""
201
159
self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
202
160
inventory.InventoryDirectory)
204
def test_make_entry_non_normalized(self):
205
orig_normalized_filename = osutils.normalized_filename
208
osutils.normalized_filename = osutils._accessible_normalized_filename
209
entry = inventory.make_entry("file", u'a\u030a', ROOT_ID)
210
self.assertEqual(u'\xe5', entry.name)
211
self.assertIsInstance(entry, inventory.InventoryFile)
213
osutils.normalized_filename = osutils._inaccessible_normalized_filename
214
self.assertRaises(errors.InvalidNormalization,
215
inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
217
osutils.normalized_filename = orig_normalized_filename
220
162
class TestEntryDiffing(TestCaseWithTransport):
349
291
self.inv_1 = self.branch.repository.get_inventory('1')
350
292
self.file_1 = self.inv_1['fileid']
351
293
self.file_active = self.wt.inventory['fileid']
352
self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
354
295
def test_snapshot_new_revision(self):
355
296
# This tests that a simple commit with no parents makes a new
356
297
# revision value in the inventory entry
357
self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
298
self.file_active.snapshot('2', 'subdir/file', {}, self.wt,
299
self.branch.repository.weave_store,
300
self.branch.get_transaction())
358
301
# expected outcome - file_1 has a revision id of '2', and we can get
359
302
# its text of 'file contents' out of the weave.
360
303
self.assertEqual(self.file_1.revision, '1')
533
482
self.assertEqual(expected_change, change)
485
class TestExecutable(TestCaseWithTransport):
487
def test_stays_executable(self):
488
a_id = "a-20051208024829-849e76f7968d7a86"
489
b_id = "b-20051208024829-849e76f7968d7a86"
490
wt = self.make_branch_and_tree('b1')
492
tt = TreeTransform(wt)
493
tt.new_file('a', tt.root, 'a test\n', a_id, True)
494
tt.new_file('b', tt.root, 'b test\n', b_id, False)
497
self.failUnless(wt.is_executable(a_id), "'a' lost the execute bit")
499
# reopen the tree and ensure it stuck.
500
wt = wt.bzrdir.open_workingtree()
501
self.assertEqual(['a', 'b'], [cn for cn,ie in wt.inventory.iter_entries()])
503
self.failUnless(wt.is_executable(a_id), "'a' lost the execute bit")
504
self.failIf(wt.is_executable(b_id), "'b' gained an execute bit")
506
wt.commit('adding a,b', rev_id='r1')
508
rev_tree = b.repository.revision_tree('r1')
509
self.failUnless(rev_tree.is_executable(a_id), "'a' lost the execute bit")
510
self.failIf(rev_tree.is_executable(b_id), "'b' gained an execute bit")
512
self.failUnless(rev_tree.inventory[a_id].executable)
513
self.failIf(rev_tree.inventory[b_id].executable)
515
# Make sure the entries are gone
518
self.failIf(wt.has_id(a_id))
519
self.failIf(wt.has_filename('a'))
520
self.failIf(wt.has_id(b_id))
521
self.failIf(wt.has_filename('b'))
523
# Make sure that revert is able to bring them back,
524
# and sets 'a' back to being executable
526
wt.revert(['a', 'b'], rev_tree, backups=False)
527
self.assertEqual(['a', 'b'], [cn for cn,ie in wt.inventory.iter_entries()])
529
self.failUnless(wt.is_executable(a_id), "'a' lost the execute bit")
530
self.failIf(wt.is_executable(b_id), "'b' gained an execute bit")
532
# Now remove them again, and make sure that after a
533
# commit, they are still marked correctly
536
wt.commit('removed', rev_id='r2')
538
self.assertEqual([], [cn for cn,ie in wt.inventory.iter_entries()])
539
self.failIf(wt.has_id(a_id))
540
self.failIf(wt.has_filename('a'))
541
self.failIf(wt.has_id(b_id))
542
self.failIf(wt.has_filename('b'))
544
# Now revert back to the previous commit
545
wt.revert([], rev_tree, backups=False)
546
self.assertEqual(['a', 'b'], [cn for cn,ie in wt.inventory.iter_entries()])
548
self.failUnless(wt.is_executable(a_id), "'a' lost the execute bit")
549
self.failIf(wt.is_executable(b_id), "'b' gained an execute bit")
551
# Now make sure that 'bzr branch' also preserves the
553
# TODO: Maybe this should be a blackbox test
554
d2 = b.bzrdir.clone('b2', revision_id='r1')
555
t2 = d2.open_workingtree()
557
self.assertEquals('r1', b2.last_revision())
559
self.assertEqual(['a', 'b'], [cn for cn,ie in t2.inventory.iter_entries()])
560
self.failUnless(t2.is_executable(a_id), "'a' lost the execute bit")
561
self.failIf(t2.is_executable(b_id), "'b' gained an execute bit")
563
# Make sure pull will delete the files
565
self.assertEquals('r2', b2.last_revision())
566
self.assertEqual([], [cn for cn,ie in t2.inventory.iter_entries()])
568
# Now commit the changes on the first branch
569
# so that the second branch can pull the changes
570
# and make sure that the executable bit has been copied
571
wt.commit('resurrected', rev_id='r3')
574
self.assertEquals('r3', b2.last_revision())
575
self.assertEqual(['a', 'b'], [cn for cn,ie in t2.inventory.iter_entries()])
577
self.failUnless(t2.is_executable(a_id), "'a' lost the execute bit")
578
self.failIf(t2.is_executable(b_id), "'b' gained an execute bit")
536
581
class TestRevert(TestCaseWithTransport):
538
583
def test_dangling_id(self):