/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
70 by mbp at sourcefrog
Prepare for smart recursive add.
1
# Copyright (C) 2005 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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tree classes, representing directory at point in time.
18
"""
19
849 by Martin Pool
- Put files inside an exported tarball into a top-level directory rather than
20
import os
1196 by Martin Pool
- [WIP] retrieve historical texts from weaves
21
from cStringIO import StringIO
800 by Martin Pool
Merge John's import-speedup branch:
22
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
23
import bzrlib
2079.1.1 by John Arbash Meinel
Create a deprecated bzrlib.tree.RevisionTree() in favor of bzrlib.revisiontree.RevisionTree()
24
from bzrlib import (
25
    delta,
2012.1.8 by Aaron Bentley
Merge from bzr.dev
26
    osutils,
2079.1.1 by John Arbash Meinel
Create a deprecated bzrlib.tree.RevisionTree() in favor of bzrlib.revisiontree.RevisionTree()
27
    symbol_versioning,
28
    )
1852.11.1 by Robert Collins
Deprecate compare_trees and move its body to InterTree.changes_from.
29
from bzrlib.decorators import needs_read_lock
1196 by Martin Pool
- [WIP] retrieve historical texts from weaves
30
from bzrlib.errors import BzrError, BzrCheckError
1551.7.14 by Aaron Bentley
Use specified_file_ids instead of is_inside_any in compare_trees
31
from bzrlib import errors
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
32
from bzrlib.inventory import Inventory
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
33
from bzrlib.inter import InterObject
1732.1.1 by John Arbash Meinel
deprecating appendpath, it does exactly what pathjoin does
34
from bzrlib.osutils import fingerprint_file
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
35
import bzrlib.revision
36
from bzrlib.trace import mutter, note
1 by mbp at sourcefrog
import from baz patch-364
37
1852.5.1 by Robert Collins
Deprecate EmptyTree in favour of using Repository.revision_tree.
38
558 by Martin Pool
- All top-level classes inherit from object
39
class Tree(object):
1 by mbp at sourcefrog
import from baz patch-364
40
    """Abstract file tree.
41
42
    There are several subclasses:
43
    
44
    * `WorkingTree` exists as files on disk editable by the user.
45
46
    * `RevisionTree` is a tree as recorded at some point in the past.
47
48
    Trees contain an `Inventory` object, and also know how to retrieve
49
    file texts mentioned in the inventory, either from a working
50
    directory or from a store.
51
52
    It is possible for trees to contain files that are not described
53
    in their inventory or vice versa; for this use `filenames()`.
54
55
    Trees can be compared, etc, regardless of whether they are working
56
    trees or versioned trees.
57
    """
58
    
1852.9.6 by Robert Collins
Merge the change from Tree.compare to Tree.changes_from.
59
    def changes_from(self, other, want_unchanged=False, specific_files=None,
1731.1.33 by Aaron Bentley
Revert no-special-root changes
60
        extra_trees=None, require_versioned=False, include_root=False):
1852.8.8 by Robert Collins
change Tree.compare to Tree.changes_from - its better for the common case.
61
        """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.
62
63
        :param other: A tree to compare with.
64
        :param specific_files: An optional list of file paths to restrict the
65
            comparison to. When mapping filenames to ids, all matches in all
66
            trees (including optional extra_trees) are used, and all children of
67
            matched directories are included.
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
68
        :param want_unchanged: An optional boolean requesting the inclusion of
69
            unchanged entries in the result.
70
        :param extra_trees: An optional list of additional trees to use when
71
            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.
72
        :param require_versioned: An optional boolean (defaults to False). When
73
            supplied and True all the 'specific_files' must be versioned, or
74
            a PathsNotVersionedError will be thrown.
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
75
1852.8.4 by Robert Collins
Hook InterTree into Tree.
76
        The comparison will be performed by an InterTree object looked up on 
77
        self and other.
78
        """
1852.8.8 by Robert Collins
change Tree.compare to Tree.changes_from - its better for the common case.
79
        # Martin observes that Tree.changes_from returns a TreeDelta and this
80
        # may confuse people, because the class name of the returned object is
81
        # 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.
82
        return InterTree.get(other, self).compare(
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
83
            want_unchanged=want_unchanged,
84
            specific_files=specific_files,
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
85
            extra_trees=extra_trees,
86
            require_versioned=require_versioned,
1731.1.33 by Aaron Bentley
Revert no-special-root changes
87
            include_root=include_root
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
88
            )
2012.1.1 by Aaron Bentley
Implement change iterator
89
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
90
    def _iter_changes(self, from_tree, include_unchanged=False,
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
91
                     specific_file_ids=None, pb=None):
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
92
        intertree = InterTree.get(from_tree, self)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
93
        return intertree._iter_changes(include_unchanged,
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
94
                                       specific_file_ids, pb)
1852.8.4 by Robert Collins
Hook InterTree into Tree.
95
    
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
96
    def conflicts(self):
97
        """Get a list of the conflicts in the tree.
98
99
        Each conflict is an instance of bzrlib.conflicts.Conflict.
100
        """
101
        return []
102
103
    def get_parent_ids(self):
104
        """Get the parent ids for this tree. 
