/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2255.2.62 by John Arbash Meinel
add a workingtree_implementations test that makes sure smart_add_tree orks properly
1
# Copyright (C) 2007 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
17
"""Test that we can use smart_add on all Tree implementations."""
18
2568.2.4 by Robert Collins
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
19
from cStringIO import StringIO
20
2255.2.62 by John Arbash Meinel
add a workingtree_implementations test that makes sure smart_add_tree orks properly
21
from bzrlib import (
22
    add,
23
    errors,
2568.2.4 by Robert Collins
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
24
    ignores,
25
    osutils,
2568.2.10 by Robert Collins
And a missing import.
26
    tests,
2255.2.62 by John Arbash Meinel
add a workingtree_implementations test that makes sure smart_add_tree orks properly
27
    workingtree,
28
    )
2255.7.92 by Martin Pool
Test for smart_add(save=false) should be run against all WorkingTrees; adjust the test to more precisely cover the contract.
29
from bzrlib.add import (
30
    AddAction,
31
    AddFromBaseAction,
32
    )
2568.2.4 by Robert Collins
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
33
from bzrlib.tests.test_smart_add import AddCustomIDAction
2255.2.62 by John Arbash Meinel
add a workingtree_implementations test that makes sure smart_add_tree orks properly
34
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
35
36
37
class TestSmartAddTree(TestCaseWithWorkingTree):
38
39
    def test_single_file(self):
40
        tree = self.make_branch_and_tree('tree')
41
        self.build_tree(['tree/a'])
2568.2.4 by Robert Collins
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
42
        tree.smart_add(['tree'])
2255.2.62 by John Arbash Meinel
add a workingtree_implementations test that makes sure smart_add_tree orks properly
43
44
        tree.lock_read()
45
        try:
46
            files = [(path, status, kind)
47
                     for path, status, kind, file_id, parent_id
48
                      in tree.list_files(include_root=True)]
49
        finally:
50
            tree.unlock()
51
        self.assertEqual([('', 'V', 'directory'), ('a', 'V', 'file')],
52
                         files)
2255.7.92 by Martin Pool
Test for smart_add(save=false) should be run against all WorkingTrees; adjust the test to more precisely cover the contract.
53
54
    def test_save_false(self):
55
        """Dry-run add doesn't permanently affect the tree."""
56
        wt = self.make_branch_and_tree('.')
2585.1.1 by Aaron Bentley
Unify MutableTree.smart_add behavior by disabling quirky memory-only Inventory
57
        wt.lock_write()
58
        try:
59
            self.build_tree(['file'])
60
            wt.smart_add(['file'], save=False)
61
            # the file should not be added - no id.
62
            self.assertEqual(wt.path2id('file'), None)
63
        finally:
64
            wt.unlock()
2568.2.4 by Robert Collins
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
65
        # and the disk state should be the same - reopen to check.
2255.7.92 by Martin Pool
Test for smart_add(save=false) should be run against all WorkingTrees; adjust the test to more precisely cover the contract.
66
        wt = wt.bzrdir.open_workingtree()
67
        self.assertEqual(wt.path2id('file'), None)
2568.2.4 by Robert Collins
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
68
69
    def test_add_dot_from_root(self):
70
        """Test adding . from the root of the tree.""" 
71
        paths = ("original/", "original/file1", "original/file2")
72
        self.build_tree(paths)
73
        wt = self.make_branch_and_tree('.')
74
        wt.smart_add((u".",))
75
        for path in paths:
76
            self.assertNotEqual(wt.path2id(path), None)
77
78
    def test_add_dot_from_subdir(self):
79
        """Test adding . from a subdir of the tree.""" 
80
        paths = ("original/", "original/file1", "original/file2")
81
        self.build_tree(paths)
82
        wt = self.make_branch_and_tree('.')
83
        wt.smart_add((u".",))
84
        for path in paths:
85
            self.assertNotEqual(wt.path2id(path), None)
86
87
    def test_add_tree_from_above_tree(self):
88
        """Test adding a tree from above the tree.""" 
89
        paths = ("original/", "original/file1", "original/file2")
90
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
91
                        "branch/original/file2")
92
        self.build_tree(branch_paths)
93
        wt = self.make_branch_and_tree('branch')
94
        wt.smart_add(("branch",))
95
        for path in paths:
96
            self.assertNotEqual(wt.path2id(path), None)
97
98
    def test_add_above_tree_preserves_tree(self):
99
        """Test nested trees are not affect by an add above them."""
100
        paths = ("original/", "original/file1", "original/file2")
101
        child_paths = ("path",)
102
        full_child_paths = ("original/child", "original/child/path")
103
        build_paths = ("original/", "original/file1", "original/file2", 
104
                       "original/child/", "original/child/path")
105
        
106
        self.build_tree(build_paths)
107
        wt = self.make_branch_and_tree('.')
108
        child_tree = self.make_branch_and_tree('original/child')
109
        wt.smart_add((".",))
110
        for path in paths:
111
            self.assertNotEqual((path, wt.path2id(path)),
112
                                (path, None))
113
        for path in full_child_paths:
114
            self.assertEqual((path, wt.path2id(path)),
115
                             (path, None))
116
        for path in child_paths:
117
            self.assertEqual(child_tree.path2id(path), None)
118
119
    def test_add_paths(self):
120
        """Test smart-adding a list of paths."""
121
        paths = ("file1", "file2")
122
        self.build_tree(paths)
123
        wt = self.make_branch_and_tree('.')
124
        wt.smart_add(paths)
125
        for path in paths:
126
            self.assertNotEqual(wt.path2id(path), None)
127
    
128
    def test_add_ignored_nested_paths(self):
129
        """Test smart-adding a list of paths which includes ignored ones."""
130
        wt = self.make_branch_and_tree('.')
131
        tree_shape = ("adir/", "adir/CVS/", "adir/CVS/afile", "adir/CVS/afile2")
132
        add_paths = ("adir/CVS", "adir/CVS/afile", "adir")
133
        expected_paths = ("adir", "adir/CVS", "adir/CVS/afile", "adir/CVS/afile2")
134
        self.build_tree(tree_shape)
135
        wt.smart_add(add_paths)
136
        for path in expected_paths:
137
            self.assertNotEqual(wt.path2id(path), None, "No id added for %s" % path)
138
139
    def test_add_non_existant(self):
140
        """Test smart-adding a file that does not exist."""
141
        wt = self.make_branch_and_tree('.')
142
        self.assertRaises(errors.NoSuchFile, wt.smart_add, ['non-existant-file'])
143
144
    def test_returns_and_ignores(self):
145
        """Correctly returns added/ignored files"""
146
        wt = self.make_branch_and_tree('.')
147
        # The default ignore list includes '*.py[co]', but not CVS
148
        ignores._set_user_ignores(['*.py[co]'])
149
        self.build_tree(['inertiatic/', 'inertiatic/esp', 'inertiatic/CVS',
150
                        'inertiatic/foo.pyc'])
151
        added, ignored = wt.smart_add(u'.')
152
        self.assertSubset(('inertiatic', 'inertiatic/esp', 'inertiatic/CVS'),
153
                          added)
154
        self.assertSubset(('*.py[co]',), ignored)
155
        self.assertSubset(('inertiatic/foo.pyc',), ignored['*.py[co]'])
156
157
    def test_add_multiple_dirs(self):
158
        """Test smart adding multiple directories at once."""
159
        added_paths = ['file1', 'file2',
160
                       'dir1/', 'dir1/file3',
161
                       'dir1/subdir2/', 'dir1/subdir2/file4',
162
                       'dir2/', 'dir2/file5',
163
                      ]
164
        not_added = ['file6', 'dir3/', 'dir3/file7', 'dir3/file8']
165
        self.build_tree(added_paths)
166
        self.build_tree(not_added)
167
168
        wt = self.make_branch_and_tree('.')
169
        wt.smart_add(['file1', 'file2', 'dir1', 'dir2'])
170
171
        for path in added_paths:
172
            self.assertNotEqual(None, wt.path2id(path.rstrip('/')),
173
                    'Failed to add path: %s' % (path,))
174
        for path in not_added:
175
            self.assertEqual(None, wt.path2id(path.rstrip('/')),
176
                    'Accidentally added path: %s' % (path,))
177
178
    def test_custom_ids(self):
179
        sio = StringIO()
180
        action = AddCustomIDAction(to_file=sio, should_print=True)
181
        self.build_tree(['file1', 'dir1/', 'dir1/file2'])
182
183
        wt = self.make_branch_and_tree('.')
184
        wt.smart_add(['.'], action=action)
185
        # The order of adds is not strictly fixed:
186
        sio.seek(0)
187
        lines = sorted(sio.readlines())
188
        self.assertEqualDiff(['added dir1 with id directory-dir1\n',
189
                              'added dir1/file2 with id file-dir1%file2\n',
190
                              'added file1 with id file-file1\n',
191
                             ], lines)
192
        wt.lock_read()
193
        self.addCleanup(wt.unlock)
194
        self.assertEqual([('', wt.path2id('')),
195
                          ('dir1', 'directory-dir1'),
196
                          ('dir1/file2', 'file-dir1%file2'),
197
                          ('file1', 'file-file1'),
198
                         ], [(path, ie.file_id) for path, ie
199
                                in wt.inventory.iter_entries()])
200
201
    def make_unicode_containing_tree(self):
202
        try:
203
            self.build_tree([u'a\u030a'])
204
        except UnicodeError:
2568.2.10 by Robert Collins
And a missing import.
205
            raise tests.TestSkipped('Filesystem cannot create unicode filenames')
2568.2.4 by Robert Collins
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
206
        self.wt = self.make_branch_and_tree('.')
207
208
    def test_accessible_explicit(self):
209
        self.make_unicode_containing_tree()
210
        orig = osutils.normalized_filename
211
        osutils.normalized_filename = osutils._accessible_normalized_filename
212
        try:
213
            self.wt.smart_add([u'a\u030a'])
214
            self.wt.lock_read()
215
            self.addCleanup(self.wt.unlock)
216
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
217
                    [(path, ie.kind) for path,ie in 
218
                        self.wt.inventory.iter_entries()])
219
        finally:
220
            osutils.normalized_filename = orig
221
222
    def test_accessible_implicit(self):
223
        self.make_unicode_containing_tree()
224
        orig = osutils.normalized_filename
225
        osutils.normalized_filename = osutils._accessible_normalized_filename
226
        try:
227
            self.wt.smart_add([])
228
            self.wt.lock_read()
229
            self.addCleanup(self.wt.unlock)
230
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
231
                    [(path, ie.kind) for path,ie in 
232
                        self.wt.inventory.iter_entries()])
233
        finally:
234
            osutils.normalized_filename = orig
235
236
    def test_inaccessible_explicit(self):
237
        self.make_unicode_containing_tree()
238
        orig = osutils.normalized_filename
239
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
240
        try:
241
            self.assertRaises(errors.InvalidNormalization,
242
                    self.wt.smart_add, [u'a\u030a'])
243
        finally:
244
            osutils.normalized_filename = orig
245
246
    def test_inaccessible_implicit(self):
247
        self.make_unicode_containing_tree()
248
        orig = osutils.normalized_filename
249
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
250
        try:
251
            # TODO: jam 20060701 In the future, this should probably
252
            #       just ignore files that don't fit the normalization
253
            #       rules, rather than exploding
254
            self.assertRaises(errors.InvalidNormalization,
255
                    self.wt.smart_add, [])
256
        finally:
257
            osutils.normalized_filename = orig