~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Martin
  • Date: 2010-05-16 15:18:43 UTC
  • mfrom: (5235 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5239.
  • Revision ID: gzlist@googlemail.com-20100516151843-lu53u7caehm3ie3i
Merge bzr.dev to resolve conflicts in NEWS and _chk_map_pyx

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
29
29
WorkingTree.open(dir).
30
30
"""
31
31
 
32
 
# TODO: Give the workingtree sole responsibility for the working inventory;
33
 
# remove the variable and references to it from the branch.  This may require
34
 
# updating the commit code so as to update the inventory within the working
35
 
# copy, and making sure there's only one WorkingTree for any directory on disk.
36
 
# At the moment they may alias the inventory and have old copies of it in
37
 
# memory.  (Now done? -- mbp 20060309)
38
32
 
39
33
from cStringIO import StringIO
40
34
import os
48
42
import itertools
49
43
import operator
50
44
import stat
51
 
from time import time
52
 
import warnings
53
45
import re
54
46
 
55
47
import bzrlib
57
49
    branch,
58
50
    bzrdir,
59
51
    conflicts as _mod_conflicts,
60
 
    dirstate,
61
52
    errors,
62
53
    generate_ids,
63
54
    globbing,
 
55
    graph as _mod_graph,
64
56
    hashcache,
65
57
    ignores,
 
58
    inventory,
66
59
    merge,
67
60
    revision as _mod_revision,
68
61
    revisiontree,
69
 
    repository,
70
 
    textui,
71
62
    trace,
72
63
    transform,
73
64
    ui,
74
 
    urlutils,
75
65
    views,
76
66
    xml5,
77
 
    xml6,
78
67
    xml7,
79
68
    )
80
69
import bzrlib.branch
81
70
from bzrlib.transport import get_transport
82
 
import bzrlib.ui
83
 
from bzrlib.workingtree_4 import WorkingTreeFormat4, WorkingTreeFormat5
 
71
from bzrlib.workingtree_4 import (
 
72
    WorkingTreeFormat4,
 
73
    WorkingTreeFormat5,
 
74
    WorkingTreeFormat6,
 
75
    )
84
76
""")
85
77
 
86
78
from bzrlib import symbol_versioning
87
79
from bzrlib.decorators import needs_read_lock, needs_write_lock
88
 
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
 
80
from bzrlib.lock import LogicalLockResult
89
81
from bzrlib.lockable_files import LockableFiles
90
82
from bzrlib.lockdir import LockDir
91
83
import bzrlib.mutabletree
92
84
from bzrlib.mutabletree import needs_tree_write_lock
93
85
from bzrlib import osutils
94
86
from bzrlib.osutils import (
95
 
    compact_date,
96
87
    file_kind,
97
88
    isdir,
98
89
    normpath,
99
90
    pathjoin,
100
 
    rand_chars,
101
91
    realpath,
102
92
    safe_unicode,
103
93
    splitpath,
106
96
from bzrlib.filters import filtered_input_file
107
97
from bzrlib.trace import mutter, note
108
98
from bzrlib.transport.local import LocalTransport
109
 
from bzrlib.progress import DummyProgress, ProgressPhase
110
 
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
 
99
from bzrlib.revision import CURRENT_REVISION
111
100
from bzrlib.rio import RioReader, rio_file, Stanza
112
 
from bzrlib.symbol_versioning import (deprecated_passed,
113
 
        deprecated_method,
114
 
        deprecated_function,
115
 
        DEPRECATED_PARAMETER,
116
 
        )
 
101
from bzrlib.symbol_versioning import (
 
102
    deprecated_passed,
 
103
    DEPRECATED_PARAMETER,
 
104
    )
117
105
 
118
106
 
119
107
MERGE_MODIFIED_HEADER_1 = "BZR merge-modified list format 1"
 
108
# TODO: Modifying the conflict objects or their type is currently nearly
 
109
# impossible as there is no clear relationship between the working tree format
 
110
# and the conflict list file format.
120
111
CONFLICT_HEADER_1 = "BZR conflict list format 1"
121
112
 
122
113
ERROR_PATH_NOT_FOUND = 3    # WindowsError errno code, equivalent to ENOENT
177
168
        return ''
178
169
 
179
170
 
180
 
class WorkingTree(bzrlib.mutabletree.MutableTree):
 
171
class WorkingTree(bzrlib.mutabletree.MutableTree,
 
172
    bzrdir.ControlComponent):
181
173
    """Working copy tree.
182
174
 
183
175
    The inventory is held in the `Branch` working-inventory, and the
256
248
        self._rules_searcher = None
257
249
        self.views = self._make_views()
258
250
 
 
251
    @property
 
252
    def user_transport(self):
 
253
        return self.bzrdir.user_transport
 
254
 
 
255
    @property
 
256
    def control_transport(self):
 
257
        return self._transport
 
258
 
259
259
    def _detect_case_handling(self):
260
260
        wt_trans = self.bzrdir.get_workingtree_transport(None)
261
261
        try:
286
286
        self._control_files.break_lock()
287
287
        self.branch.break_lock()
288
288
 
 
289
    def _get_check_refs(self):
 
290
        """Return the references needed to perform a check of this tree.
 
291
        
 
292
        The default implementation returns no refs, and is only suitable for
 
293
        trees that have no local caching and can commit on ghosts at any time.
 
294
 
 
295
        :seealso: bzrlib.check for details about check_refs.
 
296
        """
 
297
        return []
 
298
 
289
299
    def requires_rich_root(self):
290
300
        return self._format.requires_rich_root
291
301
 
415
425
            return self.branch.repository.revision_tree(revision_id)
416
426
        except (errors.RevisionNotPresent, errors.NoSuchRevision):
417
427
            # the basis tree *may* be a ghost or a low level error may have
418
 
            # occured. If the revision is present, its a problem, if its not
 
428
            # occurred. If the revision is present, its a problem, if its not
419
429
            # its a ghost.
420
430
            if self.branch.repository.has_revision(revision_id):
421
431
                raise
442
452
 
443
453
    def get_file_with_stat(self, file_id, path=None, filtered=True,
444
454
        _fstat=os.fstat):
445
 
        """See MutableTree.get_file_with_stat."""
 
455
        """See Tree.get_file_with_stat."""
446
456
        if path is None:
447
457
            path = self.id2path(file_id)
448
458
        file_obj = self.get_file_byname(path, filtered=False)
449
459
        stat_value = _fstat(file_obj.fileno())
450
 
        if self.supports_content_filtering() and filtered:
 
460
        if filtered and self.supports_content_filtering():
451
461
            filters = self._content_filter_stack(path)
452
462
            file_obj = filtered_input_file(file_obj, filters)
453
463
        return (file_obj, stat_value)
458
468
    def get_file_byname(self, filename, filtered=True):
459
469
        path = self.abspath(filename)
460
470
        f = file(path, 'rb')
461
 
        if self.supports_content_filtering() and filtered:
 
471
        if filtered and self.supports_content_filtering():
462
472
            filters = self._content_filter_stack(filename)
463
473
            return filtered_input_file(f, filters)
464
474
        else:
483
493
        incorrectly attributed to CURRENT_REVISION (but after committing, the
484
494
        attribution will be correct).
485
495
        """
486
 
        basis = self.basis_tree()
487
 
        basis.lock_read()
488
 
        try:
489
 
            changes = self.iter_changes(basis, True, [self.id2path(file_id)],
490
 
                require_versioned=True).next()
491
 
            changed_content, kind = changes[2], changes[6]
492
 
            if not changed_content:
493
 
                return basis.annotate_iter(file_id)
494
 
            if kind[1] is None:
495
 
                return None
496
 
            import annotate
497
 
            if kind[0] != 'file':
498
 
                old_lines = []
499
 
            else:
500
 
                old_lines = list(basis.annotate_iter(file_id))
501
 
            old = [old_lines]
502
 
            for tree in self.branch.repository.revision_trees(
503
 
                self.get_parent_ids()[1:]):
504
 
                if file_id not in tree:
505
 
                    continue
506
 
                old.append(list(tree.annotate_iter(file_id)))
507
 
            return annotate.reannotate(old, self.get_file(file_id).readlines(),
508
 
                                       default_revision)
509
 
        finally:
510
 
            basis.unlock()
 
496
        maybe_file_parent_keys = []
 
497
        for parent_id in self.get_parent_ids():
 
498
            try:
 
499
                parent_tree = self.revision_tree(parent_id)
 
500
            except errors.NoSuchRevisionInTree:
 
501
                parent_tree = self.branch.repository.revision_tree(parent_id)
 
502
            parent_tree.lock_read()
 
503
            try:
 
504
                if file_id not in parent_tree:
 
505
                    continue
 
506
                ie = parent_tree.inventory[file_id]
 
507
                if ie.kind != 'file':
 
508
                    # Note: this is slightly unnecessary, because symlinks and
 
509
                    # directories have a "text" which is the empty text, and we
 
510
                    # know that won't mess up annotations. But it seems cleaner
 
511
                    continue
 
512
                parent_text_key = (file_id, ie.revision)
 
513
                if parent_text_key not in maybe_file_parent_keys:
 
514
                    maybe_file_parent_keys.append(parent_text_key)
 
515
            finally:
 
516
                parent_tree.unlock()
 
517
        graph = _mod_graph.Graph(self.branch.repository.texts)
 
518
        heads = graph.heads(maybe_file_parent_keys)
 
519
        file_parent_keys = []
 
520
        for key in maybe_file_parent_keys:
 
521
            if key in heads:
 
522
                file_parent_keys.append(key)
 
523
 
 
524
        # Now we have the parents of this content
 
525
        annotator = self.branch.repository.texts.get_annotator()
 
526
        text = self.get_file(file_id).read()
 
527
        this_key =(file_id, default_revision)
 
528
        annotator.add_special_text(this_key, file_parent_keys, text)
 
529
        annotations = [(key[-1], line)
 
530
                       for key, line in annotator.annotate_flat(this_key)]
 
531
        return annotations
511
532
 
512
533
    def _get_ancestors(self, default_revision):
513
534
        ancestors = set([default_revision])
528
549
        else:
529
550
            parents = [last_rev]
530
551
        try:
531
 
            merges_file = self._transport.get('pending-merges')
 
552
            merges_bytes = self._transport.get_bytes('pending-merges')
532
553
        except errors.NoSuchFile:
533
554
            pass
534
555
        else:
535
 
            for l in merges_file.readlines():
 
556
            for l in osutils.split_lines(merges_bytes):
536
557
                revision_id = l.rstrip('\n')
537
558
                parents.append(revision_id)
538
559
        return parents
557
578
 
558
579
        revision
559
580
            If not None, the cloned tree will have its last revision set to
560
 
            revision, and and difference between the source trees last revision
 
581
            revision, and difference between the source trees last revision
561
582
            and this one merged in.
562
583
        """
563
584
        # assumes the target bzr dir format is compatible.
597
618
 
598
619
    def get_file_size(self, file_id):
599
620
        """See Tree.get_file_size"""
 
621
        # XXX: this returns the on-disk size; it should probably return the
 
622
        # canonical size
600
623
        try:
601
624
            return os.path.getsize(self.id2abspath(file_id))
602
625
        except OSError, e:
618
641
 
619
642
    def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
620
643
        file_id = self.path2id(path)
 
644
        if file_id is None:
 
645
            # For unversioned files on win32, we just assume they are not
 
646
            # executable
 
647
            return False
621
648
        return self._inventory[file_id].executable
622
649
 
623
650
    def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
733
760
            raise
734
761
        kind = _mapper(stat_result.st_mode)
735
762
        if kind == 'file':
736
 
            size = stat_result.st_size
737
 
            # try for a stat cache lookup
738
 
            executable = self._is_executable_from_path_and_stat(path, stat_result)
739
 
            return (kind, size, executable, self._sha_from_stat(
740
 
                path, stat_result))
 
763
            return self._file_content_summary(path, stat_result)
741
764
        elif kind == 'directory':
742
765
            # perhaps it looks like a plain directory, but it's really a
743
766
            # reference.
745
768
                kind = 'tree-reference'
746
769
            return kind, None, None, None
747
770
        elif kind == 'symlink':
748
 
            return ('symlink', None, None,
749
 
                    os.readlink(abspath.encode(osutils._fs_enc)
750
 
                                ).decode(osutils._fs_enc))
 
771
            target = osutils.readlink(abspath)
 
772
            return ('symlink', None, None, target)
751
773
        else:
752
774
            return (kind, None, None, None)
753
775
 
 
776
    def _file_content_summary(self, path, stat_result):
 
777
        size = stat_result.st_size
 
778
        executable = self._is_executable_from_path_and_stat(path, stat_result)
 
779
        # try for a stat cache lookup
 
780
        return ('file', size, executable, self._sha_from_stat(
 
781
            path, stat_result))
 
782
 
754
783
    def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
755
784
        """Common ghost checking functionality from set_parent_*.
756
785
 
876
905
 
877
906
    @needs_write_lock # because merge pulls data into the branch.
878
907
    def merge_from_branch(self, branch, to_revision=None, from_revision=None,
879
 
        merge_type=None):
 
908
                          merge_type=None, force=False):
