~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

  • Committer: Robert Collins
  • Date: 2007-03-02 01:06:12 UTC
  • mto: (2255.11.3 dirstate)
  • mto: This revision was merged to the branch mainline in revision 2322.
  • Revision ID: robertc@robertcollins.net-20070302010612-v4zb59puoc5b0ai5
Teach _iter_changes to gather unversioned path details upon request.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
"""
19
19
 
20
20
import os
 
21
from collections import deque
21
22
from cStringIO import StringIO
22
23
 
23
24
import bzrlib
29
30
from bzrlib.decorators import needs_read_lock
30
31
from bzrlib.errors import BzrError, BzrCheckError
31
32
from bzrlib import errors
32
 
from bzrlib.inventory import Inventory
 
33
from bzrlib.inventory import Inventory, InventoryFile
33
34
from bzrlib.inter import InterObject
34
35
from bzrlib.osutils import fingerprint_file
35
36
import bzrlib.revision
89
90
 
90
91
    def _iter_changes(self, from_tree, include_unchanged=False,
91
92
                     specific_files=None, pb=None, extra_trees=None,
92
 
                     require_versioned=True):
 
93
                     require_versioned=True, want_unversioned=False):
93
94
        intertree = InterTree.get(from_tree, self)
94
95
        return intertree._iter_changes(include_unchanged, specific_files, pb,
95
96
            extra_trees, require_versioned)
557
558
 
558
559
    def _iter_changes(self, include_unchanged=False,
559
560
                      specific_files=None, pb=None, extra_trees=[],
560
 
                      require_versioned=True):
 
561
                      require_versioned=True, want_unversioned=False):
561
562
        """Generate an iterator of changes between trees.
562
563
 
563
564
        A tuple is returned:
581
582
        :param require_versioned: Raise errors.PathsNotVersionedError if a
582
583
            path in the specific_files list is not versioned in one of
583
584
            source, target or extra_trees.
 
585
        :param want_unversioned: Should unversioned files be returned in the
 
586
            output. An unversioned file is defined as one with (False, False)
 
587
            for the versioned pair.
584
588
        """
585
589
        lookup_trees = [self.source]
586
590
        if extra_trees:
587
591
             lookup_trees.extend(extra_trees)
588
592
        specific_file_ids = self.target.paths2ids(specific_files,
589
593
            lookup_trees, require_versioned=require_versioned)
 
594
        if want_unversioned:
 
595
            all_unversioned = sorted([(p.split('/'), p) for p in self.target.extras()
 
596
                if not specific_files or
 
597
                    osutils.is_inside_any(specific_files, p)])
 
598
            all_unversioned = deque(all_unversioned)
 
599
        else:
 
600
            all_unversioned = deque()
590
601
        to_paths = {}
591
602
        from_entries_by_dir = list(self.source.inventory.iter_entries_by_dir(
592
603
            specific_file_ids=specific_file_ids))
595
606
            specific_file_ids=specific_file_ids))
596
607
        num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
597
608
        entry_count = 0
 
609
        # the unversioned path lookup only occurs on real trees - where there 
 
610
        # can be extras. So the fake_entry is solely used to look up
 
611
        # executable it values when execute is not supported.
 
612
        fake_entry = InventoryFile('unused', 'unused', 'unused')
598
613
        for to_path, to_entry in to_entries_by_dir:
 
614
            while all_unversioned and all_unversioned[0][0] < to_path.split('/'):
 
615
                unversioned_path = all_unversioned.popleft()
 
616
                to_kind, to_executable, to_stat = \
 
617
                    self.target._comparison_data(fake_entry, unversioned_path[1])
 
618
                yield (None, unversioned_path[1], True, (False, False),
 
619
                    (None, None),
 
620
                    (None, unversioned_path[0][-1]),
 
621
                    (None, to_kind),
 
622
                    (None, to_executable))
599
623
            file_id = to_entry.file_id
600
624
            to_paths[file_id] = to_path
601
625
            entry_count += 1
643
667
                executable[0] != executable[1] or include_unchanged):
644
668
                yield (file_id, to_path, changed_content, versioned, parent,
645
669
                       name, kind, executable)
 
670
        while all_unversioned:
 
671
            # yield any trailing unversioned paths
 
672
            unversioned_path = all_unversioned.popleft()
 
673
            to_kind, to_executable, to_stat = \
 
674
                self.target._comparison_data(fake_entry, unversioned_path[1])
 
675
            yield (None, unversioned_path[1], True, (False, False),
 
676
                (None, None),
 
677
                (None, unversioned_path[0][-1]),
 
678
                (None, to_kind),
 
679
                (None, to_executable))
646
680
 
647
681
        def get_to_path(from_entry):
648
682
            if from_entry.parent_id is None: