/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

[merge] bzr.dev 2240

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
import os
21
21
from cStringIO import StringIO
22
 
from warnings import warn
23
22
 
24
23
import bzrlib
25
 
from bzrlib import delta
 
24
from bzrlib import (
 
25
    delta,
 
26
    osutils,
 
27
    symbol_versioning,
 
28
    )
26
29
from bzrlib.decorators import needs_read_lock
27
30
from bzrlib.errors import BzrError, BzrCheckError
28
31
from bzrlib import errors
83
86
            require_versioned=require_versioned,
84
87
            include_root=include_root
85
88
            )
 
89
 
 
90
    def _iter_changes(self, from_tree, include_unchanged=False, 
 
91
                     specific_file_ids=None, pb=None):
 
92
        intertree = InterTree.get(from_tree, self)
 
93
        return intertree._iter_changes(from_tree, self, include_unchanged, 
 
94
                                       specific_file_ids, pb)
86
95
    
87
96
    def conflicts(self):
88
97
        """Get a list of the conflicts in the tree.
132
141
        """
133
142
        return self.bzrdir.is_control_filename(filename)
134
143
 
135
 
    def iter_entries_by_dir(self):
 
144
    def iter_entries_by_dir(self, specific_file_ids=None):
136
145
        """Walk the tree in 'by_dir' order.
137
146
 
138
147
        This will yield each entry in the tree as a (path, entry) tuple. The
140
149
        preceeded by the parent of a directory, and all the contents of a 
141
150
        directory are grouped together.
142
151
        """
143
 
        return self.inventory.iter_entries_by_dir()
 
152
        return self.inventory.iter_entries_by_dir(
 
153
            specific_file_ids=specific_file_ids)
144
154
 
145
155
    def kind(self, file_id):
146
156
        raise NotImplementedError("subclasses must implement kind")
147
157
 
 
158
    def _comparison_data(self, entry, path):
 
159
        """Return a tuple of kind, executable, stat_value for a file.
 
160
 
 
161
        entry may be None if there is no inventory entry for the file, but
 
162
        path must always be supplied.
 
163
 
 
164
        kind is None if there is no file present (even if an inventory id is
 
165
        present).  executable is False for non-file entries.
 
166
        """
 
167
        raise NotImplementedError(self._comparison_data)
 
168
 
 
169
    def _file_size(entry, stat_value):
 
170
        raise NotImplementedError(self._file_size)
 
171
 
148
172
    def _get_inventory(self):
149
173
        return self._inventory
150
174
    
155
179
    def get_file_by_path(self, path):
156
180
        return self.get_file(self._inventory.path2id(path))
157
181
 
 
182
    def annotate_iter(self, file_id):
 
183
        """Return an iterator of revision_id, line tuples
 
184
 
 
185
        For working trees (and mutable trees in general), the special
 
186
        revision_id 'current:' will be used for lines that are new in this
 
187
        tree, e.g. uncommitted changes.
 
188
        :param file_id: The file to produce an annotated version from
 
189
        """
 
190
        raise NotImplementedError(self.annotate_iter)
 
191
 
158
192
    inventory = property(_get_inventory,
159
193
                         doc="Inventory of this Tree")
160
194
 
226
260
        return set((p for p in paths if not pred(p)))
227
261
 
228
262
 
229
 
# for compatibility
230
 
from bzrlib.revisiontree import RevisionTree
231
 
 
232
 
 
233
263
class EmptyTree(Tree):
234
264
 
235
265
    def __init__(self):
236
 
        self._inventory = Inventory()
237
 
        warn('EmptyTree is deprecated as of bzr 0.9 please use '
238
 
            'repository.revision_tree instead.',
239
 
            DeprecationWarning, stacklevel=2)
 
266
        self._inventory = Inventory(root_id=None)
 
267
        symbol_versioning.warn('EmptyTree is deprecated as of bzr 0.9 please'
 
268
                               ' use repository.revision_tree instead.',
 
269
                               DeprecationWarning, stacklevel=2)
240
270
 
241
271
    def get_parent_ids(self):
242
272
        return []
251
281
        assert self._inventory[file_id].kind == "directory"
252
282
        return "directory"
253
283
 
254
 
    def list_files(self):
 
284
    def list_files(self, include_root=False):
255
285
        return iter([])
256
286
    
257
287
    def __contains__(self, file_id):
258
288
        return (file_id in self._inventory)
259
289
 
260
 
    def get_file_sha1(self, file_id, path=None):
 
290
    def get_file_sha1(self, file_id, path=None, stat_value=None):
261
291
        return None
262
292
 
263
293
 
443
473
            return delta.TreeDelta()
444
474
        return delta._compare_trees(self.source, self.target, want_unchanged,
445
475
            specific_file_ids, include_root)
 
476
 
 
477
    def _iter_changes(self, from_tree, to_tree, include_unchanged, 
 
478
                      specific_file_ids, pb):
 
479
        """Generate an iterator of changes between trees.
 
480
 
 
481
        A tuple is returned:
 
482
        (file_id, path, changed_content, versioned, parent, name, kind,
 
483
         executable)
 
484
 
 
485
        Path is relative to the to_tree.  changed_content is True if the file's
 
486
        content has changed.  This includes changes to its kind, and to
 
487
        a symlink's target.
 
488
 
 
489
        versioned, parent, name, kind, executable are tuples of (from, to).
 
490
        If a file is missing in a tree, its kind is None.
 
491
 
 
492
        Iteration is done in parent-to-child order, relative to the to_tree.
 
493
        """
 
494
        to_paths = {}
 
495
        from_entries_by_dir = list(from_tree.inventory.iter_entries_by_dir(
 
496
            specific_file_ids=specific_file_ids))
 
497
        from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
 
498
        to_entries_by_dir = list(to_tree.inventory.iter_entries_by_dir(
 
499
            specific_file_ids=specific_file_ids))
 
500
        num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
 
501
        entry_count = 0
 
502
        for to_path, to_entry in to_entries_by_dir:
 
503
            file_id = to_entry.file_id
 
504
            to_paths[file_id] = to_path
 
505
            entry_count += 1
 
506
            changed_content = False
 
507
            from_path, from_entry = from_data.get(file_id, (None, None))
 
508
            from_versioned = (from_entry is not None)
 
509
            if from_entry is not None:
 
510
                from_versioned = True
 
511
                from_name = from_entry.name
 
512
                from_parent = from_entry.parent_id
 
513
                from_kind, from_executable, from_stat = \
 
514
                    from_tree._comparison_data(from_entry, from_path)
 
515
                entry_count += 1
 
516
            else:
 
517
                from_versioned = False
 
518
                from_kind = None
 
519
                from_parent = None
 
520
                from_name = None
 
521
                from_executable = None
 
522
            versioned = (from_versioned, True)
 
523
            to_kind, to_executable, to_stat = \
 
524
                to_tree._comparison_data(to_entry, to_path)
 
525
            kind = (from_kind, to_kind)
 
526
            if kind[0] != kind[1]:
 
527
                changed_content = True
 
528
            elif from_kind == 'file':
 
529
                from_size = from_tree._file_size(from_entry, from_stat)
 
530
                to_size = to_tree._file_size(to_entry, to_stat)
 
531
                if from_size != to_size:
 
532
                    changed_content = True
 
533
                elif (from_tree.get_file_sha1(file_id, from_path, from_stat) !=
 
534
                    to_tree.get_file_sha1(file_id, to_path, to_stat)):
 
535
                    changed_content = True
 
536
            elif from_kind == 'symlink':
 
537
                if (from_tree.get_symlink_target(file_id) != 
 
538
                    to_tree.get_symlink_target(file_id)):
 
539
                    changed_content = True
 
540
            parent = (from_parent, to_entry.parent_id)
 
541
            name = (from_name, to_entry.name)
 
542
            executable = (from_executable, to_executable)
 
543
            if pb is not None:
 
544
                pb.update('comparing files', entry_count, num_entries)
 
545
            if (changed_content is not False or versioned[0] != versioned[1] 
 
546
                or parent[0] != parent[1] or name[0] != name[1] or 
 
547
                executable[0] != executable[1] or include_unchanged):
 
548
                yield (file_id, to_path, changed_content, versioned, parent,
 
549
                       name, kind, executable)
 
550
 
 
551
        def get_to_path(from_entry):
 
552
            if from_entry.parent_id is None:
 
553
                to_path = ''
 
554
            else:
 
555
                if from_entry.parent_id not in to_paths:
 
556
                    get_to_path(from_tree.inventory[from_entry.parent_id])
 
557
                to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
 
558
                                           from_entry.name)
 
559
            to_paths[from_entry.file_id] = to_path
 
560
            return to_path
 
561
 
 
562
        for path, from_entry in from_entries_by_dir:
 
563
            file_id = from_entry.file_id
 
564
            if file_id in to_paths:
 
565
                continue
 
566
            to_path = get_to_path(from_entry)
 
567
            entry_count += 1
 
568
            if pb is not None:
 
569
                pb.update('comparing files', entry_count, num_entries)
 
570
            versioned = (True, False)
 
571
            parent = (from_entry.parent_id, None)
 
572
            name = (from_entry.name, None)
 
573
            from_kind, from_executable, stat_value = \
 
574
                from_tree._comparison_data(from_entry, path)
 
575
            kind = (from_kind, None)
 
576
            executable = (from_executable, None)
 
577
            changed_content = True
 
578
            # the parent's path is necessarily known at this point.
 
579
            yield(file_id, to_path, changed_content, versioned, parent,
 
580
                  name, kind, executable)
 
581
 
 
582
 
 
583
# This was deprecated before 0.12, but did not have an official warning
 
584
@symbol_versioning.deprecated_function(symbol_versioning.zero_twelve)
 
585
def RevisionTree(*args, **kwargs):
 
586
    """RevisionTree has moved to bzrlib.revisiontree.RevisionTree()
 
587
 
 
588
    Accessing it as bzrlib.tree.RevisionTree has been deprecated as of
 
589
    bzr 0.12.
 
590
    """
 
591
    from bzrlib.revisiontree import RevisionTree as _RevisionTree
 
592
    return _RevisionTree(*args, **kwargs)
 
593
 
 
594