105
106
        :return: a list of parent ids. [] is returned to indicate
107
        a tree with no parents.
108
        :raises: BzrError if the parents are not known.
109
        """
110
        raise NotImplementedError(self.get_parent_ids)
111
    
1 by mbp at sourcefrog
import from baz patch-364
112
    def has_filename(self, filename):
113
        """True if the tree has given filename."""
114
        raise NotImplementedError()
115
1185.12.39 by abentley
Propogated has_or_had_id to Tree
116
    def has_id(self, file_id):
2294.1.10 by John Arbash Meinel
Switch all apis over to utf8 file ids. All tests pass
117
        file_id = osutils.safe_file_id(file_id)
1185.12.39 by abentley
Propogated has_or_had_id to Tree
118
        return self.inventory.has_id(file_id)
119
1852.6.9 by Robert Collins
Add more test trees to the tree-implementations tests.
120
    __contains__ = has_id
121
1185.12.39 by abentley
Propogated has_or_had_id to Tree
122
    def has_or_had_id(self, file_id):
2294.1.10 by John Arbash Meinel
Switch all apis over to utf8 file ids. All tests pass
123
        file_id = osutils.safe_file_id(file_id)
1185.12.39 by abentley
Propogated has_or_had_id to Tree
124
        if file_id == self.inventory.root.file_id:
1185.12.38 by abentley
semi-broke merge
125
            return True
1 by mbp at sourcefrog
import from baz patch-364
126
        return self.inventory.has_id(file_id)
127
462 by Martin Pool
- New form 'file_id in tree' to check if the file is present
128
    def __iter__(self):
129
        return iter(self.inventory)
130
1 by mbp at sourcefrog
import from baz patch-364
131
    def id2path(self, file_id):
2294.1.10 by John Arbash Meinel
Switch all apis over to utf8 file ids. All tests pass
132
        file_id = osutils.safe_file_id(file_id)
1 by mbp at sourcefrog
import from baz patch-364
133
        return self.inventory.id2path(file_id)
134
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
135
    def is_control_filename(self, filename):
136
        """True if filename is the name of a control file in this tree.
137
        
138
        :param filename: A filename within the tree. This is a relative path
139
        from the root of this tree.
140
141
        This is true IF and ONLY IF the filename is part of the meta data
142
        that bzr controls in this tree. I.E. a random .bzr directory placed
143
        on disk will not be a control file for this tree.
144
        """
145
        return self.bzrdir.is_control_filename(filename)
146
2255.2.15 by Robert Collins
Dirstate - truncate state file fixing bug in saving a smaller file, get more tree_implementation tests passing.
147
    @needs_read_lock
1551.9.29 by Aaron Bentley
Optimize Tree._iter_changes with specific file_ids
148
    def iter_entries_by_dir(self, specific_file_ids=None):
1852.6.9 by Robert Collins
Add more test trees to the tree-implementations tests.
149
        """Walk the tree in 'by_dir' order.
150
151
        This will yield each entry in the tree as a (path, entry) tuple. The
152
        order that they are yielded is: the contents of a directory are 
153
        preceeded by the parent of a directory, and all the contents of a 
154
        directory are grouped together.
155
        """
1551.9.29 by Aaron Bentley
Optimize Tree._iter_changes with specific file_ids
156
        return self.inventory.iter_entries_by_dir(
157
            specific_file_ids=specific_file_ids)
1852.6.9 by Robert Collins
Add more test trees to the tree-implementations tests.
158
2100.3.27 by Aaron Bentley
Enable nested commits
159
    def iter_reference_entries(self):
160
        for path, entry in self.iter_entries_by_dir():
161
            if entry.kind == 'tree-reference':
162
                yield path, entry
163
1465 by Robert Collins
Bugfix the new pull --clobber to not generate spurious conflicts.
164
    def kind(self, file_id):
165
        raise NotImplementedError("subclasses must implement kind")
166
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
167
    def get_reference_revision(self, entry, path=None):
168
        raise NotImplementedError("subclasses must implement "
169
                                  "get_reference_revision")
170
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
171
    def _comparison_data(self, entry, path):
2012.1.15 by Aaron Bentley
Minor tweaks
172
        """Return a tuple of kind, executable, stat_value for a file.
173
174
        entry may be None if there is no inventory entry for the file, but
175
        path must always be supplied.
176
177
        kind is None if there is no file present (even if an inventory id is
178
        present).  executable is False for non-file entries.
179
        """
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
180
        raise NotImplementedError(self._comparison_data)
181
2255.2.10 by Robert Collins
Now all tests matching dirstate pass - added generation of inventories for parent trees.
182
    def _file_size(self, entry, stat_value):
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
183
        raise NotImplementedError(self._file_size)
184
1 by mbp at sourcefrog
import from baz patch-364
185
    def _get_inventory(self):
186
        return self._inventory
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
187
    
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
188
    def get_file(self, file_id):
189
        """Return a file object for the file file_id in the tree."""
190
        raise NotImplementedError(self.get_file)
191
    
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
192
    def get_file_by_path(self, path):
193
        return self.get_file(self._inventory.path2id(path))
1 by mbp at sourcefrog
import from baz patch-364
194
1551.9.16 by Aaron Bentley
Implement Tree.annotate_iter for RevisionTree and WorkingTree
195
    def annotate_iter(self, file_id):
1551.9.18 by Aaron Bentley
Updates from review comments
196
        """Return an iterator of revision_id, line tuples
