/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('.')
57
        self.build_tree(['file'])
2568.2.4 by Robert Collins
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
58
        wt.smart_add(['file'], save=False)
59
        # the file should not be added - no id.
60
        self.assertEqual(wt.path2id('file'), None)
61
        # 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.
62
        wt = wt.bzrdir.open_workingtree()
63
        self.assertEqual(wt.path2id('file'), None)
2568.2.4 by Robert Collins
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
64
65
    def test_add_dot_from_root(self):
66
        """Test adding . from the root of the tree.""" 
67
        paths = ("original/", "original/file1", "original/file2")
68
        self.build_tree(paths)
69
        wt = self.make_branch_and_tree('.')
70
        wt.smart_add((u".",))
71
        for path in paths:
72
            self.assertNotEqual(wt.path2id(path), None)
73
74
    def test_add_dot_from_subdir(self):
75
        """Test adding . from a subdir of the tree.""" 
76
        paths = ("original/", "original/file1", "original/file2")
77
        self.build_tree(paths)
78
        wt = self.make_branch_and_tree('.')
79
        wt.smart_add((u".",))
80
        for path in paths:
81
            self.assertNotEqual(wt.path2id(path), None)
82
83
    def test_add_tree_from_above_tree(self):
84
        """Test adding a tree from above the tree.""" 
85
        paths = ("original/", "original/file1", "original/file2")
86
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
87
                        "branch/original/file2")
88
        self.build_tree(branch_paths)
89
        wt = self.make_branch_and_tree('branch')
90
        wt.smart_add(("branch",))
91
        for path in paths:
92
            self.assertNotEqual(wt.path2id(path), None)
93
94
    def test_add_above_tree_preserves_tree(self):
95
        """Test nested trees are not affect by an add above them."""
96
        paths = ("original/", "original/file1", "original/file2")
97
        child_paths = ("path",)
98
        full_child_paths = ("original/child", "original/child/path")
99
        build_paths = ("original/", "original/file1", "original/file2", 
100
                       "original/child/", "original/child/path")
101
        
102
        self.build_tree(build_paths)
103
        wt = self.make_branch_and_tree('.')
104
        child_tree = self.make_branch_and_tree('original/child')
105
        wt.smart_add((".",))
106
        for path in paths:
107
            self.assertNotEqual((path, wt.path2id(path)),
108
                                (path, None))
109
        for path in full_child_paths:
110
            self.assertEqual((path, wt.path2id(path)),
111
                             (path, None))
112
        for path in child_paths:
113
            self.assertEqual(child_tree.path2id(path), None)
114
115
    def test_add_paths(self):
116
        """Test smart-adding a list of paths."""
117
        paths = ("file1", "file2")
118
        self.build_tree(paths)
119
        wt = self.make_branch_and_tree('.')
120
        wt.smart_add(paths)
121
        for path in paths:
122
            self.assertNotEqual(wt.path2id(path), None)
123
    
124
    def test_add_ignored_nested_paths(self):
125
        """Test smart-adding a list of paths which includes ignored ones."""
126
        wt = self.make_branch_and_tree('.')
127
        tree_shape = ("adir/", "adir/CVS/", "adir/CVS/afile", "adir/CVS/afile2")
128
        add_paths = ("adir/CVS", "adir/CVS/afile", "adir")
129
        expected_paths = ("adir", "adir/CVS", "adir/CVS/afile", "adir/CVS/afile2")
130
        self.build_tree(tree_shape)
131
        wt.smart_add(add_paths)
132
        for path in expected_paths:
133
            self.assertNotEqual(wt.path2id(path), None, "No id added for %s" % path)
134
135
    def test_add_non_existant(self):
136
        """Test smart-adding a file that does not exist."""
137
        wt = self.make_branch_and_tree('.')
138
        self.assertRaises(errors.NoSuchFile, wt.smart_add, ['non-existant-file'])
139
140
    def test_returns_and_ignores(self):
141
        """Correctly returns added/ignored files"""
142
        wt = self.make_branch_and_tree('.')
143
        # The default ignore list includes '*.py[co]', but not CVS
144
        ignores._set_user_ignores(['*.py[co]'])
145
        self.build_tree(['inertiatic/', 'inertiatic/esp', 'inertiatic/CVS',
146
                        'inertiatic/foo.pyc'])
147
        added, ignored = wt.smart_add(u'.')
148
        self.assertSubset(('inertiatic', 'inertiatic/esp', 'inertiatic/CVS'),
149
                          added)
