~bzr-pqm/bzr/bzr.dev

1852.16.5 by John Arbash Meinel
[merge] bzr.dev 2255, resolve conflicts, update copyrights
1
# Copyright (C) 2006, 2007 Canonical Ltd
1852.15.9 by Robert Collins
Add missing test script.
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
"""Tests for the extra cases that WorkingTree.walkdirs can encounter."""
18
19
import os
20
1852.15.12 by Robert Collins
WorkingTree.walkdirs handling of changing file kinds, and multi-directory with missing and unknown ordering bugfix.
21
from bzrlib import transform
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
22
from bzrlib.tests import SymlinkFeature
1852.15.9 by Robert Collins
Add missing test script.
23
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
24
25
# tests to write:
26
# type mismatches - file to link, dir, dir to file, link, link to file, dir
27
2457.2.5 by Marius Kruger
move DirBlock out of TestWalkdirs as per review comment
28
class DirBlock:
2457.2.6 by Marius Kruger
add DirBlock comment
29
    """Object representation of the tuples returned by dirstate."""
2457.2.5 by Marius Kruger
move DirBlock out of TestWalkdirs as per review comment
30
31
    def __init__(self, tree, file_path, file_name=None, id=None,
32
                 inventory_kind=None, stat=None, disk_kind='unknown'):
33
        self.file_path = file_path
34
        self.abspath = tree.abspath(file_path)
35
        self.relpath = tree.relpath(file_path)
3376.2.11 by Martin Pool
Compare to None using is/is not not ==
36
        if file_name is None:
2457.2.5 by Marius Kruger
move DirBlock out of TestWalkdirs as per review comment
37
           file_name = os.path.split(file_path)[-1]
38
           if len(file_name) == 0:
39
               file_name = os.path.split(file_path)[-2]
40
        self.file_name = file_name
41
        self.id = id
42
        self.inventory_kind = inventory_kind
43
        self.stat = stat
44
        self.disk_kind = disk_kind
45
46
    def as_tuple(self):
47
         return (self.relpath, self.file_name, self.disk_kind,
48
                 self.stat, self.id, self.inventory_kind)
49
50
    def as_dir_tuple(self):
51
         return (self.relpath, self.id)
52
53
    def __str__(self):
54
        return """
2457.2.1 by Marius Kruger
* Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
55
file_path      = %r
56
abspath        = %r
57
relpath        = %r
58
file_name      = %r
59
id             = %r
60
inventory_kind = %r
61
stat           = %r
62
disk_kind      = %r""" % (self.file_path, self.abspath, self.relpath,
2457.2.5 by Marius Kruger
move DirBlock out of TestWalkdirs as per review comment
63
        self.file_name, self.id, self.inventory_kind, self.stat,
64
        self.disk_kind)
65
66
67
class TestWalkdirs(TestCaseWithWorkingTree):
68
69
    added='added'
70
    missing='missing'
71
    unknown='unknown'
2457.2.1 by Marius Kruger
* Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
72
73
    def get_tree(self, file_status, prefix=None):
1852.15.9 by Robert Collins
Add missing test script.
74
        tree = self.make_branch_and_tree('.')
2457.2.1 by Marius Kruger
* Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
75
        dirblocks = []
76
        paths = [
77
            file_status + ' file',
78
            file_status + ' dir/',
79
            file_status + ' dir/a file',
80
            file_status + ' empty dir/',
81
            ]
82
        self.build_tree(paths)
83
84
        def add_dirblock(path, kind):
2457.2.5 by Marius Kruger
move DirBlock out of TestWalkdirs as per review comment
85
            dirblock = DirBlock(tree, path)
2457.2.1 by Marius Kruger
* Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
86
            if file_status != self.unknown:
87
                dirblock.id = 'a ' + str(path).replace('/','-') + '-id'
88
                dirblock.inventory_kind = kind
89
            if file_status != self.missing:
90
                dirblock.disk_kind = kind
91
                dirblock.stat = os.lstat(dirblock.relpath)
92
            dirblocks.append(dirblock)
93
94
        add_dirblock(paths[0], 'file')
95
        add_dirblock(paths[1], 'directory')
96
        add_dirblock(paths[2], 'file')
97
        add_dirblock(paths[3], 'directory')
98
99
        if file_status != self.unknown:
100
            tree.add(paths, [db.id for db in dirblocks])
101
102
        if file_status == self.missing:
103
            # now make the files be missing
104
            tree.bzrdir.root_transport.delete(dirblocks[0].relpath)
105
            tree.bzrdir.root_transport.delete_tree(dirblocks[1].relpath)
106
            tree.bzrdir.root_transport.delete_tree(dirblocks[3].relpath)