197
1551.9.16 by Aaron Bentley
Implement Tree.annotate_iter for RevisionTree and WorkingTree
198
        For working trees (and mutable trees in general), the special
199
        revision_id 'current:' will be used for lines that are new in this
200
        tree, e.g. uncommitted changes.
201
        :param file_id: The file to produce an annotated version from
202
        """
203
        raise NotImplementedError(self.annotate_iter)
204
1 by mbp at sourcefrog
import from baz patch-364
205
    inventory = property(_get_inventory,
206
                         doc="Inventory of this Tree")
207
208
    def _check_retrieved(self, ie, f):
1364 by Martin Pool
- remove extra verification of files retrieved from tree
209
        if not __debug__:
210
            return  
130 by mbp at sourcefrog
- fixup checks on retrieved files to cope with compression,
211
        fp = fingerprint_file(f)
212
        f.seek(0)
213
        
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
214
        if ie.text_size is not None:
131 by mbp at sourcefrog
check size and sha1 of files retrieved from the tree
215
            if ie.text_size != fp['size']:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
216
                raise BzrError("mismatched size for file %r in %r" % (ie.file_id, self._store),
1 by mbp at sourcefrog
import from baz patch-364
217
                        ["inventory expects %d bytes" % ie.text_size,
130 by mbp at sourcefrog
- fixup checks on retrieved files to cope with compression,
218
                         "file is actually %d bytes" % fp['size'],
1 by mbp at sourcefrog
import from baz patch-364
219
                         "store is probably damaged/corrupt"])
220
130 by mbp at sourcefrog
- fixup checks on retrieved files to cope with compression,
221
        if ie.text_sha1 != fp['sha1']:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
222
            raise BzrError("wrong SHA-1 for file %r in %r" % (ie.file_id, self._store),
1 by mbp at sourcefrog
import from baz patch-364
223
                    ["inventory expects %s" % ie.text_sha1,
130 by mbp at sourcefrog
- fixup checks on retrieved files to cope with compression,
224
                     "file is actually %s" % fp['sha1'],
1 by mbp at sourcefrog
import from baz patch-364
225
                     "store is probably damaged/corrupt"])
226
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
227
    def path2id(self, path):
228
        """Return the id for path in this tree."""
229
        return self._inventory.path2id(path)
1 by mbp at sourcefrog
import from baz patch-364
230
2255.2.101 by Robert Collins
Finish making Tree.ids2paths support the file_ids_across_trees api.
231
    def paths2ids(self, paths, trees=[], require_versioned=True):
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
232
        """Return all the ids that can be reached by walking from paths.
233
        
234
        Each path is looked up in each this tree and any extras provided in
235
        trees, and this is repeated recursively: the children in an extra tree
236
        of a directory that has been renamed under a provided path in this tree
237
        are all returned, even if none exist until a provided path in this
238
        tree, and vice versa.
2255.2.101 by Robert Collins
Finish making Tree.ids2paths support the file_ids_across_trees api.
239
240
        :param paths: An iterable of paths to start converting to ids from.
2255.2.104 by Robert Collins
Add WorkingTree4.paths2ids which is inventory-usage free if the trees being examined are in the dirstate.
241
            Alternatively, if paths is None, no ids should be calculated and None
242
            will be returned. This is offered to make calling the api unconditional
243
            for code that *might* take a list of files.
2255.2.101 by Robert Collins
Finish making Tree.ids2paths support the file_ids_across_trees api.
244
        :param trees: Additional trees to consider.
245
        :param require_versioned: If False, do not raise NotVersionedError if
246
            an element of paths is not versioned in this tree and all of trees.
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
247
        """
2255.2.105 by Robert Collins
Unfuck InterTree.compare which I broke with the paths2ids implementation.
248
        return find_ids_across_trees(paths, [self] + list(trees), require_versioned)
2255.2.100 by Robert Collins
Create a paths2ids api to replace find_ids_across_trees, with tests.
249
1196 by Martin Pool
- [WIP] retrieve historical texts from weaves
250
    def print_file(self, file_id):
251
        """Print file with id `file_id` to stdout."""
2294.1.10 by John Arbash Meinel
Switch all apis over to utf8 file ids. All tests pass
252
        file_id = osutils.safe_file_id(file_id)
176 by mbp at sourcefrog
New cat command contributed by janmar.
253
        import sys
1196 by Martin Pool
- [WIP] retrieve historical texts from weaves
254
        sys.stdout.write(self.get_file_text(file_id))
1543.1.1 by Denys Duchier
lock operations for trees - use them for diff
255
256
    def lock_read(self):
257
        pass
258
1908.11.1 by Robert Collins
Add a new method ``Tree.revision_tree`` which allows access to cached
259
    def revision_tree(self, revision_id):
260
        """Obtain a revision tree for the revision revision_id.
261
262
        The intention of this method is to allow access to possibly cached
263
        tree data. Implementors of this method should raise NoSuchRevision if
264
        the tree is not locally available, even if they could obtain the 
