~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

  • Committer: Andrew Bennetts
  • Date: 2009-07-27 05:35:00 UTC
  • mfrom: (4570 +trunk)
  • mto: (4634.6.29 2.0)
  • mto: This revision was merged to the branch mainline in revision 4680.
  • Revision ID: andrew.bennetts@canonical.com-20090727053500-q76zsn2dx33jhmj5
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tree classes, representing directory at point in time.
18
18
"""
19
19
 
20
20
import os
21
21
from collections import deque
22
 
from cStringIO import StringIO
23
22
 
24
23
import bzrlib
25
24
from bzrlib import (
26
25
    conflicts as _mod_conflicts,
 
26
    debug,
27
27
    delta,
 
28
    filters,
28
29
    osutils,
29
30
    revision as _mod_revision,
30
31
    rules,
31
 
    symbol_versioning,
32
32
    )
33
33
from bzrlib.decorators import needs_read_lock
34
 
from bzrlib.errors import BzrError, BzrCheckError, NoSuchId
 
34
from bzrlib.errors import BzrError, NoSuchId
35
35
from bzrlib import errors
36
 
from bzrlib.inventory import Inventory, InventoryFile
 
36
from bzrlib.inventory import InventoryFile
37
37
from bzrlib.inter import InterObject
38
38
from bzrlib.osutils import fingerprint_file
39
39
import bzrlib.revision
40
40
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
41
 
from bzrlib.trace import mutter, note
 
41
from bzrlib.trace import note
42
42
 
43
43
 
44
44
class Tree(object):
95
95
            want_unversioned=want_unversioned,
96
96
            )
97
97
 
98
 
    @symbol_versioning.deprecated_method(symbol_versioning.one_three)
99
 
    def _iter_changes(self, *args, **kwargs):
100
 
        return self.iter_changes(*args, **kwargs)
101
 
 
102
98
    def iter_changes(self, from_tree, include_unchanged=False,
103
99
                     specific_files=None, pb=None, extra_trees=None,
104
100
                     require_versioned=True, want_unversioned=False):
137
133
        return self.has_id(file_id)
138
134
 
139
135
    def has_or_had_id(self, file_id):
140
 
        if file_id == self.inventory.root.file_id:
141
 
            return True
142
136
        return self.inventory.has_id(file_id)
143
137
 
144
138
    def is_ignored(self, filename):
204
198
            specific_file_ids=specific_file_ids)
205
199
 
206
200
    def iter_references(self):
207
 
        for path, entry in self.iter_entries_by_dir():
208
 
            if entry.kind == 'tree-reference':
209
 
                yield path, entry.file_id
 
201
        if self.supports_tree_reference():
 
202
            for path, entry in self.iter_entries_by_dir():
 
203
                if entry.kind == 'tree-reference':
 
204
                    yield path, entry.file_id
210
205
 
211
206
    def kind(self, file_id):
212
207
        raise NotImplementedError("Tree subclass %s must implement kind"
264
259
        """
265
260
        raise NotImplementedError(self.get_file)
266
261
 
 
262
    def get_file_with_stat(self, file_id, path=None):
 
263
        """Get a file handle and stat object for file_id.
 
264
 
 
265
        The default implementation returns (self.get_file, None) for backwards
 
266
        compatibility.
 
267
 
 
268
        :param file_id: The file id to read.
 
269
        :param path: The path of the file, if it is known.
 
270
        :return: A tuple (file_handle, stat_value_or_None). If the tree has
 
271
            no stat facility, or need for a stat cache feedback during commit,
 
272
            it may return None for the second element of the tuple.
 
273
        """
 
274
        return (self.get_file(file_id, path), None)
 
275
 
267
276
    def get_file_text(self, file_id, path=None):
268
277
        """Return the byte content of a file.
269
278
 
424
433
        raise NotImplementedError(self.annotate_iter)
425
434
 
426
435
    def _get_plan_merge_data(self, file_id, other, base):
427
 
        from bzrlib import merge, versionedfile
 
436
        from bzrlib import versionedfile
428
437
        vf = versionedfile._PlanMergeVersionedFile(file_id)
429
438
        last_revision_a = self._get_file_revision(file_id, vf, 'this:')
430
439
        last_revision_b = other._get_file_revision(file_id, vf, 'other:')
546
555
        for child in getattr(entry, 'children', {}).itervalues():
547
556
            yield child.file_id
548
557
 
549
 
    @symbol_versioning.deprecated_method(symbol_versioning.one_six)
550
 
    def print_file(self, file_id):
551
 
        """Print file with id `file_id` to stdout."""
552
 
        import sys
553
 
        sys.stdout.write(self.get_file_text(file_id))
554
 
 
555
558
    def lock_read(self):
556
559
        pass
557
560
 
627
630
    def supports_content_filtering(self):
628
631
        return False
629
632
 
 
633
    def _content_filter_stack(self, path=None, file_id=None):
 
634
        """The stack of content filters for a path if filtering is supported.
 
635
 
 
636
        Readers will be applied in first-to-last order.
 
637
        Writers will be applied in last-to-first order.
 
638
        Either the path or the file-id needs to be provided.
 
639
 
 
640
        :param path: path relative to the root of the tree
 
641
            or None if unknown
 
642
        :param file_id: file_id or None if unknown
 
643
        :return: the list of filters - [] if there are none
 
644
        """
 
645
        filter_pref_names = filters._get_registered_names()
 
646
        if len(filter_pref_names) == 0:
 
647
            return []
 
648
        if path is None:
 
649
            path = self.id2path(file_id)
 
650
        prefs = self.iter_search_rules([path], filter_pref_names).next()
 
651
        stk = filters._get_filter_stack_for(prefs)
 
652
        if 'filters' in debug.debug_flags:
 
653
            note("*** %s content-filter: %s => %r" % (path,prefs,stk))
 
654
        return stk
 
655
 
 
656
    def _content_filter_stack_provider(self):
 
657
        """A function that returns a stack of ContentFilters.
 
658
 
 
659
        The function takes a path (relative to the top of the tree) and a
 
660
        file-id as parameters.
 
661
 
 
662
        :return: None if content filtering is not supported by this tree.
 
663
        """
 
664
        if self.supports_content_filtering():
 
665
            return lambda path, file_id: \
 
666
                    self._content_filter_stack(path, file_id)
 
667
        else:
 
668
            return None
 
669
 
630
670
    def iter_search_rules(self, path_names, pref_names=None,
631
 
        _default_searcher=rules._per_user_searcher):
 
671
        _default_searcher=None):
632
672
        """Find the preferences for filenames in a tree.
633
673
 
634
674
        :param path_names: an iterable of paths to find attributes for.
638
678
        :return: an iterator of tuple sequences, one per path-name.
639
679
          See _RulesSearcher.get_items for details on the tuple sequence.
640
680
        """
 
681
        if _default_searcher is None:
 
682
            _default_searcher = rules._per_user_searcher
641
683
        searcher = self._get_rules_searcher(_default_searcher)
642
684
        if searcher is not None:
643
685
            if pref_names is not None:
781
823
        new_pending = set()
782
824
        for file_id in pending:
783
825
            for tree in trees:
784
 
                if not tree.has_id(file_id):
 
826
                if not tree.has_or_had_id(file_id):
785
827
                    continue
786
828
                for child_id in tree.iter_children(file_id):
787
829
                    if child_id not in interesting_ids:
876
918
            output. An unversioned file is defined as one with (False, False)
877
919
            for the versioned pair.
878
920
        """
879
 
        result = []
880
921
        lookup_trees = [self.source]
881
922
        if extra_trees:
882
923
             lookup_trees.extend(extra_trees)
941
982
            if kind[0] != kind[1]:
942
983
                changed_content = True
943
984
            elif from_kind == 'file':
944
 
                from_size = self.source._file_size(from_entry, from_stat)
945
 
                to_size = self.target._file_size(to_entry, to_stat)
946
 
                if from_size != to_size:
947
 
                    changed_content = True
948
 
                elif (self.source.get_file_sha1(file_id, from_path, from_stat) !=
 
985
                if (self.source.get_file_sha1(file_id, from_path, from_stat) !=
949
986
                    self.target.get_file_sha1(file_id, to_path, to_stat)):
950
987
                    changed_content = True
951
988
            elif from_kind == 'symlink':
952
989
                if (self.source.get_symlink_target(file_id) !=
953
990
                    self.target.get_symlink_target(file_id)):
954
991
                    changed_content = True
 
992
                # XXX: Yes, the indentation below is wrong. But fixing it broke
 
993
                # test_merge.TestMergerEntriesLCAOnDisk.
 
994
                # test_nested_tree_subtree_renamed_and_modified. We'll wait for
 
995
                # the fix from bzr.dev -- vila 2009026
955
996
                elif from_kind == 'tree-reference':
956
997
                    if (self.source.get_reference_revision(file_id, from_path)
957
998
                        != self.target.get_reference_revision(file_id, to_path)):