/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
16
17
"""Tests for WorkingTree.paths2ids.
18
19
This API probably needs to be exposed as a tree implementation test, but these
20
initial tests are for the specific cases being refactored from
21
find_ids_across_trees.
22
"""
23
24
from operator import attrgetter
25
2255.2.101 by Robert Collins
Finish making Tree.ids2paths support the file_ids_across_trees api.
26
from bzrlib import errors
6345.1.2 by Martin Packman
Add targetted working tree tests for places that raise PathsNotVersionedError
27
from bzrlib.tests import features
4523.1.4 by Martin Pool
Rename remaining *_implementations tests
28
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
29
30
2255.2.103 by Robert Collins
Document some future tests for paths2ids.
31
# TODO: This needs an additional test: do a merge, then do a
32
# paths2id(trees=left parent only), and also with (trees=all parents) to check
33
# that only the requested trees are considered - i.e. have an unversioned path
34
# in the unlisted tree, or an extra file that moves into the selected path but
35
# should not be returned
36
37
# TODO: test that supplying paths with duplication - i.e. foo, foo, foo/bar -
38
# does not result in garbage out.
39
2255.2.104 by Robert Collins
Add WorkingTree4.paths2ids which is inventory-usage free if the trees being examined are in the dirstate.
40
# TODO: Are we meant to raise the precise unversioned paths when some are
41
# unversioned - if so, test this.
2255.2.103 by Robert Collins
Document some future tests for paths2ids.
42
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
43
class TestPaths2Ids(TestCaseWithWorkingTree):
44
2255.2.101 by Robert Collins
Finish making Tree.ids2paths support the file_ids_across_trees api.
45
    def assertExpectedIds(self, ids, tree, paths, trees=None,
46
        require_versioned=True):
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
47
        """Run paths2ids for tree, and check the result."""
48
        tree.lock_read()
49
        if trees:
50
            map(apply, map(attrgetter('lock_read'), trees))
2255.2.101 by Robert Collins
Finish making Tree.ids2paths support the file_ids_across_trees api.
51
            result = tree.paths2ids(paths, trees,
52
                require_versioned=require_versioned)
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
53
            map(apply, map(attrgetter('unlock'), trees))
54
        else:
2255.2.101 by Robert Collins
Finish making Tree.ids2paths support the file_ids_across_trees api.
55
            result = tree.paths2ids(paths,
56
                require_versioned=require_versioned)
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
57
        self.assertEqual(set(ids), result)
58
        tree.unlock()
59
2255.2.104 by Robert Collins
Add WorkingTree4.paths2ids which is inventory-usage free if the trees being examined are in the dirstate.
60
    def test_paths_none_result_none(self):
61
        tree = self.make_branch_and_tree('tree')
62
        tree.lock_read()
63
        self.assertEqual(None, tree.paths2ids(None))
64
        tree.unlock()
65
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
66
    def test_find_single_root(self):
67
        tree = self.make_branch_and_tree('tree')
68
        self.assertExpectedIds([tree.path2id('')], tree, [''])
69
70
    def test_find_tree_and_clone_roots(self):
71
        tree = self.make_branch_and_tree('tree')
72
        clone = tree.bzrdir.clone('clone').open_workingtree()
73
        clone.lock_tree_write()
74
        clone_root_id = 'new-id'
75
        clone.set_root_id(clone_root_id)
76
        tree_root_id = tree.path2id('')
77
        clone.unlock()
78
        self.assertExpectedIds([tree_root_id, clone_root_id], tree, [''], [clone])
79
80
    def test_find_tree_basis_roots(self):
81
        tree = self.make_branch_and_tree('tree')
82
        tree.commit('basis')
83
        basis = tree.basis_tree()
84
        basis_root_id = basis.path2id('')
85
        tree.lock_tree_write()
86
        tree_root_id = 'new-id'
87
        tree.set_root_id(tree_root_id)
88
        tree.unlock()
89
        self.assertExpectedIds([tree_root_id, basis_root_id], tree, [''], [basis])
90
91
    def test_find_children_of_moved_directories(self):
92
        """Check the basic nasty corner case that path2ids should handle.
93
94
        This is the following situation:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
95
        basis:
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
96
          / ROOT
97
          /dir dir
98
          /dir/child-moves child-moves
99
          /dir/child-stays child-stays
100
          /dir/child-goes  child-goes
101
102
        current tree:
103
          / ROOT
104
          /child-moves child-moves
105
          /newdir newdir
106
          /newdir/dir  dir
107
          /newdir/dir/child-stays child-stays
108
          /newdir/dir/new-child   new-child
109
110
        In english: we move a directory under a directory that was a sibling,
111
        and at the same time remove, or move out of the directory, some of its
112
        children, and give it a new child previous absent or a sibling.
113
114
        current_tree.path2ids(['newdir'], [basis]) is meant to handle this
115
        correctly: that is it should return the ids:
116
          newdir because it was provided
117
          dir, because its under newdir in current
118
          child-moves because its under dir in old
119
          child-stays either because its under newdir/dir in current, or under dir in old
120
          child-goes because its under dir in old.
121
          new-child because its under dir in new
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
122
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
123
        Symmetrically, current_tree.path2ids(['dir'], [basis]) is meant to show
124
        new-child, even though its not under the path 'dir' in current, because
125
        its under a path selected by 'dir' in basis:
126
          dir because its selected in basis.
127
          child-moves because its under dir in old
128
          child-stays either because its under newdir/dir in current, or under dir in old
129
          child-goes because its under dir in old.
130
          new-child because its under dir in new.
131
        """
132
        tree = self.make_branch_and_tree('tree')
133
        self.build_tree(
134
            ['tree/dir/', 'tree/dir/child-moves', 'tree/dir/child-stays',
135
             'tree/dir/child-goes'])
136
        tree.add(['dir', 'dir/child-moves', 'dir/child-stays', 'dir/child-goes'],
137
                 ['dir', 'child-moves', 'child-stays', 'child-goes'])
138
        tree.commit('create basis')
139
        basis = tree.basis_tree()
140
        tree.unversion(['child-goes'])
141
        tree.rename_one('dir/child-moves', 'child-moves')
142
        self.build_tree(['tree/newdir/'])
143
        tree.add(['newdir'], ['newdir'])
144
        tree.rename_one('dir/child-stays', 'child-stays')
145
        tree.rename_one('dir', 'newdir/dir')
146
        tree.rename_one('child-stays', 'newdir/dir/child-stays')
147
        self.build_tree(['tree/newdir/dir/new-child'])
148
        tree.add(['newdir/dir/new-child'], ['new-child'])
149
        self.assertExpectedIds(
150
            ['newdir', 'dir', 'child-moves', 'child-stays', 'child-goes',
151
             'new-child'], tree, ['newdir'], [basis])
152
        self.assertExpectedIds(
153
            ['dir', 'child-moves', 'child-stays', 'child-goes', 'new-child'],
154
            tree, ['dir'], [basis])
2255.2.101 by Robert Collins
Finish making Tree.ids2paths support the file_ids_across_trees api.
155
156
    def test_unversioned_one_tree(self):
157
        tree = self.make_branch_and_tree('tree')
158
        self.build_tree(['tree/unversioned'])
159
        self.assertExpectedIds([], tree, ['unversioned'], require_versioned=False)
160
        tree.lock_read()
161
        self.assertRaises(errors.PathsNotVersionedError, tree.paths2ids, ['unversioned'])
162
        tree.unlock()
163
2255.2.104 by Robert Collins
Add WorkingTree4.paths2ids which is inventory-usage free if the trees being examined are in the dirstate.
164
    def test_unversioned_in_one_of_multiple_trees(self):
165
        # in this test, the path is unversioned in only one tree, and thus
166
        # should not raise an error: it must be unversioned in *all* trees to
167
        # error.
168
        tree = self.make_branch_and_tree('tree')
169
        tree.commit('make basis')
170
        basis = tree.basis_tree()
171
        self.build_tree(['tree/in-one'])
172
        tree.add(['in-one'], ['in-one'])
173
        self.assertExpectedIds(['in-one'], tree, ['in-one'], [basis])
174
175
    def test_unversioned_all_of_multiple_trees(self):
176
        # in this test, the path is unversioned in every tree, and thus
177
        # should not raise an error: it must be unversioned in *all* trees to
178
        # error.
179
        tree = self.make_branch_and_tree('tree')
180
        tree.commit('make basis')
181
        basis = tree.basis_tree()
2255.2.101 by Robert Collins
Finish making Tree.ids2paths support the file_ids_across_trees api.
182
        self.assertExpectedIds([], tree, ['unversioned'], [basis],
183
            require_versioned=False)
184
        tree.lock_read()
185
        basis.lock_read()
186
        self.assertRaises(errors.PathsNotVersionedError, tree.paths2ids,
187
            ['unversioned'], [basis])
188
        self.assertRaises(errors.PathsNotVersionedError, basis.paths2ids,
189
            ['unversioned'], [tree])
190
        basis.unlock()
191
        tree.unlock()
6345.1.2 by Martin Packman
Add targetted working tree tests for places that raise PathsNotVersionedError
192
193
    def test_unversioned_non_ascii_one_tree(self):
194
        self.requireFeature(features.UnicodeFilenameFeature)
195
        tree = self.make_branch_and_tree('.')
196
        self.build_tree([u"\xa7"])
197
        self.assertExpectedIds([], tree, [u"\xa7"], require_versioned=False)
198
        self.addCleanup(tree.lock_read().unlock)
199
        e = self.assertRaises(errors.PathsNotVersionedError,
200
            tree.paths2ids, [u"\xa7"])
201
        self.assertEqual([u"\xa7"], e.paths)