880
909
        """Merge from a branch into this working tree.
881
910
 
882
911
        :param branch: The branch to merge from.
886
915
            branch.last_revision().
887
916
        """
888
917
        from bzrlib.merge import Merger, Merge3Merger
889
 
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
890
 
        try:
891
 
            merger = Merger(self.branch, this_tree=self, pb=pb)
892
 
            merger.pp = ProgressPhase("Merge phase", 5, pb)
893
 
            merger.pp.next_phase()
894
 
            # check that there are no
895
 
            # local alterations
896
 
            merger.check_basis(check_clean=True, require_commits=False)
897
 
            if to_revision is None:
898
 
                to_revision = _mod_revision.ensure_null(branch.last_revision())
899
 
            merger.other_rev_id = to_revision
900
 
            if _mod_revision.is_null(merger.other_rev_id):
901
 
                raise errors.NoCommits(branch)
902
 
            self.branch.fetch(branch, last_revision=merger.other_rev_id)
903
 
            merger.other_basis = merger.other_rev_id
904
 
            merger.other_tree = self.branch.repository.revision_tree(
905
 
                merger.other_rev_id)
906
 
            merger.other_branch = branch
907
 
            merger.pp.next_phase()
908
 
            if from_revision is None:
909
 
                merger.find_base()
910
 
            else:
911
 
                merger.set_base_revision(from_revision, branch)
912
 
            if merger.base_rev_id == merger.other_rev_id:
913
 
                raise errors.PointlessMerge
914
 
            merger.backup_files = False
915
 
            if merge_type is None:
916
 
                merger.merge_type = Merge3Merger
917
 
            else:
918
 
                merger.merge_type = merge_type
919
 
            merger.set_interesting_files(None)
920
 
            merger.show_base = False
921
 
            merger.reprocess = False
922
 
            conflicts = merger.do_merge()
923
 
            merger.set_pending()
924
 
        finally:
925
 
            pb.finished()
 
918
        merger = Merger(self.branch, this_tree=self)
 
919
        # check that there are no local alterations
 
920
        if not force and self.has_changes():
 
921
            raise errors.UncommittedChanges(self)
 
922
        if to_revision is None:
 
923
            to_revision = _mod_revision.ensure_null(branch.last_revision())
 
924
        merger.other_rev_id = to_revision
 
925
        if _mod_revision.is_null(merger.other_rev_id):
 
926
            raise errors.NoCommits(branch)
 
927
        self.branch.fetch(branch, last_revision=merger.other_rev_id)
 
928
        merger.other_basis = merger.other_rev_id
 
929
        merger.other_tree = self.branch.repository.revision_tree(
 
930
            merger.other_rev_id)
 
931
        merger.other_branch = branch
 
932
        if from_revision is None:
 
933
            merger.find_base()
 
934
        else:
 
935
            merger.set_base_revision(from_revision, branch)
 
936
        if merger.base_rev_id == merger.other_rev_id:
 
937
            raise errors.PointlessMerge
 
938
        merger.backup_files = False
 
939
        if merge_type is None:
 
940
            merger.merge_type = Merge3Merger
 
941
        else:
 
942
            merger.merge_type = merge_type
 
943
        merger.set_interesting_files(None)
 
944
        merger.show_base = False
 
945
        merger.reprocess = False
 
946
        conflicts = merger.do_merge()
 
947
        merger.set_pending()
926
948
        return conflicts
927
949
 
928
950
    @needs_read_lock
969
991
        return file_id
970
992
 
971
993
    def get_symlink_target(self, file_id):
972
 
        return os.readlink(self.id2abspath(file_id).encode(osutils._fs_enc))
 
994
        abspath = self.id2abspath(file_id)
 
995
        target = osutils.readlink(abspath)
 
996
        return target
973
997
 
974
998
    @needs_write_lock
975
999
    def subsume(self, other_tree):
1073
1097
        tree_transport = self.bzrdir.root_transport.clone(sub_path)
1074
1098
        if tree_transport.base != branch_transport.base:
1075
1099
            tree_bzrdir = format.initialize_on_transport(tree_transport)
1076
 
            branch.BranchReferenceFormat().initialize(tree_bzrdir, new_branch)
 
1100
            branch.BranchReferenceFormat().initialize(tree_bzrdir,
 
1101
                target_branch=new_branch)
1077
1102
        else:
1078
1103
            tree_bzrdir = branch_bzrdir
1079
 
        wt = tree_bzrdir.create_workingtree(NULL_REVISION)
 
1104
        wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
1080
1105
        wt.set_parent_ids(self.get_parent_ids())
1081
1106
        my_inv = self.inventory
1082
 
        child_inv = Inventory(root_id=None)
 
1107
        child_inv = inventory.Inventory(root_id=None)
1083
1108
        new_root = my_inv[file_id]
1084
1109
        my_inv.remove_recursive_id(file_id)
1085
1110
        new_root.parent_id = None
1110
1135
    def _kind(self, relpath):
1111
1136
        return osutils.file_kind(self.abspath(relpath))
1112
1137
 
1113
 
    def list_files(self, include_root=False):
1114
 
        """Recursively list all files as (path, class, kind, id, entry).
 
1138
    def list_files(self, include_root=False, from_dir=None, recursive=True):
 
1139
        """List all files as (path, class, kind, id, entry).
1115
1140
 
1116
1141
        Lists, but does not descend into unversioned directories.
1117
 
 
1118
1142
        This does not include files that have been deleted in this
1119
 
        tree.
 
