~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

  • Committer: John Arbash Meinel
  • Date: 2006-12-11 19:25:13 UTC
  • mfrom: (2172 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2173.
  • Revision ID: john@arbash-meinel.com-20061211192513-u9ivkqwkp8j3v2i5
[merge] bzr.dev 2172 and move NEWS to the correct location

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
    
240
261
    def __contains__(self, file_id):
241
262
        return (file_id in self._inventory)
242
263
 
243
 
    def get_file_sha1(self, file_id, path=None):
 
264
    def get_file_sha1(self, file_id, path=None, stat_value=None):
244
265
        return None
245
266
 
246
267
 
427
448
        return delta._compare_trees(self.source, self.target, want_unchanged,
428
449
            specific_file_ids, include_root)
429
450
 
 
451
    def _iter_changes(self, from_tree, to_tree, include_unchanged, 
 
452
                      specific_file_ids, pb):
 
453
        """Generate an iterator of changes between trees.
 
454
 
 
455
        A tuple is returned:
 
456
        (file_id, path, changed_content, versioned, parent, name, kind,
 
457
         executable)
 
458
 
 
459
        Path is relative to the to_tree.  changed_content is True if the file's
 
460
        content has changed.  This includes changes to its kind, and to
 
461
        a symlink's target.
 
462
 
 
463
        versioned, parent, name, kind, executable are tuples of (from, to).
 
464
        If a file is missing in a tree, its kind is None.
 
465
 
 
466
        Iteration is done in parent-to-child order, relative to the to_tree.
 
467
        """
 
468
        to_paths = {}
 
469
        from_entries_by_dir = list(from_tree.inventory.iter_entries_by_dir())
 
470
        from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
 
471
        to_entries_by_dir = list(to_tree.inventory.iter_entries_by_dir())
 
472
        if specific_file_ids is not None:
 
473
            specific_file_ids = set(specific_file_ids)
 
474
            num_entries = len(specific_file_ids)
 
475
        else:
 
476
            num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
 
477
        entry_count = 0
 
478
        for to_path, to_entry in to_entries_by_dir:
 
479
            file_id = to_entry.file_id
 
480
            to_paths[file_id] = to_path
 
481
            if (specific_file_ids is not None and 
 
482
                file_id not in specific_file_ids):
 
483
                continue
 
484
            entry_count += 1
 
485
            changed_content = False
 
486
            from_path, from_entry = from_data.get(file_id, (None, None))
 
487
            from_versioned = (from_entry is not None)
 
488
            if from_entry is not None:
 
489
                from_versioned = True
 
490
                from_name = from_entry.name
 
491
                from_parent = from_entry.parent_id
 
492
                from_kind, from_executable, from_stat = \
 
493
                    from_tree._comparison_data(from_entry, from_path)
 
494
                if specific_file_ids is None:
 
495
                    entry_count += 1
 
496
            else:
 
497
                from_versioned = False
 
498
                from_kind = None
 
499
                from_parent = None
 
500
                from_name = None
 
501
                from_executable = None
 
502
            versioned = (from_versioned, True)
 
503
            to_kind, to_executable, to_stat = \
 
504
                to_tree._comparison_data(to_entry, to_path)
 
505
            kind = (from_kind, to_kind)
 
506
            if kind[0] != kind[1]:
 
507
                changed_content = True
 
508
            elif from_kind == 'file':
 
509
                from_size = from_tree._file_size(from_entry, from_stat)
 
510
                to_size = to_tree._file_size(to_entry, to_stat)
 
511
                if from_size != to_size:
 
512
                    changed_content = True
 
513
                elif (from_tree.get_file_sha1(file_id, from_path, from_stat) !=
 
514
                    to_tree.get_file_sha1(file_id, to_path, to_stat)):
 
515
                    changed_content = True
 
516
            elif from_kind == 'symlink':
 
517
                if (from_tree.get_symlink_target(file_id) != 
 
518
                    to_tree.get_symlink_target(file_id)):
 
519
                    changed_content = True
 
520
            parent = (from_parent, to_entry.parent_id)
 
521
            name = (from_name, to_entry.name)
 
522
            executable = (from_executable, to_executable)
 
523
            if pb is not None:
 
524
                pb.update('comparing files', entry_count, num_entries)
 
525
            if (changed_content is not False or versioned[0] != versioned[1] 
 
526
                or parent[0] != parent[1] or name[0] != name[1] or 
 
527
                executable[0] != executable[1] or include_unchanged):
 
528
                yield (file_id, to_path, changed_content, versioned, parent,
 
529
                       name, kind, executable)
 
530
 
 
531
        for path, from_entry in from_entries_by_dir:
 
532
            file_id = from_entry.file_id
 
533
            if file_id in to_paths:
 
534
                continue
 
535
            if from_entry.parent_id is None:
 
536
                to_path = ''
 
537
            else:
 
538
                to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
 
539
                                           from_entry.name)
 
540
            to_paths[file_id] = to_path
 
541
            if (specific_file_ids is not None and 
 
542
                file_id not in specific_file_ids):
 
543
                continue
 
544
            entry_count += 1
 
545
            if pb is not None:
 
546
                pb.update('comparing files', entry_count, num_entries)
 
547
            versioned = (True, False)
 
548
            parent = (from_entry.parent_id, None)
 
549
            name = (from_entry.name, None)
 
550
            from_kind, from_executable, stat_value = \
 
551
                from_tree._comparison_data(from_entry, path)
 
552
            kind = (from_kind, None)
 
553
            executable = (from_executable, None)
 
554
            changed_content = True
 
555
            # the parent's path is necessarily known at this point.
 
556
            yield(file_id, to_path, changed_content, versioned, parent,
 
557
                  name, kind, executable)
 
558
 
430
559
 
431
560
# This was deprecated before 0.12, but did not have an official warning
432
561
@symbol_versioning.deprecated_function(symbol_versioning.zero_twelve)