107
1852.15.9 by Robert Collins
Add missing test script.
108
        expected_dirblocks = [
2255.2.47 by Robert Collins
Adjust walkdirs tests to talk a lock around walk_dirs.
109
            (('', tree.path2id('')),
2457.2.1 by Marius Kruger
* Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
110
             [dirblocks[1].as_tuple(), dirblocks[3].as_tuple(),
111
              dirblocks[0].as_tuple()]
112
            ),
113
            (dirblocks[1].as_dir_tuple(),
114
             [dirblocks[2].as_tuple()]
115
            ),
116
            (dirblocks[3].as_dir_tuple(),
117
             []
1852.15.10 by Robert Collins
Tweak the Tree.walkdirs interface more to be more useful.
118
            ),
119
            ]
2457.2.1 by Marius Kruger
* Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
120
        if prefix:
121
            expected_dirblocks = [e for e in expected_dirblocks
122
                if len(e) > 0 and len(e[0]) > 0 and e[0][0] == prefix]
1852.15.10 by Robert Collins
Tweak the Tree.walkdirs interface more to be more useful.
123
        return tree, expected_dirblocks
2457.2.1 by Marius Kruger
* Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
124
2457.2.7 by Marius Kruger
extract method as per review request
125
    def _test_walkdir(self, file_status, prefix=""):
126
        result = []
127
        tree, expected_dirblocks = self.get_tree(file_status, prefix)
128
        tree.lock_read()
129
        for dirinfo, dirblock in tree.walkdirs(prefix):
130
            result.append((dirinfo, list(dirblock)))
131
        tree.unlock()
132
133
        # check each return value for debugging ease.
134
        for pos, item in enumerate(expected_dirblocks):
135
            result_pos = []
136
            if len(result) > pos:
137
                result_pos = result[pos]
138
            self.assertEqual(item, result_pos)
139
        self.assertEqual(expected_dirblocks, result)
140
1852.15.10 by Robert Collins
Tweak the Tree.walkdirs interface more to be more useful.
141
    def test_walkdir_unknowns(self):
142
        """unknown files and directories should be reported by walkdirs."""
2457.2.7 by Marius Kruger
extract method as per review request
143
        self._test_walkdir(self.unknown)
1852.15.10 by Robert Collins
Tweak the Tree.walkdirs interface more to be more useful.
144
145
    def test_walkdir_from_unknown_dir(self):
146
        """Doing a walkdir when the requested prefix is unknown but on disk."""
2457.2.7 by Marius Kruger
extract method as per review request
147
        self._test_walkdir(self.unknown, 'unknown dir')
148
1852.15.11 by Robert Collins
Tree.walkdirs handles missing contents in workingtrees.
149
    def test_walkdir_missings(self):
150
        """missing files and directories should be reported by walkdirs."""
2457.2.7 by Marius Kruger
extract method as per review request
151
        self._test_walkdir(self.missing)
2457.2.1 by Marius Kruger
* Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
152
153
    def test_walkdir_from_dir(self):
154
        """Doing a walkdir when the requested prefix is known and on disk."""
2457.2.7 by Marius Kruger
extract method as per review request
155
        self._test_walkdir(self.added, 'added dir')
2457.2.1 by Marius Kruger
* Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
156
157
    def test_walkdir_from_empty_dir(self):
158
        """Doing a walkdir when the requested prefix is empty dir."""
2457.2.7 by Marius Kruger
extract method as per review request
159
        self._test_walkdir(self.added, 'added empty dir')
1852.15.11 by Robert Collins
Tree.walkdirs handles missing contents in workingtrees.
160
161
    def test_walkdir_from_missing_dir(self):
162
        """Doing a walkdir when the requested prefix is missing but on disk."""
2457.2.7 by Marius Kruger
extract method as per review request
163
        self._test_walkdir(self.missing, 'missing dir')
1852.15.12 by Robert Collins
WorkingTree.walkdirs handling of changing file kinds, and multi-directory with missing and unknown ordering bugfix.
164
165
    def test_walkdirs_type_changes(self):
166
        """Walkdir shows the actual kinds on disk and the recorded kinds."""
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
167
        self.requireFeature(SymlinkFeature)
1852.15.12 by Robert Collins
WorkingTree.walkdirs handling of changing file kinds, and multi-directory with missing and unknown ordering bugfix.
168
        tree = self.make_branch_and_tree('.')
169
        paths = ['file1', 'file2', 'dir1/', 'dir2/']
170
        ids = ['file1', 'file2', 'dir1', 'dir2']
171
        self.build_tree(paths)
172
        tree.add(paths, ids)
173
        tt = transform.TreeTransform(tree)
174
        root_transaction_id = tt.trans_id_tree_path('')
175
        tt.new_symlink('link1',
176
            root_transaction_id, 'link-target', 'link1')