1143
        tree. Skips the control directory.
1120
1144
 
1121
 
        Skips the control directory.
 
1145
        :param include_root: if True, return an entry for the root
 
1146
        :param from_dir: start from this directory or None for the root
 
1147
        :param recursive: whether to recurse into subdirectories or not
1122
1148
        """
1123
1149
        # list_files is an iterator, so @needs_read_lock doesn't work properly
1124
1150
        # with it. So callers should be careful to always read_lock the tree.
1126
1152
            raise errors.ObjectNotLocked(self)
1127
1153
 
1128
1154
        inv = self.inventory
1129
 
        if include_root is True:
 
1155
        if from_dir is None and include_root is True:
1130
1156
            yield ('', 'V', 'directory', inv.root.file_id, inv.root)
1131
1157
        # Convert these into local objects to save lookup times
1132
1158
        pathjoin = osutils.pathjoin
1139
1165
        fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
1140
1166
 
1141
1167
        # directory file_id, relative path, absolute path, reverse sorted children
1142
 
        children = os.listdir(self.basedir)
 
1168
        if from_dir is not None:
 
1169
            from_dir_id = inv.path2id(from_dir)
 
1170
            if from_dir_id is None:
 
1171
                # Directory not versioned
 
1172
                return
 
1173
            from_dir_abspath = pathjoin(self.basedir, from_dir)
 
1174
        else:
 
1175
            from_dir_id = inv.root.file_id
 
1176
            from_dir_abspath = self.basedir
 
1177
        children = os.listdir(from_dir_abspath)
1143
1178
        children.sort()
1144
1179
        # jam 20060527 The kernel sized tree seems equivalent whether we
1145
1180
        # use a deque and popleft to keep them sorted, or if we use a plain
1146
1181
        # list and just reverse() them.
1147
1182
        children = collections.deque(children)
1148
 
        stack = [(inv.root.file_id, u'', self.basedir, children)]
 
1183
        stack = [(from_dir_id, u'', from_dir_abspath, children)]
1149
1184
        while stack:
1150
1185
            from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
1151
1186
 
1209
1244
                if fk != 'directory':
1210
1245
                    continue
1211
1246
 
1212
 
                # But do this child first
1213
 
                new_children = os.listdir(fap)
1214
 
                new_children.sort()
1215
 
                new_children = collections.deque(new_children)
1216
 
                stack.append((f_ie.file_id, fp, fap, new_children))
1217
 
                # Break out of inner loop,
1218
 
                # so that we start outer loop with child
1219
 
                break
 
1247
                # But do this child first if recursing down
 
1248
                if recursive:
 
1249
                    new_children = os.listdir(fap)
 
1250
                    new_children.sort()
 
1251
                    new_children = collections.deque(new_children)
 
1252
                    stack.append((f_ie.file_id, fp, fap, new_children))
 
1253
                    # Break out of inner loop,
 
1254
                    # so that we start outer loop with child
 
1255
                    break
1220
1256
            else:
1221
1257
                # if we finished all children, pop it off the stack
1222
1258
                stack.pop()
1400
1436
        inv = self.inventory
1401
1437
        for entry in moved:
1402
1438
            try:
1403
 
                self._move_entry(_RenameEntry(entry.to_rel, entry.from_id,
 
1439
                self._move_entry(WorkingTree._RenameEntry(
 
1440
                    entry.to_rel, entry.from_id,
1404
1441
                    entry.to_tail, entry.to_parent_id, entry.from_rel,
1405
1442
                    entry.from_tail, entry.from_parent_id,
1406
1443
                    entry.only_change_inv))
1457
1494
        from_tail = splitpath(from_rel)[-1]
1458
1495
        from_id = inv.path2id(from_rel)
1459
1496
        if from_id is None:
1460
 
            raise errors.BzrRenameFailedError(from_rel,to_rel,
1461
 
                errors.NotVersionedError(path=str(from_rel)))
1462
 
        from_entry = inv[from_id]
 
1497
            # if file is missing in the inventory maybe it's in the basis_tree
 
1498
            basis_tree = self.branch.basis_tree()
 
1499
            from_id = basis_tree.path2id(from_rel)
 
1500
            if from_id is None:
 
1501
                raise errors.BzrRenameFailedError(from_rel,to_rel,
 
1502
                    errors.NotVersionedError(path=str(from_rel)))
 
1503
            # put entry back in the inventory so we can rename it
 
1504
            from_entry = basis_tree.inventory[from_id].copy()
 
1505
            inv.add(from_entry)
 
1506
        else:
 
1507
            from_entry = inv[from_id]
1463
1508
        from_parent_id = from_entry.parent_id
1464
1509
        to_dir, to_tail = os.path.split(to_rel)
1465
1510
        to_dir_id = inv.path2id(to_dir)
1527
1572
        :raises: NoSuchId if any fileid is not currently versioned.
1528
1573
        """
1529
1574
        for file_id in file_ids:
 
1575
            if file_id not in self._inventory:
 
1576
                raise errors.NoSuchId(self, file_id)
 
1577
        for file_id in file_ids:
1530
1578
            if self._inventory.has_id(file_id):
1531
1579
                self._inventory.remove_recursive_id(file_id)
1532
 
            else:
1533
 
                raise errors.NoSuchId(self, file_id)
1534
1580
        if len(file_ids):
1535
1581
            # in the future this should just set a dirty bit to wait for the
1536
1582
            # final unlock. However, until all methods of workingtree start
1555
1601
 
1556
1602
    @needs_write_lock
1557
1603
    def pull(self, source, overwrite=False, stop_revision=None,
1558
 
             change_reporter=None, possible_transports=None):
1559
 
        top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
1604
             change_reporter=None, possible_transports=None, local=False):
1560
1605
        source.lock_read()
1561
1606
        try:
1562
 
            pp = ProgressPhase("Pull phase", 2, top_pb)
1563
 
            pp.next_phase()
1564
1607
            old_revision_info = self.branch.last_revision_info()
1565
1608
            basis_tree = self.basis_tree()
1566
1609
            count = self.branch.pull(source, overwrite, stop_revision,
1567
 
                                     possible_transports=possible_transports)
 
1610
                                     possible_transports=possible_transports,
 
1611
                                     local=local)
1568
1612
            new_revision_info = self.branch.last_revision_info()