150
        self.assertSubset(('*.py[co]',), ignored)
151
        self.assertSubset(('inertiatic/foo.pyc',), ignored['*.py[co]'])
152
153
    def test_add_multiple_dirs(self):
154
        """Test smart adding multiple directories at once."""
155
        added_paths = ['file1', 'file2',
156
                       'dir1/', 'dir1/file3',
157
                       'dir1/subdir2/', 'dir1/subdir2/file4',
158
                       'dir2/', 'dir2/file5',
159
                      ]
160
        not_added = ['file6', 'dir3/', 'dir3/file7', 'dir3/file8']
161
        self.build_tree(added_paths)
162
        self.build_tree(not_added)
163
164
        wt = self.make_branch_and_tree('.')
165
        wt.smart_add(['file1', 'file2', 'dir1', 'dir2'])
166
167
        for path in added_paths:
168
            self.assertNotEqual(None, wt.path2id(path.rstrip('/')),
169
                    'Failed to add path: %s' % (path,))
170
        for path in not_added:
171
            self.assertEqual(None, wt.path2id(path.rstrip('/')),
172
                    'Accidentally added path: %s' % (path,))
173
174
    def test_custom_ids(self):
175
        sio = StringIO()
176
        action = AddCustomIDAction(to_file=sio, should_print=True)
177
        self.build_tree(['file1', 'dir1/', 'dir1/file2'])
178
179
        wt = self.make_branch_and_tree('.')
180
        wt.smart_add(['.'], action=action)
181
        # The order of adds is not strictly fixed:
182
        sio.seek(0)
183
        lines = sorted(sio.readlines())
184
        self.assertEqualDiff(['added dir1 with id directory-dir1\n',
185
                              'added dir1/file2 with id file-dir1%file2\n',
186
                              'added file1 with id file-file1\n',
187
                             ], lines)
188
        wt.lock_read()
189
        self.addCleanup(wt.unlock)
190
        self.assertEqual([('', wt.path2id('')),
191
                          ('dir1', 'directory-dir1'),
192
                          ('dir1/file2', 'file-dir1%file2'),
193
                          ('file1', 'file-file1'),
194
                         ], [(path, ie.file_id) for path, ie
195
                                in wt.inventory.iter_entries()])
196
197
    def make_unicode_containing_tree(self):
198
        try:
199
            self.build_tree([u'a\u030a'])
200
        except UnicodeError:
2568.2.10 by Robert Collins
And a missing import.
201
            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
202
        self.wt = self.make_branch_and_tree('.')
203
204
    def test_accessible_explicit(self):
205
        self.make_unicode_containing_tree()
206
        orig = osutils.normalized_filename
207
        osutils.normalized_filename = osutils._accessible_normalized_filename
208
        try:
209
            self.wt.smart_add([u'a\u030a'])
210
            self.wt.lock_read()
211
            self.addCleanup(self.wt.unlock)
212
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
213
                    [(path, ie.kind) for path,ie in 
214
                        self.wt.inventory.iter_entries()])
215
        finally:
216
            osutils.normalized_filename = orig
217
218
    def test_accessible_implicit(self):
219
        self.make_unicode_containing_tree()
220
        orig = osutils.normalized_filename
221
        osutils.normalized_filename = osutils._accessible_normalized_filename
222
        try:
223
            self.wt.smart_add([])
224
            self.wt.lock_read()
225
            self.addCleanup(self.wt.unlock)
226
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
227
                    [(path, ie.kind) for path,ie in 
228
                        self.wt.inventory.iter_entries()])
229
        finally:
230
            osutils.normalized_filename = orig
231
232
    def test_inaccessible_explicit(self):
233
        self.make_unicode_containing_tree()
234
        orig = osutils.normalized_filename
235
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
236
        try:
237
            self.assertRaises(errors.InvalidNormalization,
238
                    self.wt.smart_add, [u'a\u030a'])
239
        finally:
240
            osutils.normalized_filename = orig
241
242
    def test_inaccessible_implicit(self):
243
        self.make_unicode_containing_tree()
244
        orig = osutils.normalized_filename
245
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
246
        try:
247
            # TODO: jam 20060701 In the future, this should probably
248
            #       just ignore files that don't fit the normalization
249
            #       rules, rather than exploding
250
            self.assertRaises(errors.InvalidNormalization,
251
                    self.wt.smart_add, [])
252
        finally:
253
            osutils.normalized_filename = orig