265
        tree via a repository or some other means. Callers are responsible 
266
        for finding the ultimate source for a revision tree.
267
268
        :param revision_id: The revision_id of the requested tree.
269
        :return: A Tree.
270
        :raises: NoSuchRevision if the tree cannot be obtained.
271
        """
272
        raise errors.NoSuchRevisionInTree(self, revision_id)
273
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
274
    def unknowns(self):
275
        """What files are present in this tree and unknown.
276
        
277
        :return: an iterator over the unknown files.
278
        """
279
        return iter([])
280
1543.1.1 by Denys Duchier
lock operations for trees - use them for diff
281
    def unlock(self):
282
        pass
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
283
284
    def filter_unversioned_files(self, paths):
285
        """Filter out paths that are not versioned.
286
287
        :return: set of paths.
288
        """
1658.1.10 by Martin Pool
diff on unversiond files should give an error (Malone #3619)
289
        # NB: we specifically *don't* call self.has_filename, because for
290
        # WorkingTrees that can indicate files that exist on disk but that 
291
        # are not versioned.
292
        pred = self.inventory.has_filename
293
        return set((p for p in paths if not pred(p)))
1852.7.1 by Robert Collins
Move RevisionTree out of tree.py.
294
1852.15.3 by Robert Collins
Add a first-cut Tree.walkdirs method.
295
    def walkdirs(self, prefix=""):
296
        """Walk the contents of this tree from path down.
297
298
        This yields all the data about the contents of a directory at a time.
299
        After each directory has been yielded, if the caller has mutated the
300
        list to exclude some directories, they are then not descended into.
301
        
302
        The data yielded is of the form:
1852.15.7 by Robert Collins
Start testing behaviour of unknowns in WorkingTree.walkdirs.
303
        ((directory-relpath, directory-path-from-root, directory-fileid),
1852.15.3 by Robert Collins
Add a first-cut Tree.walkdirs method.
304
        [(relpath, basename, kind, lstat, path_from_tree_root, file_id, 
1852.15.7 by Robert Collins
Start testing behaviour of unknowns in WorkingTree.walkdirs.
305
          versioned_kind), ...]),
306
         - directory-relpath is the containing dirs relpath from prefix
307
         - directory-path-from-root is the containing dirs path from /
308
         - 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.
309
         - relpath is the relative path within the subtree being walked.
310
         - basename is the basename
311
         - kind is the kind of the file now. If unknonwn then the file is not
312
           present within the tree - but it may be recorded as versioned. See
313
           versioned_kind.
314
         - lstat is the stat data *if* the file was statted.
315
         - path_from_tree_root is the path from the root of the tree.
316
         - file_id is the file_id is the entry is versioned.
317
         - versioned_kind is the kind of the file as last recorded in the 
318
           versioning system. If 'unknown' the file is not versioned.
319
        One of 'kind' and 'versioned_kind' must not be 'unknown'.
320
321
        :param prefix: Start walking from prefix within the tree rather than
322
        at the root. This allows one to walk a subtree but get paths that are
323
        relative to a tree rooted higher up.
324
        :return: an iterator over the directory data.
325
        """
326
        raise NotImplementedError(self.walkdirs)
327
1852.7.1 by Robert Collins
Move RevisionTree out of tree.py.
328
1 by mbp at sourcefrog
import from baz patch-364
329
class EmptyTree(Tree):
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
330
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
331
    def __init__(self):
1731.1.33 by Aaron Bentley
Revert no-special-root changes
332
        self._inventory = Inventory(root_id=None)
2079.1.1 by John Arbash Meinel
Create a deprecated bzrlib.tree.RevisionTree() in favor of bzrlib.revisiontree.RevisionTree()
333
        symbol_versioning.warn('EmptyTree is deprecated as of bzr 0.9 please'
334
                               ' use repository.revision_tree instead.',
335
                               DeprecationWarning, stacklevel=2)
1 by mbp at sourcefrog
import from baz patch-364
336
1773.2.1 by Robert Collins
Teach all trees about unknowns, conflicts and get_parent_ids.
337
    def get_parent_ids(self):
338
        return []
339
1092.2.6 by Robert Collins
symlink support updated to work
340
    def get_symlink_target(self, file_id):
341
        return None
342
1 by mbp at sourcefrog
import from baz patch-364
343
    def has_filename(self, filename):
344
        return False
345
1907.1.4 by Aaron Bentley
Restore RootEntry, but mark it deprecated, restore EmptyTree.kind
346
    def kind(self, file_id):
2294.1.10 by John Arbash Meinel
Switch all apis over to utf8 file ids. All tests pass
347
        file_id = osutils.safe_file_id(file_id)
1907.1.4 by Aaron Bentley
Restore RootEntry, but mark it deprecated, restore EmptyTree.kind
348
        assert self._inventory[file_id].kind == "directory"
349
        return "directory"
350
1731.1.56 by Aaron Bentley
Fix EmptyTree's default include_root
351
    def list_files(self, include_root=False):
1732.1.14 by John Arbash Meinel
Some speedups by not calling pathjoin()
352
        return iter([])
1 by mbp at sourcefrog
import from baz patch-364
353
    
974.1.12 by aaron.bentley at utoronto
Switched from text-id to hashcache for merge optimization
354
    def __contains__(self, file_id):
2294.1.10 by John Arbash Meinel
Switch all apis over to utf8 file ids. All tests pass
355
        file_id = osutils.safe_file_id(file_id)
1711.9.11 by John Arbash Meinel
change return foo in bar to return (foo in bar)
356
        return (file_id in self._inventory)
974.1.12 by aaron.bentley at utoronto
Switched from text-id to hashcache for merge optimization
357
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
358
    def get_file_sha1(self, file_id, path=None, stat_value=None):
974.1.14 by aaron.bentley at utoronto
Fixed bugs in merge optimization
359
        return None
360
361
1 by mbp at sourcefrog
import from baz patch-364
362
######################################################################
363
# diff
364
365
# TODO: Merge these two functions into a single one that can operate
366
# on either a whole tree or a set of files.
367
368
# TODO: Return the diff in order by filename, not by category or in
369
# random order.  Can probably be done by lock-stepping through the
370
# filenames from both trees.
371
372
373
def file_status(filename, old_tree, new_tree):
374
    """Return single-letter status, old and new names for a file.