1569
1613
            if new_revision_info != old_revision_info:
1570
 
                pp.next_phase()
1571
1614
                repository = self.branch.repository
1572
 
                pb = bzrlib.ui.ui_factory.nested_progress_bar()
1573
1615
                basis_tree.lock_read()
1574
1616
                try:
1575
1617
                    new_basis_tree = self.branch.basis_tree()
1578
1620
                                new_basis_tree,
1579
1621
                                basis_tree,
1580
1622
                                this_tree=self,
1581
 
                                pb=pb,
 
1623
                                pb=None,
1582
1624
                                change_reporter=change_reporter)
1583
 
                    if (basis_tree.inventory.root is None and
1584
 
                        new_basis_tree.inventory.root is not None):
1585
 
                        self.set_root_id(new_basis_tree.get_root_id())
 
1625
                    basis_root_id = basis_tree.get_root_id()
 
1626
                    new_root_id = new_basis_tree.get_root_id()
 
1627
                    if basis_root_id != new_root_id:
 
1628
                        self.set_root_id(new_root_id)
1586
1629
                finally:
1587
 
                    pb.finished()
1588
1630
                    basis_tree.unlock()
1589
1631
                # TODO - dedup parents list with things merged by pull ?
1590
1632
                # reuse the revisiontree we merged against to set the new
1603
1645
            return count
1604
1646
        finally:
1605
1647
            source.unlock()
1606
 
            top_pb.finished()
1607
1648
 
1608
1649
    @needs_write_lock
1609
1650
    def put_file_bytes_non_atomic(self, file_id, bytes):
1635
1676
 
1636
1677
            fl = []
1637
1678
            for subf in os.listdir(dirabs):
1638
 
                if subf == '.bzr':
 
1679
                if self.bzrdir.is_control_filename(subf):
1639
1680
                    continue
1640
1681
                if subf not in dir_entry.children:
1641
1682
                    try:
1694
1735
        r"""Check whether the filename matches an ignore pattern.
1695
1736
 
1696
1737
        Patterns containing '/' or '\' need to match the whole path;
1697
 
        others match against only the last component.
 
1738
        others match against only the last component.  Patterns starting
 
1739
        with '!' are ignore exceptions.  Exceptions take precedence
 
1740
        over regular patterns and cause the filename to not be ignored.
1698
1741
 
1699
1742
        If the file is ignored, returns the pattern which caused it to
1700
1743
        be ignored, otherwise None.  So this can simply be used as a
1701
1744
        boolean if desired."""
1702
1745
        if getattr(self, '_ignoreglobster', None) is None:
1703
 
            self._ignoreglobster = globbing.Globster(self.get_ignore_list())
 
1746
            self._ignoreglobster = globbing.ExceptionGlobster(self.get_ignore_list())
1704
1747
        return self._ignoreglobster.match(filename)
1705
1748
 
1706
1749
    def kind(self, file_id):
1756
1799
            raise errors.ObjectNotLocked(self)
1757
1800
 
1758
1801
    def lock_read(self):
1759
 
        """See Branch.lock_read, and WorkingTree.unlock."""
 
1802
        """Lock the tree for reading.
 
1803
 
 
1804
        This also locks the branch, and can be unlocked via self.unlock().
 
1805
 
 
1806
        :return: A bzrlib.lock.LogicalLockResult.
 
1807
        """
1760
1808
        if not self.is_locked():
1761
1809
            self._reset_data()
1762
1810
        self.branch.lock_read()
1763
1811
        try:
1764
 
            return self._control_files.lock_read()
 
1812
            self._control_files.lock_read()
 
1813
            return LogicalLockResult(self.unlock)
1765
1814
        except:
1766
1815
            self.branch.unlock()
1767
1816
            raise
1768
1817
 
1769
1818
    def lock_tree_write(self):
1770
 
        """See MutableTree.lock_tree_write, and WorkingTree.unlock."""
 
1819
        """See MutableTree.lock_tree_write, and WorkingTree.unlock.
 
1820
 
 
1821
        :return: A bzrlib.lock.LogicalLockResult.
 
1822
        """
1771
1823
        if not self.is_locked():
1772
1824
            self._reset_data()
1773
1825
        self.branch.lock_read()
1774
1826
        try:
1775
 
            return self._control_files.lock_write()
 
1827
            self._control_files.lock_write()
 
1828
            return LogicalLockResult(self.unlock)
1776
1829
        except:
1777
1830
            self.branch.unlock()
1778
1831
            raise
1779
1832
 
1780
1833
    def lock_write(self):
1781
 
        """See MutableTree.lock_write, and WorkingTree.unlock."""
 
1834
        """See MutableTree.lock_write, and WorkingTree.unlock.
 
1835
 
 
1836
        :return: A bzrlib.lock.LogicalLockResult.
 
1837
        """
1782
1838
        if not self.is_locked():
1783
1839
            self._reset_data()
1784
1840
        self.branch.lock_write()
1785
1841
        try:
1786
 
            return self._control_files.lock_write()
 
1842
            self._control_files.lock_write()
 
1843
            return LogicalLockResult(self.unlock)
1787
1844
        except:
1788
1845
            self.branch.unlock()
1789
1846
            raise
1797
1854
    def _reset_data(self):
1798
1855
        """Reset transient data that cannot be revalidated."""
1799
1856
        self._inventory_is_modified = False
1800
 
        result = self._deserialize(self._transport.get('inventory'))
 
1857
        f = self._transport.get('inventory')
 
1858
        try:
 
1859
            result = self._deserialize(f)
 
1860
        finally:
 
1861
            f.close()
1801
1862
        self._set_inventory(result, dirty=False)
1802
1863
 
1803
1864
    @needs_tree_write_lock
1850
1911
            # revision_id is set. We must check for this full string, because a
1851
1912
            # root node id can legitimately look like 'revision_id' but cannot
1852
1913
            # contain a '"'.
1853
 
            xml = self.branch.repository.get_inventory_xml(new_revision)
 
1914
            xml = self.branch.repository._get_inventory_xml(new_revision)
1854
1915
            firstline = xml.split('\n', 1)[0]
1855
1916
            if (not 'revision_id="' in firstline or
1856
1917
                'format="7"' not in firstline):
1857
 
                inv = self.branch.repository.deserialise_inventory(
1858
 
                    new_revision, xml)
 
