/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5752.3.8 by John Arbash Meinel
Merge bzr.dev 5764 to resolve release-notes (aka NEWS) conflicts
1
# Copyright (C) 2005-2011 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1 by mbp at sourcefrog
import from baz patch-364
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1 by mbp at sourcefrog
import from baz patch-364
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1 by mbp at sourcefrog
import from baz patch-364
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
1 by mbp at sourcefrog
import from baz patch-364
16
17
"""Tree classes, representing directory at point in time.
18
"""
19
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
20
from __future__ import absolute_import
21
7206.3.3 by Jelmer Vernooij
Fix collections import.
22
try:
23
    from collections.abc import deque
24
except ImportError:  # python < 3.7
25
    from collections import deque
26
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
27
from .lazy_import import lazy_import
5745.3.1 by Jelmer Vernooij
Use lazy imports in bzrlib.tree.
28
lazy_import(globals(), """
800 by Martin Pool
Merge John's import-speedup branch:
29
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
30
from breezy import (
3398.1.24 by Ian Clatworthy
make iter_search_rules a tree method
31
    conflicts as _mod_conflicts,
3368.2.30 by Ian Clatworthy
add -Dfilters support
32
    debug,
2079.1.1 by John Arbash Meinel
Create a deprecated bzrlib.tree.RevisionTree() in favor of bzrlib.revisiontree.RevisionTree()
33
    delta,
3368.2.16 by Ian Clatworthy
add real implementation of Tree.get_filter_stack
34
    filters,
1551.15.46 by Aaron Bentley
Move plan merge to tree
35
    revision as _mod_revision,
3398.1.24 by Ian Clatworthy
make iter_search_rules a tree method
36
    rules,
5745.3.4 by Jelmer Vernooij
Merge bzr.dev.
37
    trace,
2079.1.1 by John Arbash Meinel
Create a deprecated bzrlib.tree.RevisionTree() in favor of bzrlib.revisiontree.RevisionTree()
38
    )
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
39
from breezy.i18n import gettext
5745.3.1 by Jelmer Vernooij
Use lazy imports in bzrlib.tree.
40
""")
41
6731.1.1 by Jelmer Vernooij
Move FileTimestampUnavailable to breezy.tree.
42
from . import (
43
    errors,
6754.8.3 by Jelmer Vernooij
Use context manager in decorators.
44
    lock,
6731.1.1 by Jelmer Vernooij
Move FileTimestampUnavailable to breezy.tree.
45
    osutils,
46
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
47
from .inter import InterObject
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
48
from .sixish import (
6973.6.2 by Jelmer Vernooij
Fix more tests.
49
    text_type,
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
50
    viewvalues,
51
    )
1 by mbp at sourcefrog
import from baz patch-364
52
1852.5.1 by Robert Collins
Deprecate EmptyTree in favour of using Repository.revision_tree.
53
6731.1.1 by Jelmer Vernooij
Move FileTimestampUnavailable to breezy.tree.
54
class FileTimestampUnavailable(errors.BzrError):
55
56
    _fmt = "The filestamp for %(path)s is not available."
57
58
    internal_error = True
59
60
    def __init__(self, path):
61
        self.path = path
62
63
7358.4.1 by Jelmer Vernooij
Add Tree.get_nested_tree.
64
class MissingNestedTree(errors.BzrError):
65
66
    _fmt = "The nested tree for %(path)s can not be resolved."""
67
68
    def __init__(self, path):
69
        self.path = path
70
71
6846.6.1 by Jelmer Vernooij
Move Tree{Link,File,Directory,Entry} to breezy.tree.
72
class TreeEntry(object):
73
    """An entry that implements the minimum interface used by commands.
74
    """
75
7322.3.1 by Jelmer Vernooij
Use slots on default Tree objects.
76
    __slots__ = []
77
6846.6.1 by Jelmer Vernooij
Move Tree{Link,File,Directory,Entry} to breezy.tree.
78
    def __eq__(self, other):
6857 by Jelmer Vernooij
Merge lp:~jelmer/brz/move-ie.
79
        # yes, this is ugly, TODO: best practice __eq__ style.
6846.6.1 by Jelmer Vernooij
Move Tree{Link,File,Directory,Entry} to breezy.tree.
80
        return (isinstance(other, TreeEntry)
81
                and other.__class__ == self.__class__)
82
7143.19.2 by Jelmer Vernooij
Some test fixes.
83
    kind = None
84
6846.6.1 by Jelmer Vernooij
Move Tree{Link,File,Directory,Entry} to breezy.tree.
85
    def kind_character(self):
86
        return "???"
87
88
89
class TreeDirectory(TreeEntry):
90
    """See TreeEntry. This is a directory in a working tree."""
91
7322.3.1 by Jelmer Vernooij
Use slots on default Tree objects.
92
    __slots__ = []
93
7143.19.2 by Jelmer Vernooij
Some test fixes.
94
    kind = 'directory'
95
6846.6.1 by Jelmer Vernooij
Move Tree{Link,File,Directory,Entry} to breezy.tree.
96
    def kind_character(self):
97
        return "/"
98
99
100
class TreeFile(TreeEntry):
101
    """See TreeEntry. This is a regular file in a working tree."""
102
7322.3.1 by Jelmer Vernooij
Use slots on default Tree objects.
103
    __slots__ = []
104
7143.19.2 by Jelmer Vernooij
Some test fixes.
105
    kind = 'file'
106
6846.6.1 by Jelmer Vernooij
Move Tree{Link,File,Directory,Entry} to breezy.tree.
107
    def kind_character(self):
108
        return ''
109
110
111
class TreeLink(TreeEntry):
112
    """See TreeEntry. This is a symlink in a working tree."""
113
7322.3.1 by Jelmer Vernooij
Use slots on default Tree objects.
114
    __slots__ = []
115
7143.19.2 by Jelmer Vernooij
Some test fixes.
116
    kind = 'symlink'
117
6846.6.1 by Jelmer Vernooij
Move Tree{Link,File,Directory,Entry} to breezy.tree.
118
    def kind_character(self):
119
        return ''
120
121
6926.2.1 by Jelmer Vernooij
Some tree reference fixes.
122
class TreeReference(TreeEntry):
123
    """See TreeEntry. This is a reference to a nested tree in a working tree."""
124
7322.3.1 by Jelmer Vernooij
Use slots on default Tree objects.
125
    __slots__ = []
126
7143.19.2 by Jelmer Vernooij
Some test fixes.
127
    kind = 'tree-reference'
128
6926.2.1 by Jelmer Vernooij
Some tree reference fixes.
129
    def kind_character(self):
7143.19.2 by Jelmer Vernooij
Some test fixes.
130
        return '+'
6926.2.1 by Jelmer Vernooij
Some tree reference fixes.
131
132
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
133
class TreeChange(object):
134
    """Describes the changes between the same item in two different trees."""
135
7322.1.5 by Jelmer Vernooij
Fix slice handling.
136
    __slots__ = ['file_id', 'path', 'changed_content', 'versioned', 'parent_id',
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
137
                 'name', 'kind', 'executable', 'copied']
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
138
7322.1.5 by Jelmer Vernooij
Fix slice handling.
139
    def __init__(self, file_id, path, changed_content, versioned, parent_id,
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
140
                 name, kind, executable, copied=False):
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
141
        self.file_id = file_id
7322.1.4 by Jelmer Vernooij
Use singular for consistency.
142
        self.path = path
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
143
        self.changed_content = changed_content
144
        self.versioned = versioned
7322.1.5 by Jelmer Vernooij
Fix slice handling.
145
        self.parent_id = parent_id
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
146
        self.name = name
147
        self.kind = kind
148
        self.executable = executable
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
149
        self.copied = copied
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
150
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
151
    def __repr__(self):
7358.16.1 by Jelmer Vernooij
Don't make TreeChange tuple-like objects anymore, so we can add and remove attributes as necessary.
152
        return "%s%r" % (self.__class__.__name__, self._as_tuple())
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
153
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
154
    def __len__(self):
7322.1.3 by Jelmer Vernooij
Simplify.
155
        return len(self.__slots__)
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
156
7358.16.1 by Jelmer Vernooij
Don't make TreeChange tuple-like objects anymore, so we can add and remove attributes as necessary.
157
    def _as_tuple(self):
7322.1.4 by Jelmer Vernooij
Use singular for consistency.
158
        return (self.file_id, self.path, self.changed_content, self.versioned,
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
159
                self.parent_id, self.name, self.kind, self.executable, self.copied)
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
160
161
    def __eq__(self, other):
162
        if isinstance(other, TreeChange):
7358.16.1 by Jelmer Vernooij
Don't make TreeChange tuple-like objects anymore, so we can add and remove attributes as necessary.
163
            return self._as_tuple() == other._as_tuple()
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
164
        if isinstance(other, tuple):
7358.16.1 by Jelmer Vernooij
Don't make TreeChange tuple-like objects anymore, so we can add and remove attributes as necessary.
165
            return self._as_tuple() == other
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
166
        return False
167
7322.1.7 by Jelmer Vernooij
Fix remaining tests.
168
    def __lt__(self, other):
7358.16.1 by Jelmer Vernooij
Don't make TreeChange tuple-like objects anymore, so we can add and remove attributes as necessary.
169
        return self._as_tuple() < other._as_tuple()
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
170
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
171
    def meta_modified(self):
7358.11.9 by Jelmer Vernooij
Fix other tests.
172
        if self.versioned == (True, True):
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
173
            return (self.executable[0] != self.executable[1])
174
        return False
175
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
176
    def is_reparented(self):
177
        return self.parent_id[0] != self.parent_id[1]
178
7322.1.7 by Jelmer Vernooij
Fix remaining tests.
179
    def discard_new(self):
180
        return self.__class__(
181
            self.file_id, (self.path[0], None), self.changed_content,
182
            (self.versioned[0], None), (self.parent_id[0], None),
183
            (self.name[0], None), (self.kind[0], None),
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
184
            (self.executable[0], None),
185
            copied=False)
7322.1.7 by Jelmer Vernooij
Fix remaining tests.
186
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
187
558 by Martin Pool
- All top-level classes inherit from object
188
class Tree(object):
1 by mbp at sourcefrog
import from baz patch-364
189
    """Abstract file tree.
190
191
    There are several subclasses:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
192
1 by mbp at sourcefrog
import from baz patch-364
193
    * `WorkingTree` exists as files on disk editable by the user.
194
195
    * `RevisionTree` is a tree as recorded at some point in the past.
196
197
    Trees can be compared, etc, regardless of whether they are working
198
    trees or versioned trees.
199
    """
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
200
6883.5.17 by Jelmer Vernooij
Add Tree.supports_rename_tracking().
201
    def supports_rename_tracking(self):
202
        """Whether this tree supports rename tracking.
203
204
        This defaults to True, but some implementations may want to override
205
        it.
206
        """
207
        return True
208
6110.6.1 by Jelmer Vernooij
Add Tree.has_versioned_directories.
209
    def has_versioned_directories(self):
210
        """Whether this tree can contain explicitly versioned directories.
211
212
        This defaults to True, but some implementations may want to override
213
        it.
214
        """
215
        return True
216
7122.6.3 by Jelmer Vernooij
Merge trunk.
217
    def supports_symlinks(self):
218
        """Does this tree support symbolic links?
219
        """
220
        return osutils.has_symlinks()
221
1852.9.6 by Robert Collins
Merge the change from Tree.compare to Tree.changes_from.
222
    def changes_from(self, other, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
223
                     extra_trees=None, require_versioned=False, include_root=False,
224
                     want_unversioned=False):
1852.8.8 by Robert Collins
change Tree.compare to Tree.changes_from - its better for the common case.
225
        """Return a TreeDelta of the changes from other to this tree.
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
226
227
        :param other: A tree to compare with.
228
        :param specific_files: An optional list of file paths to restrict the
229
            comparison to. When mapping filenames to ids, all matches in all
230
            trees (including optional extra_trees) are used, and all children of
231
            matched directories are included.
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
232
        :param want_unchanged: An optional boolean requesting the inclusion of
233
            unchanged entries in the result.
234
        :param extra_trees: An optional list of additional trees to use when
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
235
            mapping the contents of specific_files (paths) to their identities.
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
236
        :param require_versioned: An optional boolean (defaults to False). When
237
            supplied and True all the 'specific_files' must be versioned, or
238
            a PathsNotVersionedError will be thrown.
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
239
        :param want_unversioned: Scan for unversioned paths.
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
240
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
241
        The comparison will be performed by an InterTree object looked up on
1852.8.4 by Robert Collins
Hook InterTree into Tree.
242
        self and other.
243
        """
1852.8.8 by Robert Collins
change Tree.compare to Tree.changes_from - its better for the common case.
244
        # Martin observes that Tree.changes_from returns a TreeDelta and this
245
        # may confuse people, because the class name of the returned object is
246
        # a synonym of the object referenced in the method name.
1852.9.6 by Robert Collins
Merge the change from Tree.compare to Tree.changes_from.
247
        return InterTree.get(other, self).compare(
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
248
            want_unchanged=want_unchanged,
249
            specific_files=specific_files,
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
250
            extra_trees=extra_trees,
251
            require_versioned=require_versioned,
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
252
            include_root=include_root,
253
            want_unversioned=want_unversioned,
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
254
            )
2012.1.1 by Aaron Bentley
Implement change iterator
255
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
256
    def iter_changes(self, from_tree, include_unchanged=False,
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
257
                     specific_files=None, pb=None, extra_trees=None,
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
258
                     require_versioned=True, want_unversioned=False):
4988.10.6 by John Arbash Meinel
Fix bug #304182 by adding a trivial docstring to Tree.iter_changes
259
        """See InterTree.iter_changes"""
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
260
        intertree = InterTree.get(from_tree, self)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
261
        return intertree.iter_changes(include_unchanged, specific_files, pb,
7122.6.5 by Jelmer Vernooij
More improvements, add tests.
262
                                      extra_trees, require_versioned,
263
                                      want_unversioned=want_unversioned)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
264
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
265
    def conflicts(self):
266
        """Get a list of the conflicts in the tree.
267
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
268
        Each conflict is an instance of breezy.conflicts.Conflict.
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
269
        """
2748.2.1 by Lukáš Lalinsky
Return ConflictsList() instead of [] from Tree.conflicts.
270
        return _mod_conflicts.ConflictList()
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
271
2255.7.91 by Robert Collins
Move unknown detection in long status into the delta creation, saving a tree-scan.
272
    def extras(self):
273
        """For trees that can have unversioned files, return all such paths."""
274
        return []
275
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
276
    def get_parent_ids(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
277
        """Get the parent ids for this tree.
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
278
279
        :return: a list of parent ids. [] is returned to indicate
280
        a tree with no parents.
281
        :raises: BzrError if the parents are not known.
282
        """
283
        raise NotImplementedError(self.get_parent_ids)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
284
1 by mbp at sourcefrog
import from baz patch-364
285
    def has_filename(self, filename):
286
        """True if the tree has given filename."""
2818.2.1 by Ian Clatworthy
minor tree & dirstate code cleanups
287
        raise NotImplementedError(self.has_filename)
1 by mbp at sourcefrog
import from baz patch-364
288
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
289
    def is_ignored(self, filename):
290
        """Check whether the filename is ignored by this tree.
291
292
        :param filename: The relative filename within the tree.
293
        :return: True if the filename is ignored.
294
        """
295
        return False
296
3146.8.16 by Aaron Bentley
Updates from review
297
    def all_file_ids(self):
3146.8.2 by Aaron Bentley
Introduce iter_all_file_ids, to avoid hitting Inventory for this case
298
        """Iterate through all file ids, including ids for missing files."""
5837.2.1 by Jelmer Vernooij
Deprecate Tree.__iter__.
299
        raise NotImplementedError(self.all_file_ids)
3146.8.2 by Aaron Bentley
Introduce iter_all_file_ids, to avoid hitting Inventory for this case
300
6825.5.1 by Jelmer Vernooij
Implement Tree.all_versioned_paths.
301
    def all_versioned_paths(self):
302
        """Iterate through all paths, including paths for missing files."""
303
        raise NotImplementedError(self.all_versioned_paths)
304
1 by mbp at sourcefrog
import from baz patch-364
305
    def id2path(self, file_id):
2255.11.5 by Martin Pool
Tree.id2path should raise NoSuchId, not return None.
306
        """Return the path for a file id.
307
308
        :raises NoSuchId:
309
        """
5777.3.1 by Jelmer Vernooij
Split InventoryTree out of Tree.
310
        raise NotImplementedError(self.id2path)
1 by mbp at sourcefrog
import from baz patch-364
311
6929.6.1 by Jelmer Vernooij
Remove yield_parents argument to Tree.iter_entries_by_dir.
312
    def iter_entries_by_dir(self, specific_files=None):
1852.6.9 by Robert Collins
Add more test trees to the tree-implementations tests.
313
        """Walk the tree in 'by_dir' order.
314
3363.2.23 by Aaron Bentley
Fix iter_entries_by_dir ordering
315
        This will yield each entry in the tree as a (path, entry) tuple.
316
        The order that they are yielded is:
317
318
        Directories are walked in a depth-first lexicographical order,
319
        however, whenever a directory is reached, all of its direct child
320
        nodes are yielded in  lexicographical order before yielding the
321
        grandchildren.
322
323
        For example, in the tree::
324
325
           a/
326
             b/
327
               c
328
             d/
329
               e
330
           f/
331
             g
332
3363.5.4 by Aaron Bentley
Fix iteration order of iter_entries_by_dir
333
        The yield order (ignoring root) would be::
5891.1.3 by Andrew Bennetts
Move docstring formatting fixes.
334
3363.2.23 by Aaron Bentley
Fix iter_entries_by_dir ordering
335
          a, f, a/b, a/d, a/b/c, a/d/e, f/g
1852.6.9 by Robert Collins
Add more test trees to the tree-implementations tests.
336
        """
5777.3.1 by Jelmer Vernooij
Split InventoryTree out of Tree.
337
        raise NotImplementedError(self.iter_entries_by_dir)
1852.6.9 by Robert Collins
Add more test trees to the tree-implementations tests.
338
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
339
    def iter_child_entries(self, path):
6471.1.2 by Jelmer Vernooij
Add Tree.iter_child_entries.
340
        """Iterate over the children of a directory or tree reference.
341
6844.1.1 by Jelmer Vernooij
Many more foreign branch fixes.
342
        :param path: Path of the directory
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
343
        :raise NoSuchFile: When the path does not exist
6471.1.3 by Jelmer Vernooij
Add Tree.iter_child_entries.
344
        :return: Iterator over entries in the directory
6471.1.2 by Jelmer Vernooij
Add Tree.iter_child_entries.
345
        """
346
        raise NotImplementedError(self.iter_child_entries)
347
5793.2.1 by Jelmer Vernooij
Add Tree.list_files stub.
348
    def list_files(self, include_root=False, from_dir=None, recursive=True):
349
        """List all files in this tree.
350
351
        :param include_root: Whether to include the entry for the tree root
352
        :param from_dir: Directory under which to list files
353
        :param recursive: Whether to list files recursively
7143.19.5 by Jelmer Vernooij
Undo removal of kind.
354
        :return: iterator over tuples of
355
            (path, versioned, kind, inventory entry)
5793.2.1 by Jelmer Vernooij
Add Tree.list_files stub.
356
        """
357
        raise NotImplementedError(self.list_files)
358
2255.2.226 by Robert Collins
Get merge_nested finally working: change nested tree iterators to take file_ids, and ensure the right branch is connected to in the merge logic. May not be suitable for shared repositories yet.
359
    def iter_references(self):
4370.3.2 by Ian Clatworthy
apply jam's review feedback
360
        if self.supports_tree_reference():
361
            for path, entry in self.iter_entries_by_dir():
362
                if entry.kind == 'tree-reference':
7350.2.1 by Jelmer Vernooij
Drop file_id return value from Tree.iter_references.
363
                    yield path
2100.3.27 by Aaron Bentley
Enable nested commits
364
7358.4.1 by Jelmer Vernooij
Add Tree.get_nested_tree.
365
    def get_nested_tree(self, path):
366
        """Open the nested tree at the specified path.
367
368
        :param path: Path from which to resolve tree reference.
369
        :return: A Tree object for the nested tree
370
        :raise MissingNestedTree: If the nested tree can not be resolved
371
        """
372
        raise NotImplementedError(self.get_nested_tree)
373
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
374
    def kind(self, path):
2255.2.159 by Martin Pool
reference-trees in dirstate pass all tests.
375
        raise NotImplementedError("Tree subclass %s must implement kind"
7143.15.2 by Jelmer Vernooij
Run autopep8.
376
                                  % self.__class__.__name__)
1465 by Robert Collins
Bugfix the new pull --clobber to not generate spurious conflicts.
377
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
378
    def stored_kind(self, path):
379
        """File kind stored for this path.
3146.8.4 by Aaron Bentley
Eliminate direct use of inventory from transform application
380
3146.8.15 by Aaron Bentley
Cleanup and docs
381
        May not match kind on disk for working trees.  Always available
382
        for versioned files, even when the file itself is missing.
3146.8.4 by Aaron Bentley
Eliminate direct use of inventory from transform application
383
        """
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
384
        return self.kind(path)
3146.8.4 by Aaron Bentley
Eliminate direct use of inventory from transform application
385
2776.1.7 by Robert Collins
* New method on ``bzrlib.tree.Tree`` ``path_content_summary`` provides a
386
    def path_content_summary(self, path):
387
        """Get a summary of the information about path.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
388
4595.11.2 by Martin Pool
Clarify contract of path_content_summary
389
        All the attributes returned are for the canonical form, not the
390
        convenient form (if content filters are in use.)
391
2776.1.7 by Robert Collins
* New method on ``bzrlib.tree.Tree`` ``path_content_summary`` provides a
392
        :param path: A relative path within the tree.
393
        :return: A tuple containing kind, size, exec, sha1-or-link.
394
            Kind is always present (see tree.kind()).
7195.5.1 by Martin
Fix remaining whitespace lint in codebase
395
            size is present if kind is file and the size of the
4595.11.13 by Martin Pool
Remove get_kind_and_executable_by_path; go back to using plain path_content_summary
396
                canonical form can be cheaply determined, None otherwise.
2776.1.7 by Robert Collins
* New method on ``bzrlib.tree.Tree`` ``path_content_summary`` provides a
397
            exec is None unless kind is file and the platform supports the 'x'
398
                bit.
399
            sha1-or-link is the link target if kind is symlink, or the sha1 if
400
                it can be obtained without reading the file.
401
        """
402
        raise NotImplementedError(self.path_content_summary)
403
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
404
    def get_reference_revision(self, path):
2255.2.158 by Martin Pool
Most of the integration of dirstate and subtree
405
        raise NotImplementedError("Tree subclass %s must implement "
406
                                  "get_reference_revision"
7143.15.2 by Jelmer Vernooij
Run autopep8.
407
                                  % self.__class__.__name__)
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
408
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
409
    def _comparison_data(self, entry, path):
2012.1.15 by Aaron Bentley
Minor tweaks
410
        """Return a tuple of kind, executable, stat_value for a file.
411
412
        entry may be None if there is no inventory entry for the file, but
413
        path must always be supplied.
414
415
        kind is None if there is no file present (even if an inventory id is
416
        present).  executable is False for non-file entries.
417
        """
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
418
        raise NotImplementedError(self._comparison_data)
419
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
420
    def get_file(self, path):
421
        """Return a file object for the file path in the tree.
2772.2.1 by Ian Clatworthy
(Ian Clatworthy) Quicker initial commit - skip SHAing twice & skip path lookup as we know it
422
        """
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
423
        raise NotImplementedError(self.get_file)
2255.7.36 by John Arbash Meinel
All trees should implement get_file_mtime()
424
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
425
    def get_file_with_stat(self, path):
426
        """Get a file handle and stat object for path.
4354.4.7 by Aaron Bentley
Move MutableTree.get_file_with_stat to Tree.get_file_with_stat.
427
428
        The default implementation returns (self.get_file, None) for backwards
429
        compatibility.
430
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
431
        :param path: The path of the file.
4354.4.7 by Aaron Bentley
Move MutableTree.get_file_with_stat to Tree.get_file_with_stat.
432
        :return: A tuple (file_handle, stat_value_or_None). If the tree has
433
            no stat facility, or need for a stat cache feedback during commit,
434
            it may return None for the second element of the tuple.
435
        """
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
436
        return (self.get_file(path), None)
4354.4.5 by Aaron Bentley
Ensure Tree.get_file_with_stat is provided.
437
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
438
    def get_file_text(self, path):
3774.1.1 by Aaron Bentley
Test Tree.get_file_text() and supply default implementation.
439
        """Return the byte content of a file.
440
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
441
        :param path: The path of the file.
6006.3.1 by Martin Pool
Start adding ContentFilterTree
442
443
        :returns: A single byte string for the whole file.
3774.1.1 by Aaron Bentley
Test Tree.get_file_text() and supply default implementation.
444
        """
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
445
        with self.get_file(path) as my_file:
3774.1.1 by Aaron Bentley
Test Tree.get_file_text() and supply default implementation.
446
            return my_file.read()
447
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
448
    def get_file_lines(self, path):
3774.1.2 by Aaron Bentley
Test Tree.get_file_lines, provide a default implementation
449
        """Return the content of a file, as lines.
450
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
451
        :param path: The path of the file.
3774.1.2 by Aaron Bentley
Test Tree.get_file_lines, provide a default implementation
452
        """
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
453
        return osutils.split_lines(self.get_file_text(path))
3774.1.2 by Aaron Bentley
Test Tree.get_file_lines, provide a default implementation
454
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
455
    def get_file_verifier(self, path, stat_value=None):
5906.1.2 by Jelmer Vernooij
Add Tree.get_file_verifier.
456
        """Return a verifier for a file.
457
458
        The default implementation returns a sha1.
459
460
        :param path: The path that this file can be found at.
461
            These must point to the same object.
462
        :param stat_value: Optional stat value for the object
463
        :return: Tuple with verifier name and verifier data
464
        """
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
465
        return ("SHA1", self.get_file_sha1(path, stat_value=stat_value))
5906.1.2 by Jelmer Vernooij
Add Tree.get_file_verifier.
466
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
467
    def get_file_sha1(self, path, stat_value=None):
5777.1.3 by Jelmer Vernooij
Add stub for Tree.get_file_sha1.
468
        """Return the SHA1 file for a file.
469
5906.1.4 by Jelmer Vernooij
Add InterTree.file_contents_match.
470
        :note: callers should use get_file_verifier instead
471
            where possible, as the underlying repository implementation may
472
            have quicker access to a non-sha1 verifier.
473
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
474
        :param path: The path that this file can be found at.
5883.1.2 by Jelmer Vernooij
Support stat_value argument to get_file_sha1
475
        :param stat_value: Optional stat value for the object
5777.1.3 by Jelmer Vernooij
Add stub for Tree.get_file_sha1.
476
        """
477
        raise NotImplementedError(self.get_file_sha1)
478
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
479
    def get_file_mtime(self, path):
2255.7.36 by John Arbash Meinel
All trees should implement get_file_mtime()
480
        """Return the modification time for a file.
481
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
482
        :param path: The path that this file can be found at.
2255.7.36 by John Arbash Meinel
All trees should implement get_file_mtime()
483
        """
484
        raise NotImplementedError(self.get_file_mtime)
485
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
486
    def get_file_size(self, path):
3363.3.4 by Aaron Bentley
Add get_file_size to Tree interface
487
        """Return the size of a file in bytes.
488
489
        This applies only to regular files.  If invoked on directories or
490
        symlinks, it will return None.
491
        """
492
        raise NotImplementedError(self.get_file_size)
493
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
494
    def is_executable(self, path):
5777.1.4 by Jelmer Vernooij
Stub for is_executable.
495
        """Check if a file is executable.
496
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
497
        :param path: The path that this file can be found at.
5777.1.4 by Jelmer Vernooij
Stub for is_executable.
498
        """
499
        raise NotImplementedError(self.is_executable)
500
2708.1.7 by Aaron Bentley
Rename extract_files_bytes to iter_files_bytes
501
    def iter_files_bytes(self, desired_files):
2708.1.6 by Aaron Bentley
Turn extract_files_bytes into an iterator
502
        """Iterate through file contents.
2708.1.1 by Aaron Bentley
Implement Tree.extract_files
503
2708.1.10 by Aaron Bentley
Update docstrings
504
        Files will not necessarily be returned in the order they occur in
505
        desired_files.  No specific order is guaranteed.
506
507
        Yields pairs of identifier, bytes_iterator.  identifier is an opaque
508
        value supplied by the caller as part of desired_files.  It should
509
        uniquely identify the file version in the caller's context.  (Examples:
510
        an index number or a TreeTransform trans_id.)
511
512
        bytes_iterator is an iterable of bytestrings for the file.  The
513
        kind of iterable and length of the bytestrings are unspecified, but for
514
        this implementation, it is a tuple containing a single bytestring with
515
        the complete text of the file.
516
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
517
        :param desired_files: a list of (path, identifier) pairs
2708.1.1 by Aaron Bentley
Implement Tree.extract_files
518
        """
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
519
        for path, identifier in desired_files:
2708.1.10 by Aaron Bentley
Update docstrings
520
            # We wrap the string in a tuple so that we can return an iterable
521
            # of bytestrings.  (Technically, a bytestring is also an iterable
522
            # of bytestrings, but iterating through each character is not
523
            # performant.)
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
524
            cur_file = (self.get_file_text(path),)
2708.1.6 by Aaron Bentley
Turn extract_files_bytes into an iterator
525
            yield identifier, cur_file
2708.1.1 by Aaron Bentley
Implement Tree.extract_files
526
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
527
    def get_symlink_target(self, path):
528
        """Get the target for a given path.
2255.2.134 by John Arbash Meinel
Add a tree-test for get_symlink_target
529
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
530
        It is assumed that the caller already knows that path is referencing
2255.2.134 by John Arbash Meinel
Add a tree-test for get_symlink_target
531
        a symlink.
5858.1.1 by Jelmer Vernooij
Support optional path argument to Tree.get_symlink_target.
532
        :param path: The path of the file.
2255.2.134 by John Arbash Meinel
Add a tree-test for get_symlink_target
533
        :return: The path the symlink points to.
534
        """
535
        raise NotImplementedError(self.get_symlink_target)
536
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
537
    def annotate_iter(self, path,
3224.1.2 by John Arbash Meinel
Updated the base Tree.annotate_iter() since all implemenations take an optional kwarg.
538
                      default_revision=_mod_revision.CURRENT_REVISION):
2818.2.1 by Ian Clatworthy
minor tree & dirstate code cleanups
539
        """Return an iterator of revision_id, line tuples.
1551.9.18 by Aaron Bentley
Updates from review comments
540
1551.9.16 by Aaron Bentley
Implement Tree.annotate_iter for RevisionTree and WorkingTree
541
        For working trees (and mutable trees in general), the special
542
        revision_id 'current:' will be used for lines that are new in this
543
        tree, e.g. uncommitted changes.
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
544
        :param path: The file to produce an annotated version from
3224.1.2 by John Arbash Meinel
Updated the base Tree.annotate_iter() since all implemenations take an optional kwarg.
545
        :param default_revision: For lines that don't match a basis, mark them
546
            with this revision id. Not all implementations will make use of
547
            this value.
1551.9.16 by Aaron Bentley
Implement Tree.annotate_iter for RevisionTree and WorkingTree
548
        """
549
        raise NotImplementedError(self.annotate_iter)
550
3363.9.1 by Aaron Bentley
Implement plan_merge, refactoring various bits
551
    def _iter_parent_trees(self):
552
        """Iterate through parent trees, defaulting to Tree.revision_tree."""
553
        for revision_id in self.get_parent_ids():
554
            try:
555
                yield self.revision_tree(revision_id)
556
            except errors.NoSuchRevisionInTree:
557
                yield self.repository.revision_tree(revision_id)
558
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
559
    def path2id(self, path):
560
        """Return the id for path in this tree."""
5777.3.1 by Jelmer Vernooij
Split InventoryTree out of Tree.
561
        raise NotImplementedError(self.path2id)
1 by mbp at sourcefrog
import from baz patch-364
562
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
563
    def is_versioned(self, path):
564
        """Check whether path is versioned.
565
566
        :param path: Path to check
567
        :return: boolean
568
        """
6856 by Jelmer Vernooij
Merge lp:~jelmer/brz/is-versioned.
569
        return self.path2id(path) is not None
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
570
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
571
    def find_related_paths_across_trees(self, paths, trees=[],
7143.15.2 by Jelmer Vernooij
Run autopep8.
572
                                        require_versioned=True):
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
573
        """Find related paths in tree corresponding to specified filenames in any
574
        of `lookup_trees`.
575
576
        All matches in all trees will be used, and all children of matched
577
        directories will be used.
578
579
        :param paths: The filenames to find related paths for (if None, returns
580
            None)
581
        :param trees: The trees to find file_ids within
582
        :param require_versioned: if true, all specified filenames must occur in
583
            at least one tree.
584
        :return: a set of paths for the specified filenames and their children
585
            in `tree`
586
        """
6885.5.4 by Jelmer Vernooij
Move paths2ids to InventoryTree.
587
        raise NotImplementedError(self.find_related_paths_across_trees)
3363.12.2 by Aaron Bentley
Implement tree.iter_children to instead of adjusting InventoryEntry handling
588
1543.1.1 by Denys Duchier
lock operations for trees - use them for diff
589
    def lock_read(self):
5200.3.6 by Robert Collins
Make all lock methods return Result objects, rather than lock_read returning self, as per John's review.
590
        """Lock this tree for multiple read only operations.
6468.3.1 by Jelmer Vernooij
Use iter_children in a couple more places.
591
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
592
        :return: A breezy.lock.LogicalLockResult.
5200.3.6 by Robert Collins
Make all lock methods return Result objects, rather than lock_read returning self, as per John's review.
593
        """
6754.8.3 by Jelmer Vernooij
Use context manager in decorators.
594
        return lock.LogicalLockResult(self.unlock)
1543.1.1 by Denys Duchier
lock operations for trees - use them for diff
595
1908.11.1 by Robert Collins
Add a new method ``Tree.revision_tree`` which allows access to cached
596
    def revision_tree(self, revision_id):
597
        """Obtain a revision tree for the revision revision_id.
598
599
        The intention of this method is to allow access to possibly cached
600
        tree data. Implementors of this method should raise NoSuchRevision if
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
601
        the tree is not locally available, even if they could obtain the
602
        tree via a repository or some other means. Callers are responsible
1908.11.1 by Robert Collins
Add a new method ``Tree.revision_tree`` which allows access to cached
603
        for finding the ultimate source for a revision tree.
604
605
        :param revision_id: The revision_id of the requested tree.
606
        :return: A Tree.
607
        :raises: NoSuchRevision if the tree cannot be obtained.
608
        """
609
        raise errors.NoSuchRevisionInTree(self, revision_id)
610
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
611
    def unknowns(self):
612
        """What files are present in this tree and unknown.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
613
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
614
        :return: an iterator over the unknown files.
615
        """
616
        return iter([])
617
1543.1.1 by Denys Duchier
lock operations for trees - use them for diff
618
    def unlock(self):
619
        pass
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
620
621
    def filter_unversioned_files(self, paths):
2255.7.62 by Robert Collins
Update the Tree.filter_unversioned_files docstring to reflect what the existing implementations actually do, and change the WorkingTree4 implementation to match a newly created test for it.
622
        """Filter out paths that are versioned.
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
623
624
        :return: set of paths.
625
        """
6974.1.1 by Jelmer Vernooij
Provide a sensible default implementaton of Tree.filter_unversioned_files.
626
        # NB: we specifically *don't* call self.has_filename, because for
627
        # WorkingTrees that can indicate files that exist on disk but that
628
        # are not versioned.
6974.1.2 by Jelmer Vernooij
Avoid unnecessary parentheses.
629
        return set(p for p in paths if not self.is_versioned(p))
1852.7.1 by Robert Collins
Move RevisionTree out of tree.py.
630
1852.15.3 by Robert Collins
Add a first-cut Tree.walkdirs method.
631
    def walkdirs(self, prefix=""):
632
        """Walk the contents of this tree from path down.
633
634
        This yields all the data about the contents of a directory at a time.
635
        After each directory has been yielded, if the caller has mutated the
636
        list to exclude some directories, they are then not descended into.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
637
1852.15.3 by Robert Collins
Add a first-cut Tree.walkdirs method.
638
        The data yielded is of the form:
1852.15.7 by Robert Collins
Start testing behaviour of unknowns in WorkingTree.walkdirs.
639
        ((directory-relpath, directory-path-from-root, directory-fileid),
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
640
        [(relpath, basename, kind, lstat, path_from_tree_root, file_id,
1852.15.7 by Robert Collins
Start testing behaviour of unknowns in WorkingTree.walkdirs.
641
          versioned_kind), ...]),
642
         - directory-relpath is the containing dirs relpath from prefix
643
         - directory-path-from-root is the containing dirs path from /
644
         - directory-fileid is the id of the directory if it is versioned.
1852.15.3 by Robert Collins
Add a first-cut Tree.walkdirs method.
645
         - relpath is the relative path within the subtree being walked.
646
         - basename is the basename
647
         - kind is the kind of the file now. If unknonwn then the file is not
648
           present within the tree - but it may be recorded as versioned. See
649
           versioned_kind.
650
         - lstat is the stat data *if* the file was statted.
651
         - path_from_tree_root is the path from the root of the tree.
2818.2.1 by Ian Clatworthy
minor tree & dirstate code cleanups
652
         - file_id is the file_id if the entry is versioned.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
653
         - versioned_kind is the kind of the file as last recorded in the
1852.15.3 by Robert Collins
Add a first-cut Tree.walkdirs method.
654
           versioning system. If 'unknown' the file is not versioned.
655
        One of 'kind' and 'versioned_kind' must not be 'unknown'.
656
657
        :param prefix: Start walking from prefix within the tree rather than
658
        at the root. This allows one to walk a subtree but get paths that are
659
        relative to a tree rooted higher up.
660
        :return: an iterator over the directory data.
661
        """
662
        raise NotImplementedError(self.walkdirs)
663
3368.2.45 by Ian Clatworthy
add and use supports_content_filtering API
664
    def supports_content_filtering(self):
665
        return False
666
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
667
    def _content_filter_stack(self, path=None):
3368.2.45 by Ian Clatworthy
add and use supports_content_filtering API
668
        """The stack of content filters for a path if filtering is supported.
3368.2.47 by Ian Clatworthy
merge bzr.dev r4042
669
3368.2.4 by Ian Clatworthy
make content filter lookup a tree responsibility
670
        Readers will be applied in first-to-last order.
671
        Writers will be applied in last-to-first order.
3368.2.5 by Ian Clatworthy
incorporate jameinel's review feedback
672
        Either the path or the file-id needs to be provided.
673
674
        :param path: path relative to the root of the tree
675
            or None if unknown
676
        :return: the list of filters - [] if there are none
3368.2.4 by Ian Clatworthy
make content filter lookup a tree responsibility
677
        """
3368.2.16 by Ian Clatworthy
add real implementation of Tree.get_filter_stack
678
        filter_pref_names = filters._get_registered_names()
679
        if len(filter_pref_names) == 0:
680
            return []
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
681
        prefs = next(self.iter_search_rules([path], filter_pref_names))
3368.2.30 by Ian Clatworthy
add -Dfilters support
682
        stk = filters._get_filter_stack_for(prefs)
683
        if 'filters' in debug.debug_flags:
7143.15.2 by Jelmer Vernooij
Run autopep8.
684
            trace.note(
685
                gettext("*** {0} content-filter: {1} => {2!r}").format(path, prefs, stk))
3368.2.30 by Ian Clatworthy
add -Dfilters support
686
        return stk
3368.2.4 by Ian Clatworthy
make content filter lookup a tree responsibility
687
3368.2.45 by Ian Clatworthy
add and use supports_content_filtering API
688
    def _content_filter_stack_provider(self):
689
        """A function that returns a stack of ContentFilters.
690
691
        The function takes a path (relative to the top of the tree) and a
692
        file-id as parameters.
693
694
        :return: None if content filtering is not supported by this tree.
695
        """
696
        if self.supports_content_filtering():
697
            return lambda path, file_id: \
7143.15.2 by Jelmer Vernooij
Run autopep8.
698
                self._content_filter_stack(path)
3368.2.45 by Ian Clatworthy
add and use supports_content_filtering API
699
        else:
700
            return None
701
3398.1.24 by Ian Clatworthy
make iter_search_rules a tree method
702
    def iter_search_rules(self, path_names, pref_names=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
703
                          _default_searcher=None):
3398.1.24 by Ian Clatworthy
make iter_search_rules a tree method
704
        """Find the preferences for filenames in a tree.
705
706
        :param path_names: an iterable of paths to find attributes for.
707
          Paths are given relative to the root of the tree.
708
        :param pref_names: the list of preferences to lookup - None for all
709
        :param _default_searcher: private parameter to assist testing - don't use
710
        :return: an iterator of tuple sequences, one per path-name.
711
          See _RulesSearcher.get_items for details on the tuple sequence.
712
        """
4324.4.1 by Marius Kruger
Make it possible to blackboxtest rules
713
        if _default_searcher is None:
714
            _default_searcher = rules._per_user_searcher
3398.1.24 by Ian Clatworthy
make iter_search_rules a tree method
715
        searcher = self._get_rules_searcher(_default_searcher)
716
        if searcher is not None:
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
717
            if pref_names is not None:
718
                for path in path_names:
719
                    yield searcher.get_selected_items(path, pref_names)
720
            else:
721
                for path in path_names:
722
                    yield searcher.get_items(path)
3398.1.24 by Ian Clatworthy
make iter_search_rules a tree method
723
724
    def _get_rules_searcher(self, default_searcher):
725
        """Get the RulesSearcher for this tree given the default one."""
726
        searcher = default_searcher
727
        return searcher
728
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
729
    def archive(self, format, name, root='', subdir=None,
730
                force_mtime=None):
6968.2.1 by Jelmer Vernooij
Add Tree.archive, which streams an archived version of a tree.
731
        """Create an archive of this tree.
732
6995 by Jelmer Vernooij
Merge lp:~jelmer/brz/hpss-archive.
733
        :param format: Format name (e.g. 'tar')
6968.2.1 by Jelmer Vernooij
Add Tree.archive, which streams an archived version of a tree.
734
        :param name: target file name
735
        :param root: Root directory name (or None)
736
        :param subdir: Subdirectory to export (or None)
737
        :return: Iterator over archive chunks
738
        """
6968.2.10 by Jelmer Vernooij
Review comments.
739
        from .archive import create_archive
6968.2.1 by Jelmer Vernooij
Add Tree.archive, which streams an archived version of a tree.
740
        with self.lock_read():
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
741
            return create_archive(format, self, name, root,
7143.15.2 by Jelmer Vernooij
Run autopep8.
742
                                  subdir, force_mtime=force_mtime)
6968.2.1 by Jelmer Vernooij
Add Tree.archive, which streams an archived version of a tree.
743
6929.3.3 by Jelmer Vernooij
Add Tree.versionable_kind.
744
    @classmethod
745
    def versionable_kind(cls, kind):
746
        """Check if this tree support versioning a specific file kind."""
747
        return (kind in ('file', 'directory', 'symlink', 'tree-reference'))
748
1852.7.1 by Robert Collins
Move RevisionTree out of tree.py.
749
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
750
class InterTree(InterObject):
751
    """This class represents operations taking place between two Trees.
752
753
    Its instances have methods like 'compare' and contain references to the
754
    source and target trees these operations are to be carried out on.
755
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
756
    Clients of breezy should not need to use InterTree directly, rather they
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
757
    should use the convenience methods on Tree such as 'Tree.compare()' which
758
    will pass through to InterTree as appropriate.
759
    """
760
4585.1.18 by Jelmer Vernooij
Add note saying that InterTree will not be tested if the from and to formats are not set.
761
    # Formats that will be used to test this InterTree. If both are
762
    # None, this InterTree will not be tested (e.g. because a complex
763
    # setup is required)
764
    _matching_from_tree_format = None
765
    _matching_to_tree_format = None
766
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
767
    _optimisers = []
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
768
5837.1.2 by Jelmer Vernooij
Register defaults as first optimiser for existing Inter objects.
769
    @classmethod
770
    def is_compatible(kls, source, target):
771
        # The default implementation is naive and uses the public API, so
772
        # it works for all trees.
773
        return True
774
6883.1.1 by Jelmer Vernooij
Avoid file id lookups.
775
    def _changes_from_entries(self, source_entry, target_entry, source_path,
776
                              target_path):
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
777
        """Generate a iter_changes tuple between source_entry and target_entry.
778
779
        :param source_entry: An inventory entry from self.source, or None.
780
        :param target_entry: An inventory entry from self.target, or None.
6883.1.1 by Jelmer Vernooij
Avoid file id lookups.
781
        :param source_path: The path of source_entry.
782
        :param target_path: The path of target_entry.
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
783
        :return: A tuple, item 0 of which is an iter_changes result tuple, and
784
            item 1 is True if there are any changes in the result tuple.
785
        """
786
        if source_entry is None:
787
            if target_entry is None:
788
                return None
789
            file_id = target_entry.file_id
790
        else:
791
            file_id = source_entry.file_id
792
        if source_entry is not None:
793
            source_versioned = True
794
            source_name = source_entry.name
795
            source_parent = source_entry.parent_id
796
            source_kind, source_executable, source_stat = \
797
                self.source._comparison_data(source_entry, source_path)
798
        else:
799
            source_versioned = False
800
            source_name = None
801
            source_parent = None
802
            source_kind = None
803
            source_executable = None
804
        if target_entry is not None:
805
            target_versioned = True
806
            target_name = target_entry.name
807
            target_parent = target_entry.parent_id
808
            target_kind, target_executable, target_stat = \
809
                self.target._comparison_data(target_entry, target_path)
810
        else:
811
            target_versioned = False
812
            target_name = None
813
            target_parent = None
814
            target_kind = None
815
            target_executable = None
816
        versioned = (source_versioned, target_versioned)
817
        kind = (source_kind, target_kind)
818
        changed_content = False
819
        if source_kind != target_kind:
820
            changed_content = True
821
        elif source_kind == 'file':
6883.7.1 by Jelmer Vernooij
Swap order of arguments to Tree.file_content_matches.
822
            if not self.file_content_matches(
6883.1.2 by Jelmer Vernooij
Fix order.
823
                    source_path, target_path,
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
824
                    source_stat, target_stat):
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
825
                changed_content = True
826
        elif source_kind == 'symlink':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
827
            if (self.source.get_symlink_target(source_path) !=
7143.16.21 by Jelmer Vernooij
Fix regressions.
828
                    self.target.get_symlink_target(target_path)):
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
829
                changed_content = True
6405.2.12 by Jelmer Vernooij
Fix tests.
830
        elif source_kind == 'tree-reference':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
831
            if (self.source.get_reference_revision(source_path)
7143.16.21 by Jelmer Vernooij
Fix regressions.
832
                    != self.target.get_reference_revision(target_path)):
7260.1.2 by Jelmer Vernooij
Fix flake8 issues.
833
                changed_content = True
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
834
        parent = (source_parent, target_parent)
835
        name = (source_name, target_name)
836
        executable = (source_executable, target_executable)
7143.15.2 by Jelmer Vernooij
Run autopep8.
837
        if (changed_content is not False or versioned[0] != versioned[1] or
838
            parent[0] != parent[1] or name[0] != name[1] or
839
                executable[0] != executable[1]):
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
840
            changes = True
841
        else:
842
            changes = False
7322.1.3 by Jelmer Vernooij
Simplify.
843
        return TreeChange(
844
            file_id, (source_path, target_path), changed_content,
845
            versioned, parent, name, kind, executable), changes
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
846
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
847
    def compare(self, want_unchanged=False, specific_files=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
848
                extra_trees=None, require_versioned=False, include_root=False,
849
                want_unversioned=False):
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
850
        """Return the changes from source to target.
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
851
852
        :return: A TreeDelta.
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
853
        :param specific_files: An optional list of file paths to restrict the
854
            comparison to. When mapping filenames to ids, all matches in all
855
            trees (including optional extra_trees) are used, and all children of
856
            matched directories are included.
857
        :param want_unchanged: An optional boolean requesting the inclusion of
858
            unchanged entries in the result.
859
        :param extra_trees: An optional list of additional trees to use when
860
            mapping the contents of specific_files (paths) to file_ids.
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
861
        :param require_versioned: An optional boolean (defaults to False). When
862
            supplied and True all the 'specific_files' must be versioned, or
863
            a PathsNotVersionedError will be thrown.
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
864
        :param want_unversioned: Scan for unversioned paths.
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
865
        """
2255.2.105 by Robert Collins
Unfuck InterTree.compare which I broke with the paths2ids implementation.
866
        trees = (self.source,)
1852.11.1 by Robert Collins
Deprecate compare_trees and move its body to InterTree.changes_from.
867
        if extra_trees is not None:
868
            trees = trees + tuple(extra_trees)
6754.8.16 by Jelmer Vernooij
Get rid of all uses of needs_read_lock
869
        with self.lock_read():
870
            return delta._compare_trees(self.source, self.target, want_unchanged,
7143.15.2 by Jelmer Vernooij
Run autopep8.
871
                                        specific_files, include_root, extra_trees=extra_trees,
872
                                        require_versioned=require_versioned,
873
                                        want_unversioned=want_unversioned)
2012.1.1 by Aaron Bentley
Implement change iterator
874
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
875
    def iter_changes(self, include_unchanged=False,
7143.15.2 by Jelmer Vernooij
Run autopep8.
876
                     specific_files=None, pb=None, extra_trees=[],
877
                     require_versioned=True, want_unversioned=False):
2012.1.1 by Aaron Bentley
Implement change iterator
878
        """Generate an iterator of changes between trees.
879
880
        A tuple is returned:
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
881
        (file_id, (path_in_source, path_in_target),
882
         changed_content, versioned, parent, name, kind,
2012.1.1 by Aaron Bentley
Implement change iterator
883
         executable)
884
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
885
        Changed_content is True if the file's content has changed.  This
886
        includes changes to its kind, and to a symlink's target.
2012.1.1 by Aaron Bentley
Implement change iterator
887
2012.1.15 by Aaron Bentley
Minor tweaks
888
        versioned, parent, name, kind, executable are tuples of (from, to).
889
        If a file is missing in a tree, its kind is None.
2012.1.1 by Aaron Bentley
Implement change iterator
890
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
891
        Iteration is done in parent-to-child order, relative to the target
892
        tree.
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
893
894
        There is no guarantee that all paths are in sorted order: the
895
        requirement to expand the search due to renames may result in children
896
        that should be found early being found late in the search, after
897
        lexically later results have been returned.
898
        :param require_versioned: Raise errors.PathsNotVersionedError if a
899
            path in the specific_files list is not versioned in one of
900
            source, target or extra_trees.
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
901
        :param specific_files: An optional list of file paths to restrict the
902
            comparison to. When mapping filenames to ids, all matches in all
903
            trees (including optional extra_trees) are used, and all children
904
            of matched directories are included. The parents in the target tree
905
            of the specific files up to and including the root of the tree are
906
            always evaluated for changes too.
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
907
        :param want_unversioned: Should unversioned files be returned in the
908
            output. An unversioned file is defined as one with (False, False)
909
            for the versioned pair.
2012.1.1 by Aaron Bentley
Implement change iterator
910
        """
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
911
        if not extra_trees:
7143.15.2 by Jelmer Vernooij
Run autopep8.
912
            extra_trees = []
6885.5.8 by Jelmer Vernooij
Remove interesting_ids support from merge.
913
        else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
914
            extra_trees = list(extra_trees)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
915
        # The ids of items we need to examine to insure delta consistency.
916
        precise_file_ids = set()
917
        changed_file_ids = []
2748.3.1 by Aaron Bentley
Start supporting [] for empty list
918
        if specific_files == []:
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
919
            target_specific_files = []
920
            source_specific_files = []
2748.3.1 by Aaron Bentley
Start supporting [] for empty list
921
        else:
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
922
            target_specific_files = self.target.find_related_paths_across_trees(
7143.15.2 by Jelmer Vernooij
Run autopep8.
923
                specific_files, [self.source] + extra_trees,
924
                require_versioned=require_versioned)
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
925
            source_specific_files = self.source.find_related_paths_across_trees(
7143.15.2 by Jelmer Vernooij
Run autopep8.
926
                specific_files, [self.target] + extra_trees,
927
                require_versioned=require_versioned)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
928
        if specific_files is not None:
929
            # reparented or added entries must have their parents included
930
            # so that valid deltas can be created. The seen_parents set
931
            # tracks the parents that we need to have.
932
            # The seen_dirs set tracks directory entries we've yielded.
933
            # After outputting version object in to_entries we set difference
934
            # the two seen sets and start checking parents.
935
            seen_parents = set()
936
            seen_dirs = set()
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
937
        if want_unversioned:
2748.3.1 by Aaron Bentley
Start supporting [] for empty list
938
            all_unversioned = sorted([(p.split('/'), p) for p in
7143.15.2 by Jelmer Vernooij
Run autopep8.
939
                                      self.target.extras()
940
                                      if specific_files is None or
941
                                      osutils.is_inside_any(specific_files, p)])
7206.3.3 by Jelmer Vernooij
Fix collections import.
942
            all_unversioned = deque(all_unversioned)
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
943
        else:
7206.3.3 by Jelmer Vernooij
Fix collections import.
944
            all_unversioned = deque()
2012.1.1 by Aaron Bentley
Implement change iterator
945
        to_paths = {}
3363.14.2 by Aaron Bentley
Get iter_changes running to completion
946
        from_entries_by_dir = list(self.source.iter_entries_by_dir(
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
947
            specific_files=source_specific_files))
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
948
        from_data = dict(from_entries_by_dir)
3363.14.2 by Aaron Bentley
Get iter_changes running to completion
949
        to_entries_by_dir = list(self.target.iter_entries_by_dir(
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
950
            specific_files=target_specific_files))
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
951
        path_equivs = find_previous_paths(
952
            self.target, self.source, [p for p, e in to_entries_by_dir])
1551.9.29 by Aaron Bentley
Optimize Tree._iter_changes with specific file_ids
953
        num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
954
        entry_count = 0
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
955
        # the unversioned path lookup only occurs on real trees - where there
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
956
        # can be extras. So the fake_entry is solely used to look up
957
        # executable it values when execute is not supported.
6929.3.2 by Jelmer Vernooij
Remove use of inventory in breezy.tree.
958
        fake_entry = TreeFile()
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
959
        for target_path, target_entry in to_entries_by_dir:
960
            while (all_unversioned and
7143.15.2 by Jelmer Vernooij
Run autopep8.
961
                   all_unversioned[0][0] < target_path.split('/')):
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
962
                unversioned_path = all_unversioned.popleft()
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
963
                target_kind, target_executable, target_stat = \
7143.15.2 by Jelmer Vernooij
Run autopep8.
964
                    self.target._comparison_data(
965
                        fake_entry, unversioned_path[1])
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
966
                yield TreeChange(
7322.1.3 by Jelmer Vernooij
Simplify.
967
                    None, (None, unversioned_path[1]), True, (False, False),
968
                    (None, None),
969
                    (None, unversioned_path[0][-1]),
970
                    (None, target_kind),
971
                    (None, target_executable))
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
972
            source_path = path_equivs[target_path]
973
            if source_path is not None:
974
                source_entry = from_data.get(source_path)
975
            else:
976
                source_entry = None
977
            result, changes = self._changes_from_entries(
978
                source_entry, target_entry, source_path=source_path, target_path=target_path)
979
            to_paths[result.file_id] = result.path[1]
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
980
            entry_count += 1
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
981
            if result.versioned[0]:
1551.9.29 by Aaron Bentley
Optimize Tree._iter_changes with specific file_ids
982
                entry_count += 1
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
983
            if pb is not None:
984
                pb.update('comparing files', entry_count, num_entries)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
985
            if changes or include_unchanged:
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
986
                if specific_files is not None:
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
987
                    precise_file_ids.add(result.parent_id[1])
988
                    changed_file_ids.append(result.file_id)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
989
                yield result
990
            # Ensure correct behaviour for reparented/added specific files.
991
            if specific_files is not None:
992
                # Record output dirs
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
993
                if result.kind[1] == 'directory':
994
                    seen_dirs.add(result.file_id)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
995
                # Record parents of reparented/added entries.
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
996
                if not result.versioned[0] or result.is_reparented():
997
                    seen_parents.add(result.parent_id[1])
2255.7.85 by Robert Collins
Teach _iter_changes to gather unversioned path details upon request.
998
        while all_unversioned:
999
            # yield any trailing unversioned paths
1000
            unversioned_path = all_unversioned.popleft()
1001
            to_kind, to_executable, to_stat = \
1002
                self.target._comparison_data(fake_entry, unversioned_path[1])
7322.1.1 by Jelmer Vernooij
Add TreeChange object.
1003
            yield TreeChange(
7322.1.3 by Jelmer Vernooij
Simplify.
1004
                None, (None, unversioned_path[1]), True, (False, False),
1005
                (None, None),
1006
                (None, unversioned_path[0][-1]),
1007
                (None, to_kind),
1008
                (None, to_executable))
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1009
        # Yield all remaining source paths
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
1010
        for path, from_entry in from_entries_by_dir:
2012.1.1 by Aaron Bentley
Implement change iterator
1011
            file_id = from_entry.file_id
1012
            if file_id in to_paths:
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1013
                # already returned
2012.1.1 by Aaron Bentley
Implement change iterator
1014
                continue
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
1015
            to_path = find_previous_path(self.source, self.target, path)
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
1016
            entry_count += 1
1017
            if pb is not None:
1018
                pb.update('comparing files', entry_count, num_entries)
2012.1.1 by Aaron Bentley
Implement change iterator
1019
            versioned = (True, False)
1020
            parent = (from_entry.parent_id, None)
1021
            name = (from_entry.name, None)
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
1022
            from_kind, from_executable, stat_value = \
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
1023
                self.source._comparison_data(from_entry, path)
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
1024
            kind = (from_kind, None)
2012.1.2 by Aaron Bentley
reimplement compare_trees
1025
            executable = (from_executable, None)
3619.4.1 by Robert Collins
Improve tests for the behaviour of Tree.iter_changes for missing paths that are only present in one tree, and fix found bugs. (Robert Collins)
1026
            changed_content = from_kind is not None
2012.1.1 by Aaron Bentley
Implement change iterator
1027
            # the parent's path is necessarily known at this point.
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1028
            changed_file_ids.append(file_id)
7322.1.5 by Jelmer Vernooij
Fix slice handling.
1029
            yield TreeChange(
1030
                file_id, (path, to_path), changed_content, versioned, parent,
1031
                name, kind, executable)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1032
        changed_file_ids = set(changed_file_ids)
6885.5.3 by Jelmer Vernooij
Add a Tree.find_related_paths_across_trees.
1033
        if specific_files is not None:
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1034
            for result in self._handle_precise_ids(precise_file_ids,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1035
                                                   changed_file_ids):
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1036
                yield result
1037
7296.7.2 by Jelmer Vernooij
Avoid call to id2path.
1038
    @staticmethod
1039
    def _get_entry(tree, path):
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1040
        """Get an inventory entry from a tree, with missing entries as None.
1041
1042
        If the tree raises NotImplementedError on accessing .inventory, then
1043
        this is worked around using iter_entries_by_dir on just the file id
1044
        desired.
1045
1046
        :param tree: The tree to lookup the entry in.
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1047
        :param path: The path to look up
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1048
        """
6885.6.5 by Jelmer Vernooij
Avoid more uses of specific_file_ids.
1049
        # No inventory available.
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1050
        try:
6885.6.5 by Jelmer Vernooij
Avoid more uses of specific_file_ids.
1051
            iterator = tree.iter_entries_by_dir(specific_files=[path])
6973.7.5 by Jelmer Vernooij
s/file/open.
1052
            return next(iterator)[1]
6885.6.5 by Jelmer Vernooij
Avoid more uses of specific_file_ids.
1053
        except StopIteration:
1054
            return None
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1055
1056
    def _handle_precise_ids(self, precise_file_ids, changed_file_ids,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1057
                            discarded_changes=None):
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1058
        """Fill out a partial iter_changes to be consistent.
1059
1060
        :param precise_file_ids: The file ids of parents that were seen during
1061
            the iter_changes.
1062
        :param changed_file_ids: The file ids of already emitted items.
1063
        :param discarded_changes: An optional dict of precalculated
1064
            iter_changes items which the partial iter_changes had not output
1065
            but had calculated.
1066
        :return: A generator of iter_changes items to output.
1067
        """
1068
        # process parents of things that had changed under the users
1069
        # requested paths to prevent incorrect paths or parent ids which
1070
        # aren't in the tree.
1071
        while precise_file_ids:
1072
            precise_file_ids.discard(None)
1073
            # Don't emit file_ids twice
1074
            precise_file_ids.difference_update(changed_file_ids)
1075
            if not precise_file_ids:
1076
                break
1077
            # If the there was something at a given output path in source, we
1078
            # have to include the entry from source in the delta, or we would
1079
            # be putting this entry into a used path.
1080
            paths = []
1081
            for parent_id in precise_file_ids:
1082
                try:
1083
                    paths.append(self.target.id2path(parent_id))
1084
                except errors.NoSuchId:
1085
                    # This id has been dragged in from the source by delta
1086
                    # expansion and isn't present in target at all: we don't
1087
                    # need to check for path collisions on it.
1088
                    pass
1089
            for path in paths:
1090
                old_id = self.source.path2id(path)
1091
                precise_file_ids.add(old_id)
1092
            precise_file_ids.discard(None)
1093
            current_ids = precise_file_ids
1094
            precise_file_ids = set()
1095
            # We have to emit all of precise_file_ids that have been altered.
1096
            # We may have to output the children of some of those ids if any
1097
            # directories have stopped being directories.
1098
            for file_id in current_ids:
1099
                # Examine file_id
1100
                if discarded_changes:
1101
                    result = discarded_changes.get(file_id)
6885.6.5 by Jelmer Vernooij
Avoid more uses of specific_file_ids.
1102
                    source_entry = None
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1103
                else:
1104
                    result = None
1105
                if result is None:
6883.1.4 by Jelmer Vernooij
Fix tests.
1106
                    try:
1107
                        source_path = self.source.id2path(file_id)
1108
                    except errors.NoSuchId:
1109
                        source_path = None
6885.6.5 by Jelmer Vernooij
Avoid more uses of specific_file_ids.
1110
                        source_entry = None
1111
                    else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1112
                        source_entry = self._get_entry(
1113
                            self.source, source_path)
6883.1.4 by Jelmer Vernooij
Fix tests.
1114
                    try:
1115
                        target_path = self.target.id2path(file_id)
1116
                    except errors.NoSuchId:
1117
                        target_path = None
6885.6.5 by Jelmer Vernooij
Avoid more uses of specific_file_ids.
1118
                        target_entry = None
1119
                    else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1120
                        target_entry = self._get_entry(
1121
                            self.target, target_path)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1122
                    result, changes = self._changes_from_entries(
6885.6.5 by Jelmer Vernooij
Avoid more uses of specific_file_ids.
1123
                        source_entry, target_entry, source_path, target_path)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1124
                else:
1125
                    changes = True
4570.2.5 by Robert Collins
Review feedback, including finding a bug with changes at the root.
1126
                # Get this parents parent to examine.
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
1127
                new_parent_id = result.parent_id[1]
4570.2.5 by Robert Collins
Review feedback, including finding a bug with changes at the root.
1128
                precise_file_ids.add(new_parent_id)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1129
                if changes:
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
1130
                    if (result.kind[0] == 'directory' and
1131
                            result.kind[1] != 'directory'):
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1132
                        # This stopped being a directory, the old children have
1133
                        # to be included.
6885.6.5 by Jelmer Vernooij
Avoid more uses of specific_file_ids.
1134
                        if source_entry is None:
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1135
                            # Reusing a discarded change.
7143.15.2 by Jelmer Vernooij
Run autopep8.
1136
                            source_entry = self._get_entry(
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
1137
                                self.source, result.path[0])
6471.1.7 by Jelmer Vernooij
merge bzr.dev.
1138
                        precise_file_ids.update(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1139
                            child.file_id
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
1140
                            for child in self.source.iter_child_entries(result.path[0]))
1141
                    changed_file_ids.add(result.file_id)
4570.2.3 by Robert Collins
Change the way iter_changes treats specific files to prevent InconsistentDeltas.
1142
                    yield result
3514.3.1 by John Arbash Meinel
Start working on a special walker that can iterate several trees at once.
1143
6754.8.16 by Jelmer Vernooij
Get rid of all uses of needs_read_lock
1144
    def file_content_matches(
6883.1.3 by Jelmer Vernooij
Add test, make file_id optional.
1145
            self, source_path, target_path,
6883.1.2 by Jelmer Vernooij
Fix order.
1146
            source_stat=None, target_stat=None):
5906.1.8 by Jelmer Vernooij
Tests.
1147
        """Check if two files are the same in the source and target trees.
1148
1149
        This only checks that the contents of the files are the same,
1150
        it does not touch anything else.
1151
6883.7.1 by Jelmer Vernooij
Swap order of arguments to Tree.file_content_matches.
1152
        :param source_path: Path of the file in the source tree
1153
        :param target_path: Path of the file in the target tree
5906.1.8 by Jelmer Vernooij
Tests.
1154
        :param source_stat: Optional stat value of the file in the source tree
1155
        :param target_stat: Optional stat value of the file in the target tree
1156
        :return: Boolean indicating whether the files have the same contents
1157
        """
6754.8.16 by Jelmer Vernooij
Get rid of all uses of needs_read_lock
1158
        with self.lock_read():
1159
            source_verifier_kind, source_verifier_data = (
7143.15.15 by Jelmer Vernooij
Merge trunk.
1160
                self.source.get_file_verifier(source_path, source_stat))
6754.8.16 by Jelmer Vernooij
Get rid of all uses of needs_read_lock
1161
            target_verifier_kind, target_verifier_data = (
1162
                self.target.get_file_verifier(
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1163
                    target_path, target_stat))
6754.8.16 by Jelmer Vernooij
Get rid of all uses of needs_read_lock
1164
            if source_verifier_kind == target_verifier_kind:
1165
                return (source_verifier_data == target_verifier_data)
1166
            # Fall back to SHA1 for now
1167
            if source_verifier_kind != "SHA1":
1168
                source_sha1 = self.source.get_file_sha1(
7325.1.1 by Jelmer Vernooij
Get rid of file_id arguments to get_file_sha1.
1169
                    source_path, source_stat)
6754.8.16 by Jelmer Vernooij
Get rid of all uses of needs_read_lock
1170
            else:
1171
                source_sha1 = source_verifier_data
1172
            if target_verifier_kind != "SHA1":
1173
                target_sha1 = self.target.get_file_sha1(
7325.1.1 by Jelmer Vernooij
Get rid of file_id arguments to get_file_sha1.
1174
                    target_path, target_stat)
6754.8.16 by Jelmer Vernooij
Get rid of all uses of needs_read_lock
1175
            else:
1176
                target_sha1 = target_verifier_data
1177
            return (source_sha1 == target_sha1)
3514.3.1 by John Arbash Meinel
Start working on a special walker that can iterate several trees at once.
1178
7143.15.2 by Jelmer Vernooij
Run autopep8.
1179
5837.1.2 by Jelmer Vernooij
Register defaults as first optimiser for existing Inter objects.
1180
InterTree.register_optimiser(InterTree)
1181
1182
6883.5.2 by Jelmer Vernooij
Add find_previous_paths call.
1183
def find_previous_paths(from_tree, to_tree, paths):
1184
    """Find previous tree paths.
1185
1186
    :param from_tree: From tree
1187
    :param to_tree: To tree
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
1188
    :param paths: Iterable over paths in from_tree to search for
6883.5.2 by Jelmer Vernooij
Add find_previous_paths call.
1189
    :return: Dictionary mapping from from_tree paths to paths in to_tree, or
1190
        None if there is no equivalent path.
1191
    """
1192
    ret = {}
1193
    for path in paths:
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
1194
        ret[path] = find_previous_path(from_tree, to_tree, path)
6883.5.2 by Jelmer Vernooij
Add find_previous_paths call.
1195
    return ret
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
1196
1197
6883.5.11 by Jelmer Vernooij
Fix tests.
1198
def find_previous_path(from_tree, to_tree, path, file_id=None):
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
1199
    """Find previous tree path.
1200
1201
    :param from_tree: From tree
1202
    :param to_tree: To tree
7324.2.1 by Jelmer Vernooij
Use find_previous_path in InterTree.iter_changes.
1203
    :param path: Path to search for (exists in from_tree)
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
1204
    :return: path in to_tree, or None if there is no equivalent path.
7350.5.1 by Jelmer Vernooij
Remove file_id from transform's create_from_tree, get filter tree paths by path.
1205
    :raise NoSuchFile: If the path doesn't exist in from_tree
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
1206
    """
6883.5.11 by Jelmer Vernooij
Fix tests.
1207
    if file_id is None:
1208
        file_id = from_tree.path2id(path)
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
1209
    if file_id is None:
1210
        raise errors.NoSuchFile(path)
1211
    try:
1212
        return to_tree.id2path(file_id)
1213
    except errors.NoSuchId:
1214
        return None
7104.3.3 by Jelmer Vernooij
Move get_canonical_paths to WorkingTree.
1215
1216
7104.3.4 by Jelmer Vernooij
Fix tests.
1217
def get_canonical_path(tree, path, normalize):
7104.3.3 by Jelmer Vernooij
Move get_canonical_paths to WorkingTree.
1218
    """Find the canonical path of an item, ignoring case.
1219
1220
    :param tree: Tree to traverse
1221
    :param path: Case-insensitive path to look up
7104.3.4 by Jelmer Vernooij
Fix tests.
1222
    :param normalize: Function to normalize a filename for comparison
7104.3.3 by Jelmer Vernooij
Move get_canonical_paths to WorkingTree.
1223
    :return: The canonical path
1224
    """
1225
    # go walkin...
1226
    cur_path = ''
1227
    bit_iter = iter(path.split("/"))
1228
    for elt in bit_iter:
7104.3.4 by Jelmer Vernooij
Fix tests.
1229
        lelt = normalize(elt)
7104.3.3 by Jelmer Vernooij
Move get_canonical_paths to WorkingTree.
1230
        new_path = None
1231
        try:
7192.5.2 by Jelmer Vernooij
Fixes.
1232
            for child in tree.iter_child_entries(cur_path):
7104.3.3 by Jelmer Vernooij
Move get_canonical_paths to WorkingTree.
1233
                try:
1234
                    if child.name == elt:
1235
                        # if we found an exact match, we can stop now; if
1236
                        # we found an approximate match we need to keep
1237
                        # searching because there might be an exact match
1238
                        # later.
1239
                        new_path = osutils.pathjoin(cur_path, child.name)
1240
                        break
7104.3.4 by Jelmer Vernooij
Fix tests.
1241
                    elif normalize(child.name) == lelt:
7104.3.3 by Jelmer Vernooij
Move get_canonical_paths to WorkingTree.
1242
                        new_path = osutils.pathjoin(cur_path, child.name)
1243
                except errors.NoSuchId:
1244
                    # before a change is committed we can see this error...
1245
                    continue
1246
        except errors.NotADirectory:
1247
            pass
1248
        if new_path:
1249
            cur_path = new_path
1250
        else:
1251
            # got to the end of this directory and no entries matched.
1252
            # Return what matched so far, plus the rest as specified.
1253
            cur_path = osutils.pathjoin(cur_path, elt, *list(bit_iter))
1254
            break
1255
    return cur_path