375
376
    The complexity here is in deciding how to represent renames;
377
    many complex cases are possible.
378
    """
379
    old_inv = old_tree.inventory
380
    new_inv = new_tree.inventory
381
    new_id = new_inv.path2id(filename)
382
    old_id = old_inv.path2id(filename)
383
384
    if not new_id and not old_id:
385
        # easy: doesn't exist in either; not versioned at all
386
        if new_tree.is_ignored(filename):
387
            return 'I', None, None
388
        else:
389
            return '?', None, None
390
    elif new_id:
391
        # There is now a file of this name, great.
392
        pass
393
    else:
394
        # There is no longer a file of this name, but we can describe
395
        # what happened to the file that used to have
396
        # this name.  There are two possibilities: either it was
397
        # deleted entirely, or renamed.
398
        assert old_id
399
        if new_inv.has_id(old_id):
400
            return 'X', old_inv.id2path(old_id), new_inv.id2path(old_id)
401
        else:
402
            return 'D', old_inv.id2path(old_id), None
403
404
    # if the file_id is new in this revision, it is added
405
    if new_id and not old_inv.has_id(new_id):
406
        return 'A'
407
408
    # if there used to be a file of this name, but that ID has now
409
    # disappeared, it is deleted
410
    if old_id and not new_inv.has_id(old_id):
411
        return 'D'
412
413
    return 'wtf?'
414
415
    
416
164 by mbp at sourcefrog
new 'renames' command
417
def find_renames(old_inv, new_inv):
418
    for file_id in old_inv:
419
        if file_id not in new_inv:
420
            continue
421
        old_name = old_inv.id2path(file_id)
422
        new_name = new_inv.id2path(file_id)
423
        if old_name != new_name:
424
            yield (old_name, new_name)
425
            
678 by Martin Pool
- export to tarballs
426
1551.7.22 by Aaron Bentley
Changes from review
427
def find_ids_across_trees(filenames, trees, require_versioned=True):
428
    """Find the ids corresponding to specified filenames.
429
    
430
    All matches in all trees will be used, and all children of matched
431
    directories will be used.
432
1551.10.7 by Aaron Bentley
Use new-style output for status
433
    :param filenames: The filenames to find file_ids for (if None, returns
434
        None)
1551.7.22 by Aaron Bentley
Changes from review
435
    :param trees: The trees to find file_ids within
436
    :param require_versioned: if true, all specified filenames must occur in
437
    at least one tree.
438
    :return: a set of file ids for the specified filenames and their children.
439
    """
440
    if not filenames:
441
        return None
2255.2.82 by Robert Collins
various notes about find_ids_across_trees
442
    specified_path_ids = _find_ids_across_trees(filenames, trees,
443
        require_versioned)
444
    return _find_children_across_trees(specified_path_ids, trees)
445
#    specified_ids = [id for path, id in _find_path_ids_across_trees(filenames, trees, require_versioned)]
446
#    return _find_children_across_trees(specified_ids, trees)
447
448
def find_path_ids_across_trees(filenames, trees, require_versioned=True):
449
    """Find the paths and ids corresponding to specified filenames.
450
    
451
    All matches in all trees will be used, and all children of matched
452
    directories will be included
453
454
    :param filenames: The filenames to find file_ids for
455
    :param trees: The trees to find file_ids within
456
    :param require_versioned: if true, all specified filenames must occur in
457
        at least one tree.
458
    :return: a set of (path, file ids) for the specified filenames and their
459
        children. The returned path is the path of the id in the first tree
460
        that contains it. This matters when files have been moved 