1918
                inv = self.branch.repository._serializer.read_inventory_from_string(
 
1919
                    xml, new_revision)
1859
1920
                xml = self._create_basis_xml_from_inventory(new_revision, inv)
1860
1921
            self._write_basis_inventory(xml)
1861
1922
        except (errors.NoSuchRevision, errors.RevisionNotPresent):
1879
1940
        # binary.
1880
1941
        if self._inventory_is_modified:
1881
1942
            raise errors.InventoryModified(self)
1882
 
        result = self._deserialize(self._transport.get('inventory'))
 
1943
        f = self._transport.get('inventory')
 
1944
        try:
 
1945
            result = self._deserialize(f)
 
1946
        finally:
 
1947
            f.close()
1883
1948
        self._set_inventory(result, dirty=False)
1884
1949
        return result
1885
1950
 
1900
1965
 
1901
1966
        new_files=set()
1902
1967
        unknown_nested_files=set()
 
1968
        if to_file is None:
 
1969
            to_file = sys.stdout
1903
1970
 
1904
1971
        def recurse_directory_to_add_files(directory):
1905
1972
            # Recurse directory and add all files
1906
1973
            # so we can check if they have changed.
1907
 
            for parent_info, file_infos in\
1908
 
                self.walkdirs(directory):
 
1974
            for parent_info, file_infos in self.walkdirs(directory):
1909
1975
                for relpath, basename, kind, lstat, fileid, kind in file_infos:
1910
1976
                    # Is it versioned or ignored?
1911
1977
                    if self.path2id(relpath) or self.is_ignored(relpath):
1946
2012
                            # ... but not ignored
1947
2013
                            has_changed_files = True
1948
2014
                            break
1949
 
                    elif content_change and (kind[1] is not None):
1950
 
                        # Versioned and changed, but not deleted
 
2015
                    elif (content_change and (kind[1] is not None) and
 
2016
                            osutils.is_inside_any(files, path[1])):
 
2017
                        # Versioned and changed, but not deleted, and still
 
2018
                        # in one of the dirs to be deleted.
1951
2019
                        has_changed_files = True
1952
2020
                        break
1953
2021
 
1961
2029
                        tree_delta.unversioned.extend((unknown_file,))
1962
2030
                raise errors.BzrRemoveChangedFilesError(tree_delta)
1963
2031
 
1964
 
        # Build inv_delta and delete files where applicaple,
 
2032
        # Build inv_delta and delete files where applicable,
1965
2033
        # do this before any modifications to inventory.
1966
2034
        for f in files:
1967
2035
            fid = self.path2id(f)
1975
2043
                        new_status = 'I'
1976
2044
                    else:
1977
2045
                        new_status = '?'
1978
 
                    textui.show_status(new_status, self.kind(fid), f,
1979
 
                                       to_file=to_file)
 
2046
                    # XXX: Really should be a more abstract reporter interface
 
2047
                    kind_ch = osutils.kind_marker(self.kind(fid))
 
2048
                    to_file.write(new_status + '       ' + f + kind_ch + '\n')
1980
2049
                # Unversion file
1981
2050
                inv_delta.append((f, None, fid, None))
1982
2051
                message = "removed %s" % (f,)
2005
2074
 
2006
2075
    @needs_tree_write_lock
2007
2076
    def revert(self, filenames=None, old_tree=None, backups=True,
2008
 
               pb=DummyProgress(), report_changes=False):
 
2077
               pb=None, report_changes=False):
2009
2078
        from bzrlib.conflicts import resolve
2010
2079
        if filenames == []:
2011
2080
            filenames = None
2024
2093
            if filenames is None and len(self.get_parent_ids()) > 1:
2025
2094
                parent_trees = []
2026
2095
                last_revision = self.last_revision()
2027
 
                if last_revision != NULL_REVISION:
 
2096
                if last_revision != _mod_revision.NULL_REVISION:
2028
2097
                    if basis_tree is None:
2029
2098
                        basis_tree = self.basis_tree()
2030
2099
                        basis_tree.lock_read()
2068
2137
    def set_inventory(self, new_inventory_list):
2069
2138
        from bzrlib.inventory import (Inventory,
2070
2139
                                      InventoryDirectory,
2071
 
                                      InventoryEntry,
2072
2140
                                      InventoryFile,
2073
2141
                                      InventoryLink)
2074
2142
        inv = Inventory(self.get_root_id())
2134
2202
        """
2135
2203
        raise NotImplementedError(self.unlock)
2136
2204
 
2137
 
    def update(self, change_reporter=None, possible_transports=None):
 
2205
    _marker = object()
 
2206
 
 
2207
    def update(self, change_reporter=None, possible_transports=None,
 
2208
               revision=None, old_tip=_marker):
2138
2209
        """Update a working tree along its branch.
2139
2210
 
2140
2211
        This will update the branch if its bound too, which means we have
2158
2229
        - Merge current state -> basis tree of the master w.r.t. the old tree
2159
2230
          basis.
2160
2231
        - Do a 'normal' merge of the old branch basis if it is relevant.
 
2232
 
 
2233
        :param revision: The target revision to update to. Must be in the
 
2234
            revision history.
 
2235
        :param old_tip: If branch.update() has already been run, the value it
 
2236
            returned (old tip of the branch or None). _marker is used
 
2237
            otherwise.
2161
2238
        """
2162
2239
        if self.branch.get_bound_location() is not None:
2163
2240
            self.lock_write()
2164
 
            update_branch = True
 
2241
            update_branch = (old_tip is self._marker)
2165
2242
        else:
2166
2243
            self.lock_tree_write()
2167
2244
            update_branch = False
2169
2246
            if update_branch:
2170
2247
                old_tip = self.branch.update(possible_transports)
2171
2248
            else:
2172
 
                old_tip = None
2173
 
            return self._update_tree(old_tip, change_reporter)
 
2249
                if old_tip is self._marker:
 
2250
                    old_tip = None
 
2251
            return self._update_tree(old_tip, change_reporter, revision)
2174
2252
        finally:
2175
2253
            self.unlock()
2176
2254
 
2177
2255
    @needs_tree_write_lock
2178
 
    def _update_tree(self, old_tip=None, change_reporter=None):
 
2256
    def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
2179
2257
        """Update a tree to the master branch.
