/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 from bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import bzrlib
24
24
from bzrlib import (
25
25
    delta,
 
26
    osutils,
26
27
    symbol_versioning,
27
28
    )
28
29
from bzrlib.decorators import needs_read_lock
85
86
            require_versioned=require_versioned,
86
87
            include_root=include_root
87
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)
88
95
    
89
96
    def conflicts(self):
90
97
        """Get a list of the conflicts in the tree.
147
154
    def kind(self, file_id):
148
155
        raise NotImplementedError("subclasses must implement kind")
149
156
 
 
157
    def _comparison_data(self, entry, path):
 
158
        """Return a tuple of kind, executable, stat_value for a file.
 
159
 
 
160
        entry may be None if there is no inventory entry for the file, but
 
161
        path must always be supplied.
 
162
 
 
163
        kind is None if there is no file present (even if an inventory id is
 
164
        present).  executable is False for non-file entries.
 
165
        """
 
166
        raise NotImplementedError(self._comparison_data)
 
167
 
 
168
    def _file_size(entry, stat_value):
 
169
        raise NotImplementedError(self._file_size)
 
170
 
150
171
    def _get_inventory(self):
151
172
        return self._inventory
152
173
    
157
178
    def get_file_by_path(self, path):
158
179
        return self.get_file(self._inventory.path2id(path))
159
180
 
 
181
    def annotate_iter(self, file_id):
 
182
        """Return an iterator of revision_id, line tuples
 
183
 
 
184
        For working trees (and mutable trees in general), the special
 
185
        revision_id 'current:' will be used for lines that are new in this
 
186
        tree, e.g. uncommitted changes.
 
187
        :param file_id: The file to produce an annotated version from
 
188
        """
 
189
        raise NotImplementedError(self.annotate_iter)
 
190
 
160
191
    inventory = property(_get_inventory,
161
192
                         doc="Inventory of this Tree")
162
193
 
240
271
    def __contains__(self, file_id):
241
272
        return (file_id in self._inventory)
242
273
 
243
 
    def get_file_sha1(self, file_id, path=None):
 
274
    def get_file_sha1(self, file_id, path=None, stat_value=None):
244
275
        return None
245
276
 
246
277
 
427
458
        return delta._compare_trees(self.source, self.target, want_unchanged,
428
459
            specific_file_ids, include_root)
429
460
 
 
461
    def _iter_changes(self, from_tree, to_tree, include_unchanged, 
 
462
                      specific_file_ids, pb):
 
463
        """Generate an iterator of changes between trees.
 
464
 
 
465
        A tuple is returned:
 
466
        (file_id, path, changed_content, versioned, parent, name, kind,
 
467
         executable)
 
468
 
 
469
        Path is relative to the to_tree.  changed_content is True if the file's
 
470
        content has changed.  This includes changes to its kind, and to
 
471
        a symlink's target.
 
472
 
 
473
        versioned, parent, name, kind, executable are tuples of (from, to).
 
474
        If a file is missing in a tree, its kind is None.
 
475
 
 
476
        Iteration is done in parent-to-child order, relative to the to_tree.
 
477
        """
 
478
        to_paths = {}
 
479
        from_entries_by_dir = list(from_tree.inventory.iter_entries_by_dir())
 
480
        from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
 
481
        to_entries_by_dir = list(to_tree.inventory.iter_entries_by_dir())
 
482
        if specific_file_ids is not None:
 
483
            specific_file_ids = set(specific_file_ids)
 
484
            num_entries = len(specific_file_ids)
 
485
        else:
 
486
            num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
 
487
        entry_count = 0
 
488
        for to_path, to_entry in to_entries_by_dir:
 
489
            file_id = to_entry.file_id
 
490
            to_paths[file_id] = to_path
 
491
            if (specific_file_ids is not None and 
 
492
                file_id not in specific_file_ids):
 
493
                continue
 
494
            entry_count += 1
 
495
            changed_content = False
 
496
            from_path, from_entry = from_data.get(file_id, (None, None))
 
497
            from_versioned = (from_entry is not None)
 
498
            if from_entry is not None:
 
499
                from_versioned = True
 
500
                from_name = from_entry.name
 
501
                from_parent = from_entry.parent_id
 
502
                from_kind, from_executable, from_stat = \
 
503
                    from_tree._comparison_data(from_entry, from_path)
 
504
                if specific_file_ids is None:
 
505
                    entry_count += 1
 
506
            else:
 
507
                from_versioned = False
 
508
                from_kind = None
 
509
                from_parent = None
 
510
                from_name = None
 
511
                from_executable = None
 
512
            versioned = (from_versioned, True)
 
513
            to_kind, to_executable, to_stat = \
 
514
                to_tree._comparison_data(to_entry, to_path)
 
515
            kind = (from_kind, to_kind)
 
516
            if kind[0] != kind[1]:
 
517
                changed_content = True
 
518
            elif from_kind == 'file':
 
519
                from_size = from_tree._file_size(from_entry, from_stat)
 
520
                to_size = to_tree._file_size(to_entry, to_stat)
 
521
                if from_size != to_size:
 
522
                    changed_content = True
 
523
                elif (from_tree.get_file_sha1(file_id, from_path, from_stat) !=
 
524
                    to_tree.get_file_sha1(file_id, to_path, to_stat)):
 
525
                    changed_content = True
 
526
            elif from_kind == 'symlink':
 
527
                if (from_tree.get_symlink_target(file_id) != 
 
528
                    to_tree.get_symlink_target(file_id)):
 
529
                    changed_content = True
 
530
            parent = (from_parent, to_entry.parent_id)
 
531
            name = (from_name, to_entry.name)
 
532
            executable = (from_executable, to_executable)
 
533
            if pb is not None:
 
534
                pb.update('comparing files', entry_count, num_entries)
 
535
            if (changed_content is not False or versioned[0] != versioned[1] 
 
536
                or parent[0] != parent[1] or name[0] != name[1] or 
 
537
                executable[0] != executable[1] or include_unchanged):
 
538
                yield (file_id, to_path, changed_content, versioned, parent,
 
539
                       name, kind, executable)
 
540
 
 
541
        for path, from_entry in from_entries_by_dir:
 
542
            file_id = from_entry.file_id
 
543
            if file_id in to_paths:
 
544
                continue
 
545
            if from_entry.parent_id is None:
 
546
                to_path = ''
 
547
            else:
 
548
                to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
 
549
                                           from_entry.name)
 
550
            to_paths[file_id] = to_path
 
551
            if (specific_file_ids is not None and 
 
552
                file_id not in specific_file_ids):
 
553
                continue
 
554
            entry_count += 1
 
555
            if pb is not None:
 
556
                pb.update('comparing files', entry_count, num_entries)
 
557
            versioned = (True, False)
 
558
            parent = (from_entry.parent_id, None)
 
559
            name = (from_entry.name, None)
 
560
            from_kind, from_executable, stat_value = \
 
561
                from_tree._comparison_data(from_entry, path)
 
562
            kind = (from_kind, None)
 
563
            executable = (from_executable, None)
 
564
            changed_content = True
 
565
            # the parent's path is necessarily known at this point.
 
566
            yield(file_id, to_path, changed_content, versioned, parent,
 
567
                  name, kind, executable)
 
568
 
430
569
 
431
570
# This was deprecated before 0.12, but did not have an official warning
432
571
@symbol_versioning.deprecated_function(symbol_versioning.zero_twelve)