461
    """
462
    if not filenames:
463
        return set()
464
    # This function needs to know the ids for filenames in all trees, then
465
    # search for those same files and children in all the other trees.
466
    # it is complicated by the same path in two trees being able to have
467
    # different ids, which might both be present in both trees.
468
    # consider two trees, which have had 'mv foo bar' and 'mv baz foo' done
469
    # in this case, a diff of 'foo' should should changes to both the current
470
    # 'bar' and the current 'foo' which was baz. Its arguable that if 
471
    # the situation is 'mv parent/foo bar' and 'mv baz parent/foo', that 
472
    # we should return the current bar and the current parent/foo' - at the 
473
    # moment we do, but we loop around all ids and all trees: I*T checks.
474
    
475
    # Updating this algorithm to be fast in the common case:
476
    # nothing has moved, all files have the same id in parent, child and there
477
    # are only two trees (or one is working tree and the others are parents).
478
    # walk the dirstate. as we find each path, gather the paths of that
479
    # id in all trees. add a mapping from the id to the path in those trees.
480
    # now lookup children by id, again in all trees; for these trees that
481
    # nothing has moved in, the id->path mapping will allow us to find the
482
    # parent trivially. To answer 'has anything been moved' in one of the
483
    # dirstate parent trees though, we will need to stare harder at it.
484
485
    #  Now, given a path index, that is trivial for any one tree, and given
486
    #  that we can ask for additional data from a dirstate tree, its a single
487
    #  pass, though it will require scanning the entire tree to find paths
488
    #  that were at the current location.
489
    # ideal results?: There are three things: tree, path, id. Pathologically
490
    # we can have completely disjoint ids for each tree; but we cannot have 
491
    # disjoin paths for each tree, except if we scan each tree for the 
492
    # different ids from other trees.
493
494
    specified_path_ids = _find_ids_across_trees(filenames, trees,
495
        require_versioned)
496
    return _find_path_id_children_across_trees(specified_path_ids, trees)
497
498
499
def _find_ids_across_trees(filenames, trees, require_versioned):
1551.7.22 by Aaron Bentley
Changes from review
500
    """Find the ids corresponding to specified filenames.
501
    
2255.2.82 by Robert Collins
various notes about find_ids_across_trees
502
    All matches in all trees will be used, but subdirectories are not scanned.
1551.7.22 by Aaron Bentley
Changes from review
503
1551.7.14 by Aaron Bentley
Use specified_file_ids instead of is_inside_any in compare_trees
504
    :param filenames: The filenames to find file_ids for
505
    :param trees: The trees to find file_ids within
1551.7.16 by Aaron Bentley
Fix docs
506
    :param require_versioned: if true, all specified filenames must occur in
2255.2.82 by Robert Collins
various notes about find_ids_across_trees
507
        at least one tree.
508
    :return: a set of (path, file ids) for the specified filenames
1551.7.14 by Aaron Bentley
Use specified_file_ids instead of is_inside_any in compare_trees
509
    """
1551.7.17 by Aaron Bentley
Switch to PathsNotVersioned, accept extra_trees
510
    not_versioned = []
1551.7.18 by Aaron Bentley
Indentation and documentation fixes
511
    interesting_ids = set()
512
    for tree_path in filenames:
513
        not_found = True
514
        for tree in trees:
2255.2.82 by Robert Collins
various notes about find_ids_across_trees
515
            file_id = tree.path2id(tree_path)
1551.7.18 by Aaron Bentley
Indentation and documentation fixes
516
            if file_id is not None:
517
                interesting_ids.add(file_id)
518
                not_found = False
519
        if not_found:
520
            not_versioned.append(tree_path)
1551.7.22 by Aaron Bentley
Changes from review
521
    if len(not_versioned) > 0 and require_versioned:
522
        raise errors.PathsNotVersionedError(not_versioned)
523
    return interesting_ids
524
525
526
def _find_children_across_trees(specified_ids, trees):
527
    """Return a set including specified ids and their children
1551.7.18 by Aaron Bentley
Indentation and documentation fixes
528
    
1551.7.22 by Aaron Bentley
Changes from review
529
    All matches in all trees will be used.
530
531
    :param trees: The trees to find file_ids within
532
    :return: a set containing all specified ids and their children 
533
    """
534
    interesting_ids = set(specified_ids)
1551.7.18 by Aaron Bentley
Indentation and documentation fixes
535
    pending = interesting_ids
536
    # now handle children of interesting ids
537
    # we loop so that we handle all children of each id in both trees
538
    while len(pending) > 0:
539
        new_pending = set()
540
        for file_id in pending:
1551.7.14 by Aaron Bentley
Use specified_file_ids instead of is_inside_any in compare_trees
541
            for tree in trees:
2255.2.82 by Robert Collins
various notes about find_ids_across_trees
542
                if not tree.has_id(file_id):
1551.7.18 by Aaron Bentley
Indentation and documentation fixes
543
                    continue
544
                entry = tree.inventory[file_id]
545
                for child in getattr(entry, 'children', {}).itervalues():
546
                    if child.file_id not in interesting_ids:
547
                        new_pending.add(child.file_id)
548
        interesting_ids.update(new_pending)
549
        pending = new_pending
1551.7.14 by Aaron Bentley
Use specified_file_ids instead of is_inside_any in compare_trees
550
    return interesting_ids
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
551
552
553
class InterTree(InterObject):
554
    """This class represents operations taking place between two Trees.
555
556
    Its instances have methods like 'compare' and contain references to the
557
    source and target trees these operations are to be carried out on.
558
559
    clients of bzrlib should not need to use InterTree directly, rather they
560
    should use the convenience methods on Tree such as 'Tree.compare()' which