2180
2258
 
2181
2259
        :param old_tip: if supplied, the previous tip revision the branch,
2191
2269
        # We MUST save it even if an error occurs, because otherwise the users
2192
2270
        # local work is unreferenced and will appear to have been lost.
2193
2271
        #
2194
 
        result = 0
 
2272
        nb_conflicts = 0
2195
2273
        try:
2196
2274
            last_rev = self.get_parent_ids()[0]
2197
2275
        except IndexError:
2198
2276
            last_rev = _mod_revision.NULL_REVISION
2199
 
        if last_rev != _mod_revision.ensure_null(self.branch.last_revision()):
2200
 
            # merge tree state up to new branch tip.
 
2277
        if revision is None:
 
2278
            revision = self.branch.last_revision()
 
2279
 
 
2280
        old_tip = old_tip or _mod_revision.NULL_REVISION
 
2281
 
 
2282
        if not _mod_revision.is_null(old_tip) and old_tip != last_rev:
 
2283
            # the branch we are bound to was updated
 
2284
            # merge those changes in first
 
2285
            base_tree  = self.basis_tree()
 
2286
            other_tree = self.branch.repository.revision_tree(old_tip)
 
2287
            nb_conflicts = merge.merge_inner(self.branch, other_tree,
 
2288
                                             base_tree, this_tree=self,
 
2289
                                             change_reporter=change_reporter)
 
2290
            if nb_conflicts:
 
2291
                self.add_parent_tree((old_tip, other_tree))
 
2292
                trace.note('Rerun update after fixing the conflicts.')
 
2293
                return nb_conflicts
 
2294
 
 
2295
        if last_rev != _mod_revision.ensure_null(revision):
 
2296
            # the working tree is up to date with the branch
 
2297
            # we can merge the specified revision from master
 
2298
            to_tree = self.branch.repository.revision_tree(revision)
 
2299
            to_root_id = to_tree.get_root_id()
 
2300
 
2201
2301
            basis = self.basis_tree()
2202
2302
            basis.lock_read()
2203
2303
            try:
2204
 
                to_tree = self.branch.basis_tree()
2205
 
                if basis.inventory.root is None:
2206
 
                    self.set_root_id(to_tree.get_root_id())
 
2304
                if (basis.inventory.root is None
 
2305
                    or basis.inventory.root.file_id != to_root_id):
 
2306
                    self.set_root_id(to_root_id)
2207
2307
                    self.flush()
2208
 
                result += merge.merge_inner(
2209
 
                                      self.branch,
2210
 
                                      to_tree,
2211
 
                                      basis,
2212
 
                                      this_tree=self,
2213
 
                                      change_reporter=change_reporter)
2214
2308
            finally:
2215
2309
                basis.unlock()
 
2310
 
 
2311
            # determine the branch point
 
2312
            graph = self.branch.repository.get_graph()
 
2313
            base_rev_id = graph.find_unique_lca(self.branch.last_revision(),
 
2314
                                                last_rev)
 
2315
            base_tree = self.branch.repository.revision_tree(base_rev_id)
 
2316
 
 
2317
            nb_conflicts = merge.merge_inner(self.branch, to_tree, base_tree,
 
2318
                                             this_tree=self,
 
2319
                                             change_reporter=change_reporter)
 
2320
            self.set_last_revision(revision)
2216
2321
            # TODO - dedup parents list with things merged by pull ?
2217
2322
            # reuse the tree we've updated to to set the basis:
2218
 
            parent_trees = [(self.branch.last_revision(), to_tree)]
 
2323
            parent_trees = [(revision, to_tree)]
2219
2324
            merges = self.get_parent_ids()[1:]
2220
2325
            # Ideally we ask the tree for the trees here, that way the working
2221
 
            # tree can decide whether to give us teh entire tree or give us a
 
2326
            # tree can decide whether to give us the entire tree or give us a
2222
2327
            # lazy initialised tree. dirstate for instance will have the trees
2223
2328
            # in ram already, whereas a last-revision + basis-inventory tree
2224
2329
            # will not, but also does not need them when setting parents.
2225
2330
            for parent in merges:
2226
2331
                parent_trees.append(
2227
2332
                    (parent, self.branch.repository.revision_tree(parent)))
2228
 
            if (old_tip is not None and not _mod_revision.is_null(old_tip)):
 
2333
            if not _mod_revision.is_null(old_tip):
2229
2334
                parent_trees.append(
2230
2335
                    (old_tip, self.branch.repository.revision_tree(old_tip)))
2231
2336
            self.set_parent_trees(parent_trees)
2232
2337
            last_rev = parent_trees[0][0]
2233
 
        else:
2234
 
            # the working tree had the same last-revision as the master
2235
 
            # branch did. We may still have pivot local work from the local
2236
 
            # branch into old_tip:
2237
 
            if (old_tip is not None and not _mod_revision.is_null(old_tip)):
2238
 
                self.add_parent_tree_id(old_tip)
2239
 
        if (old_tip is not None and not _mod_revision.is_null(old_tip)
2240
 
            and old_tip != last_rev):
2241
 
            # our last revision was not the prior branch last revision
2242
 
            # and we have converted that last revision to a pending merge.
2243
 
            # base is somewhere between the branch tip now
2244
 
            # and the now pending merge
2245
 
 
2246
 
            # Since we just modified the working tree and inventory, flush out
2247
 
            # the current state, before we modify it again.
2248
 
            # TODO: jam 20070214 WorkingTree3 doesn't require this, dirstate
2249
 
            #       requires it only because TreeTransform directly munges the
2250
 
            #       inventory and calls tree._write_inventory(). Ultimately we
2251
 
            #       should be able to remove this extra flush.
2252
 
            self.flush()
2253
 
            graph = self.branch.repository.get_graph()
2254
 
            base_rev_id = graph.find_unique_lca(self.branch.last_revision(),
2255
 
                                                old_tip)
2256
 
            base_tree = self.branch.repository.revision_tree(base_rev_id)
2257
 
            other_tree = self.branch.repository.revision_tree(old_tip)
2258
 
            result += merge.merge_inner(
2259
 
                                  self.branch,
2260
 
                                  other_tree,
2261
 
                                  base_tree,
2262
 
                                  this_tree=self,
2263
 
                                  change_reporter=change_reporter)