177
        tt.new_symlink('link2',
178
            root_transaction_id, 'link-target', 'link2')
179
        tt.apply()
180
        tree.bzrdir.root_transport.delete_tree('dir1')
181
        tree.bzrdir.root_transport.delete_tree('dir2')
182
        tree.bzrdir.root_transport.delete('file1')
183
        tree.bzrdir.root_transport.delete('file2')
184
        tree.bzrdir.root_transport.delete('link1')
185
        tree.bzrdir.root_transport.delete('link2')
186
        changed_paths = ['dir1', 'file1/', 'link1', 'link2/']
187
        self.build_tree(changed_paths)
188
        os.symlink('target', 'dir2')
189
        os.symlink('target', 'file2')
190
        dir1_stat = os.lstat('dir1')
191
        dir2_stat = os.lstat('dir2')
192
        file1_stat = os.lstat('file1')
193
        file2_stat = os.lstat('file2')
194
        link1_stat = os.lstat('link1')
195
        link2_stat = os.lstat('link2')
196
        expected_dirblocks = [
2255.2.47 by Robert Collins
Adjust walkdirs tests to talk a lock around walk_dirs.
197
             (('', tree.path2id('')),
1852.15.12 by Robert Collins
WorkingTree.walkdirs handling of changing file kinds, and multi-directory with missing and unknown ordering bugfix.
198
              [('dir1', 'dir1', 'file', dir1_stat, 'dir1', 'directory'),
199
               ('dir2', 'dir2', 'symlink', dir2_stat, 'dir2', 'directory'),
200
               ('file1', 'file1', 'directory', file1_stat, 'file1', 'file'),
201
               ('file2', 'file2', 'symlink', file2_stat, 'file2', 'file'),
202
               ('link1', 'link1', 'file', link1_stat, 'link1', 'symlink'),
203
               ('link2', 'link2', 'directory', link2_stat, 'link2', 'symlink'),
204
              ]
205
             ),
206
             (('dir1', 'dir1'),
207
              [
208
              ]
209
             ),
210
             (('dir2', 'dir2'),
211
              [
212
              ]
213
             ),
214
             (('file1', None),
215
              [
216
              ]
217
             ),
218
             (('link2', None),
219
              [
220
              ]
221
             ),
222
            ]
2255.2.47 by Robert Collins
Adjust walkdirs tests to talk a lock around walk_dirs.
223
        tree.lock_read()
1852.15.12 by Robert Collins
WorkingTree.walkdirs handling of changing file kinds, and multi-directory with missing and unknown ordering bugfix.
224
        result = list(tree.walkdirs())
2255.2.47 by Robert Collins
Adjust walkdirs tests to talk a lock around walk_dirs.
225
        tree.unlock()
1852.15.12 by Robert Collins
WorkingTree.walkdirs handling of changing file kinds, and multi-directory with missing and unknown ordering bugfix.
226
        # check each return value for debugging ease.
227
        for pos, item in enumerate(expected_dirblocks):
228
            self.assertEqual(item, result[pos])
229
        self.assertEqual(len(expected_dirblocks), len(result))
2408.1.4 by Alexander Belchenko
workingtree_implementations: make usage of symlinks optional
230
231
    def test_walkdirs_type_changes_wo_symlinks(self):
232
        # similar to test_walkdirs_type_changes
233
        # but don't use symlinks for safe testing on win32
234
        tree = self.make_branch_and_tree('.')
235
        paths = ['file1', 'dir1/']
236
        ids = ['file1', 'dir1']
237
        self.build_tree(paths)
238
        tree.add(paths, ids)
239
        tree.bzrdir.root_transport.delete_tree('dir1')
240
        tree.bzrdir.root_transport.delete('file1')
241
        changed_paths = ['dir1', 'file1/']
242
        self.build_tree(changed_paths)
243
        dir1_stat = os.lstat('dir1')
244
        file1_stat = os.lstat('file1')
245
        expected_dirblocks = [
246
             (('', tree.path2id('')),
247
              [('dir1', 'dir1', 'file', dir1_stat, 'dir1', 'directory'),
248
               ('file1', 'file1', 'directory', file1_stat, 'file1', 'file'),
249
              ]
250
             ),
251
             (('dir1', 'dir1'),
252
              [
253
              ]
254
             ),
255
             (('file1', None),
256
              [
257
              ]
258
             ),
259
            ]
260
        tree.lock_read()
261
        result = list(tree.walkdirs())
262
        tree.unlock()
263
        # check each return value for debugging ease.
264
        for pos, item in enumerate(expected_dirblocks):
265
            self.assertEqual(item, result[pos])
266
        self.assertEqual(len(expected_dirblocks), len(result))