561
    will pass through to InterTree as appropriate.
562
    """
563
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
564
    _optimisers = []
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
565
1852.11.1 by Robert Collins
Deprecate compare_trees and move its body to InterTree.changes_from.
566
    @needs_read_lock
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
567
    def compare(self, want_unchanged=False, specific_files=None,
1731.1.33 by Aaron Bentley
Revert no-special-root changes
568
        extra_trees=None, require_versioned=False, include_root=False):
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
569
        """Return the changes from source to target.
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
570
571
        :return: A TreeDelta.
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
572
        :param specific_files: An optional list of file paths to restrict the
573
            comparison to. When mapping filenames to ids, all matches in all
574
            trees (including optional extra_trees) are used, and all children of
575
            matched directories are included.
576
        :param want_unchanged: An optional boolean requesting the inclusion of
577
            unchanged entries in the result.
578
        :param extra_trees: An optional list of additional trees to use when
579
            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.
580
        :param require_versioned: An optional boolean (defaults to False). When
581
            supplied and True all the 'specific_files' must be versioned, or
582
            a PathsNotVersionedError will be thrown.
1852.8.3 by Robert Collins
Implement an InterTreeTestProvider and a trivial test_compare test case.
583
        """
2255.2.82 by Robert Collins
various notes about find_ids_across_trees
584
        # NB: show_status depends on being able to pass in non-versioned files
585
        # and report them as unknown
2255.2.105 by Robert Collins
Unfuck InterTree.compare which I broke with the paths2ids implementation.
586
        trees = (self.source,)
1852.11.1 by Robert Collins
Deprecate compare_trees and move its body to InterTree.changes_from.
587
        if extra_trees is not None:
588
            trees = trees + tuple(extra_trees)
2255.2.102 by Robert Collins
Use Tree.path2ids in status operations.
589
        # target is usually the newer tree:
2255.2.105 by Robert Collins
Unfuck InterTree.compare which I broke with the paths2ids implementation.
590
        specific_file_ids = self.target.paths2ids(specific_files, trees,
2255.2.102 by Robert Collins
Use Tree.path2ids in status operations.
591
            require_versioned=require_versioned)
1852.11.1 by Robert Collins
Deprecate compare_trees and move its body to InterTree.changes_from.
592
        if specific_files and not specific_file_ids:
593
            # All files are unversioned, so just return an empty delta
594
            # _compare_trees would think we want a complete delta
595
            return delta.TreeDelta()
596
        return delta._compare_trees(self.source, self.target, want_unchanged,
1910.2.56 by Aaron Bentley
More work on bundles
597
            specific_file_ids, include_root)
2012.1.1 by Aaron Bentley
Implement change iterator
598
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
599
    def _iter_changes(self, include_unchanged=False,
600
                      specific_file_ids=None, pb=None):
2012.1.1 by Aaron Bentley
Implement change iterator
601
        """Generate an iterator of changes between trees.
602
603
        A tuple is returned:
604
        (file_id, path, changed_content, versioned, parent, name, kind,
605
         executable)
606
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
607
        Path is relative to the target tree.  changed_content is True if the
608
        file's content has changed.  This includes changes to its kind, and to
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
609
        a symlink's target.
2012.1.1 by Aaron Bentley
Implement change iterator
610
2012.1.15 by Aaron Bentley
Minor tweaks
611
        versioned, parent, name, kind, executable are tuples of (from, to).
612
        If a file is missing in a tree, its kind is None.
2012.1.1 by Aaron Bentley
Implement change iterator
613
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
614
        Iteration is done in parent-to-child order, relative to the target
615
        tree.