2264
 
        return result
 
2338
        return nb_conflicts
2265
2339
 
2266
2340
    def _write_hashcache_if_dirty(self):
2267
2341
        """Write out the hashcache if it is dirty."""
2367
2441
                    bzrdir_loc = bisect_left(cur_disk_dir_content,
2368
2442
                        ('.bzr', '.bzr'))
2369
2443
                    if (bzrdir_loc < len(cur_disk_dir_content)
2370
 
                        and cur_disk_dir_content[bzrdir_loc][0] == '.bzr'):
 
2444
                        and self.bzrdir.is_control_filename(
 
2445
                            cur_disk_dir_content[bzrdir_loc][0])):
2371
2446
                        # we dont yield the contents of, or, .bzr itself.
2372
2447
                        del cur_disk_dir_content[bzrdir_loc]
2373
2448
            if inv_finished:
2507
2582
        return un_resolved, resolved
2508
2583
 
2509
2584
    @needs_read_lock
2510
 
    def _check(self):
 
2585
    def _check(self, references):
 
2586
        """Check the tree for consistency.
 
2587
 
 
2588
        :param references: A dict with keys matching the items returned by
 
2589
            self._get_check_refs(), and values from looking those keys up in
 
2590
            the repository.
 
2591
        """
2511
2592
        tree_basis = self.basis_tree()
2512
2593
        tree_basis.lock_read()
2513
2594
        try:
2514
 
            repo_basis = self.branch.repository.revision_tree(
2515
 
                self.last_revision())
 
2595
            repo_basis = references[('trees', self.last_revision())]
2516
2596
            if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2517
2597
                raise errors.BzrCheckError(
2518
2598
                    "Mismatched basis inventory content.")
2531
2611
        """
2532
2612
        return
2533
2613
 
2534
 
    @needs_read_lock
2535
2614
    def _get_rules_searcher(self, default_searcher):
2536
2615
        """See Tree._get_rules_searcher."""
2537
2616
        if self._rules_searcher is None:
2564
2643
        if self._inventory is None:
2565
2644
            self.read_working_inventory()
2566
2645
 
 
2646
    def _get_check_refs(self):
 
2647
        """Return the references needed to perform a check of this tree."""
 
2648
        return [('trees', self.last_revision())]
 
2649
 
2567
2650
    def lock_tree_write(self):
2568
2651
        """See WorkingTree.lock_tree_write().
2569
2652
 
2570
2653
        In Format2 WorkingTrees we have a single lock for the branch and tree
2571
2654
        so lock_tree_write() degrades to lock_write().
 
2655
 
 
2656
        :return: An object with an unlock method which will release the lock
 
2657
            obtained.
2572
2658
        """
2573
2659
        self.branch.lock_write()
2574
2660
        try:
2575
 
            return self._control_files.lock_write()
 
2661
            self._control_files.lock_write()
 
2662
            return self
2576
2663
        except:
2577
2664
            self.branch.unlock()
2578
2665
            raise
2615
2702
 
2616
2703
    def _change_last_revision(self, revision_id):
2617
2704
        """See WorkingTree._change_last_revision."""
2618
 
        if revision_id is None or revision_id == NULL_REVISION:
 
2705
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
2619
2706
            try:
2620
2707
                self._transport.delete('last-revision')
2621
2708
            except errors.NoSuchFile:
2626
2713
                mode=self.bzrdir._get_file_mode())
2627
2714
            return True
2628
2715
 
 
2716
    def _get_check_refs(self):
 
2717
        """Return the references needed to perform a check of this tree."""
 
2718
        return [('trees', self.last_revision())]
 
2719
 
2629
2720
    @needs_tree_write_lock
2630
2721
    def set_conflicts(self, conflicts):
2631
2722
        self._put_rio('conflicts', conflicts.to_stanzas(),
2708
2799
        """Return the format for the working tree object in a_bzrdir."""
2709
2800
        try:
2710
2801
            transport = a_bzrdir.get_workingtree_transport(None)
2711
 
            format_string = transport.get("format").read()
 
2802
            format_string = transport.get_bytes("format")
2712
2803
            return klass._formats[format_string]
2713
2804
        except errors.NoSuchFile:
2714
2805
            raise errors.NoWorkingTree(base=transport.base)
2785
2876
        no working tree.  (See bug #43064).
2786
2877
        """
2787
2878
        sio = StringIO()
2788
 
        inv = Inventory()
 
2879
        inv = inventory.Inventory()
2789
2880
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
2790
2881
        sio.seek(0)
2791
2882
        transport.put_file('inventory', sio, file_mode)
2807
2898
            branch.generate_revision_history(revision_id)
2808
2899
        finally:
2809
2900
            branch.unlock()
2810
 
        inv = Inventory()
 
2901
        inv = inventory.Inventory()
2811
2902
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2812
2903
                         branch,
2813
2904
                         inv,
2930
3021
            # only set an explicit root id if there is one to set.
2931
3022
            if basis_tree.inventory.root is not None:
2932
3023
                wt.set_root_id(basis_tree.get_root_id())
2933
 
            if revision_id == NULL_REVISION:
 
3024
            if revision_id == _mod_revision.NULL_REVISION:
2934
3025
                wt.set_parent_trees([])
2935
3026
            else:
2936
3027
                wt.set_parent_trees([(revision_id, basis_tree)])
2943
3034
        return wt
2944
3035
 
2945
3036
    def _initial_inventory(self):
2946
 
        return Inventory()
 
3037
        return inventory.Inventory()
2947
3038
 
2948
3039
    def __init__(self):
2949
3040
        super(WorkingTreeFormat3, self).__init__()
2978
3069
        return self.get_format_string()
2979
3070
 
2980
3071
 
2981
 
__default_format = WorkingTreeFormat4()
 
3072
__default_format = WorkingTreeFormat6()
2982
3073
WorkingTreeFormat.register_format(__default_format)
2983
3074
WorkingTreeFormat.register_format(WorkingTreeFormat5())
 
3075
WorkingTreeFormat.register_format(WorkingTreeFormat4())
2984
3076
WorkingTreeFormat.register_format(WorkingTreeFormat3())
2985
3077
WorkingTreeFormat.set_default_format(__default_format)
2986
3078
# formats which have no format string are not discoverable