2012.1.1 by Aaron Bentley
Implement change iterator
616
        """
617
        to_paths = {}
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
618
        from_entries_by_dir = list(self.source.inventory.iter_entries_by_dir(
1551.9.29 by Aaron Bentley
Optimize Tree._iter_changes with specific file_ids
619
            specific_file_ids=specific_file_ids))
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
620
        from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
621
        to_entries_by_dir = list(self.target.inventory.iter_entries_by_dir(
1551.9.31 by Aaron Bentley
Handle to_paths correctly when parent of file is not in specified_ids
622
            specific_file_ids=specific_file_ids))
1551.9.29 by Aaron Bentley
Optimize Tree._iter_changes with specific file_ids
623
        num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
624
        entry_count = 0
625
        for to_path, to_entry in to_entries_by_dir:
2012.1.1 by Aaron Bentley
Implement change iterator
626
            file_id = to_entry.file_id
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
627
            to_paths[file_id] = to_path
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
628
            entry_count += 1
2012.1.1 by Aaron Bentley
Implement change iterator
629
            changed_content = False
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
630
            from_path, from_entry = from_data.get(file_id, (None, None))
631
            from_versioned = (from_entry is not None)
632
            if from_entry is not None:
633
                from_versioned = True
634
                from_name = from_entry.name
2012.1.1 by Aaron Bentley
Implement change iterator
635
                from_parent = from_entry.parent_id
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
636
                from_kind, from_executable, from_stat = \
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
637
                    self.source._comparison_data(from_entry, from_path)
1551.9.29 by Aaron Bentley
Optimize Tree._iter_changes with specific file_ids
638
                entry_count += 1
2012.1.1 by Aaron Bentley
Implement change iterator
639
            else:
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
640
                from_versioned = False
2012.1.1 by Aaron Bentley
Implement change iterator
641
                from_kind = None
642
                from_parent = None
643
                from_name = None
644
                from_executable = None
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
645
            versioned = (from_versioned, True)
646
            to_kind, to_executable, to_stat = \
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
647
                self.target._comparison_data(to_entry, to_path)
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
648
            kind = (from_kind, to_kind)
649
            if kind[0] != kind[1]:
2012.1.1 by Aaron Bentley
Implement change iterator
650
                changed_content = True
2012.1.2 by Aaron Bentley
reimplement compare_trees
651
            elif from_kind == 'file':
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
652
                from_size = self.source._file_size(from_entry, from_stat)
653
                to_size = self.target._file_size(to_entry, to_stat)
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
654
                if from_size != to_size:
655
                    changed_content = True
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
656
                elif (self.source.get_file_sha1(file_id, from_path, from_stat) !=
657
                    self.target.get_file_sha1(file_id, to_path, to_stat)):
2012.1.2 by Aaron Bentley
reimplement compare_trees
658
                    changed_content = True
659
            elif from_kind == 'symlink':
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
660
                if (self.source.get_symlink_target(file_id) != 
661
                    self.target.get_symlink_target(file_id)):
2012.1.2 by Aaron Bentley
reimplement compare_trees
662
                    changed_content = True
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
663
            elif from_kind == 'tree-reference':
2255.6.7 by Aaron Bentley
Merge from dirstate
664
                if (self.source.get_reference_revision(from_entry, from_path)
665
                    != self.target.get_reference_revision(to_entry, to_path)):
2100.3.20 by Aaron Bentley
Implement tree comparison for tree references
666
                    changed_content = True 
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
667
            parent = (from_parent, to_entry.parent_id)
668
            name = (from_name, to_entry.name)
669
            executable = (from_executable, to_executable)
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
670
            if pb is not None:
671
                pb.update('comparing files', entry_count, num_entries)
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
672
            if (changed_content is not False or versioned[0] != versioned[1] 
673
                or parent[0] != parent[1] or name[0] != name[1] or 
674
                executable[0] != executable[1] or include_unchanged):
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
675
                yield (file_id, to_path, changed_content, versioned, parent,
2012.1.1 by Aaron Bentley
Implement change iterator
676
                       name, kind, executable)
677
1551.9.31 by Aaron Bentley
Handle to_paths correctly when parent of file is not in specified_ids
678
        def get_to_path(from_entry):
679
            if from_entry.parent_id is None:
680
                to_path = ''
681
            else:
682
                if from_entry.parent_id not in to_paths:
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
683
                    get_to_path(self.source.inventory[from_entry.parent_id])
1551.9.31 by Aaron Bentley
Handle to_paths correctly when parent of file is not in specified_ids
684
                to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
685
                                           from_entry.name)
686
            to_paths[from_entry.file_id] = to_path
687
            return to_path
688
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
689
        for path, from_entry in from_entries_by_dir:
2012.1.1 by Aaron Bentley
Implement change iterator
690
            file_id = from_entry.file_id
691
            if file_id in to_paths:
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
692
                continue
1551.9.31 by Aaron Bentley
Handle to_paths correctly when parent of file is not in specified_ids
693
            to_path = get_to_path(from_entry)
2012.1.16 by Aaron Bentley
Support progress bars in iter_changes
694
            entry_count += 1
695
            if pb is not None:
696
                pb.update('comparing files', entry_count, num_entries)
2012.1.1 by Aaron Bentley
Implement change iterator
697
            versioned = (True, False)
698
            parent = (from_entry.parent_id, None)
699
            name = (from_entry.name, None)
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
700
            from_kind, from_executable, stat_value = \
2255.2.122 by Robert Collins
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
701
                self.source._comparison_data(from_entry, path)
2012.1.7 by Aaron Bentley
Get tree._iter_changed down to ~ 1 stat per file
702
            kind = (from_kind, None)
2012.1.2 by Aaron Bentley
reimplement compare_trees
703
            executable = (from_executable, None)
2012.1.1 by Aaron Bentley
Implement change iterator
704
            changed_content = True
705
            # the parent's path is necessarily known at this point.
706
            yield(file_id, to_path, changed_content, versioned, parent,
707
                  name, kind, executable)
2012.1.8 by Aaron Bentley
Merge from bzr.dev
708
2079.1.1 by John Arbash Meinel
Create a deprecated bzrlib.tree.RevisionTree() in favor of bzrlib.revisiontree.RevisionTree()
709
710
# This was deprecated before 0.12, but did not have an official warning
711
@symbol_versioning.deprecated_function(symbol_versioning.zero_twelve)
712
def RevisionTree(*args, **kwargs):
713
    """RevisionTree has moved to bzrlib.revisiontree.RevisionTree()
714
715
    Accessing it as bzrlib.tree.RevisionTree has been deprecated as of
716
    bzr 0.12.
717
    """
718
    from bzrlib.revisiontree import RevisionTree as _RevisionTree
719
    return _RevisionTree(*args, **kwargs)
720
 
721