~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Parth Malwankar
  • Date: 2010-06-12 02:58:42 UTC
  • mto: This revision was merged to the branch mainline in revision 5291.
  • Revision ID: parth.malwankar@gmail.com-20100612025842-amc5em04efepm069
reduced STEP in recordcounter to allow more frequent updates
on progress bar for slower connections.

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)
454
464
 
455
465
    def get_file_text(self, file_id, path=None, filtered=True):
456
 
        return self.get_file(file_id, path=path, filtered=filtered).read()
 
466
        my_file = self.get_file(file_id, path=path, filtered=filtered)
 
467
        try:
 
468
            return my_file.read()
 
469
        finally:
 
470
            my_file.close()
457
471
 
458
472
    def get_file_byname(self, filename, filtered=True):
459
473
        path = self.abspath(filename)
460
474
        f = file(path, 'rb')
461
 
        if self.supports_content_filtering() and filtered:
 
475
        if filtered and self.supports_content_filtering():
462
476
            filters = self._content_filter_stack(filename)
463
477
            return filtered_input_file(f, filters)
464
478
        else:
483
497
        incorrectly attributed to CURRENT_REVISION (but after committing, the
484
498
        attribution will be correct).
485
499
        """
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()
 
500
        maybe_file_parent_keys = []
 
501
        for parent_id in self.get_parent_ids():
 
502
            try:
 
503
                parent_tree = self.revision_tree(parent_id)
 
504
            except errors.NoSuchRevisionInTree:
 
505
                parent_tree = self.branch.repository.revision_tree(parent_id)
 
506
            parent_tree.lock_read()
 
507
            try:
 
508
                if file_id not in parent_tree:
 
509
                    continue
 
510
                ie = parent_tree.inventory[file_id]
 
511
                if ie.kind != 'file':
 
512
                    # Note: this is slightly unnecessary, because symlinks and
 
513
                    # directories have a "text" which is the empty text, and we
 
514
                    # know that won't mess up annotations. But it seems cleaner
 
515
                    continue
 
516
                parent_text_key = (file_id, ie.revision)
 
517
                if parent_text_key not in maybe_file_parent_keys:
 
518
                    maybe_file_parent_keys.append(parent_text_key)
 
519
            finally:
 
520
                parent_tree.unlock()
 
521
        graph = _mod_graph.Graph(self.branch.repository.texts)
 
522
        heads = graph.heads(maybe_file_parent_keys)
 
523
        file_parent_keys = []
 
524
        for key in maybe_file_parent_keys:
 
525
            if key in heads:
 
526
                file_parent_keys.append(key)
 
527
 
 
528
        # Now we have the parents of this content
 
529
        annotator = self.branch.repository.texts.get_annotator()
 
530
        text = self.get_file_text(file_id)
 
531
        this_key =(file_id, default_revision)
 
532
        annotator.add_special_text(this_key, file_parent_keys, text)
 
533
        annotations = [(key[-1], line)
 
534
                       for key, line in annotator.annotate_flat(this_key)]
 
535
        return annotations
511
536
 
512
537
    def _get_ancestors(self, default_revision):
513
538
        ancestors = set([default_revision])
528
553
        else:
529
554
            parents = [last_rev]
530
555
        try:
531
 
            merges_file = self._transport.get('pending-merges')
 
556
            merges_bytes = self._transport.get_bytes('pending-merges')
532
557
        except errors.NoSuchFile:
533
558
            pass
534
559
        else:
535
 
            for l in merges_file.readlines():
 
560
            for l in osutils.split_lines(merges_bytes):
536
561
                revision_id = l.rstrip('\n')
537
562
                parents.append(revision_id)
538
563
        return parents
557
582
 
558
583
        revision
559
584
            If not None, the cloned tree will have its last revision set to
560
 
            revision, and and difference between the source trees last revision
 
585
            revision, and difference between the source trees last revision
561
586
            and this one merged in.
562
587
        """
563
588
        # assumes the target bzr dir format is compatible.
597
622
 
598
623
    def get_file_size(self, file_id):
599
624
        """See Tree.get_file_size"""
 
625
        # XXX: this returns the on-disk size; it should probably return the
 
626
        # canonical size
600
627
        try:
601
628
            return os.path.getsize(self.id2abspath(file_id))
602
629
        except OSError, e:
618
645
 
619
646
    def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
620
647
        file_id = self.path2id(path)
 
648
        if file_id is None:
 
649
            # For unversioned files on win32, we just assume they are not
 
650
            # executable
 
651
            return False
621
652
        return self._inventory[file_id].executable
622
653
 
623
654
    def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
733
764
            raise
734
765
        kind = _mapper(stat_result.st_mode)
735
766
        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))
 
767
            return self._file_content_summary(path, stat_result)
741
768
        elif kind == 'directory':
742
769
            # perhaps it looks like a plain directory, but it's really a
743
770
            # reference.
745
772
                kind = 'tree-reference'
746
773
            return kind, None, None, None
747
774
        elif kind == 'symlink':
748
 
            return ('symlink', None, None,
749
 
                    os.readlink(abspath.encode(osutils._fs_enc)
750
 
                                ).decode(osutils._fs_enc))
 
775
            target = osutils.readlink(abspath)
 
776
            return ('symlink', None, None, target)
751
777
        else:
752
778
            return (kind, None, None, None)
753
779
 
 
780
    def _file_content_summary(self, path, stat_result):
 
781
        size = stat_result.st_size
 
782
        executable = self._is_executable_from_path_and_stat(path, stat_result)
 
783
        # try for a stat cache lookup
 
784
        return ('file', size, executable, self._sha_from_stat(
 
785
            path, stat_result))
 
786
 
754
787
    def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
755
788
        """Common ghost checking functionality from set_parent_*.
756
789
 
876
909
 
877
910
    @needs_write_lock # because merge pulls data into the branch.
878
911
    def merge_from_branch(self, branch, to_revision=None, from_revision=None,
879
 
        merge_type=None):
 
912
                          merge_type=None, force=False):
880
913
        """Merge from a branch into this working tree.
881
914
 
882
915
        :param branch: The branch to merge from.
886
919
            branch.last_revision().
887
920
        """
888
921
        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()
 
922
        merger = Merger(self.branch, this_tree=self)
 
923
        # check that there are no local alterations
 
924
        if not force and self.has_changes():
 
925
            raise errors.UncommittedChanges(self)
 
926
        if to_revision is None:
 
927
            to_revision = _mod_revision.ensure_null(branch.last_revision())
 
928
        merger.other_rev_id = to_revision
 
929
        if _mod_revision.is_null(merger.other_rev_id):
 
930
            raise errors.NoCommits(branch)
 
931
        self.branch.fetch(branch, last_revision=merger.other_rev_id)
 
932
        merger.other_basis = merger.other_rev_id
 
933
        merger.other_tree = self.branch.repository.revision_tree(
 
934
            merger.other_rev_id)
 
935
        merger.other_branch = branch
 
936
        if from_revision is None:
 
937
            merger.find_base()
 
938
        else:
 
939
            merger.set_base_revision(from_revision, branch)
 
940
        if merger.base_rev_id == merger.other_rev_id:
 
941
            raise errors.PointlessMerge
 
942
        merger.backup_files = False
 
943
        if merge_type is None:
 
944
            merger.merge_type = Merge3Merger
 
945
        else:
 
946
            merger.merge_type = merge_type
 
947
        merger.set_interesting_files(None)
 
948
        merger.show_base = False
 
949
        merger.reprocess = False
 
950
        conflicts = merger.do_merge()
 
951
        merger.set_pending()
926
952
        return conflicts
927
953
 
928
954
    @needs_read_lock
969
995
        return file_id
970
996
 
971
997
    def get_symlink_target(self, file_id):
972
 
        return os.readlink(self.id2abspath(file_id).encode(osutils._fs_enc))
 
998
        abspath = self.id2abspath(file_id)
 
999
        target = osutils.readlink(abspath)
 
1000
        return target
973
1001
 
974
1002
    @needs_write_lock
975
1003
    def subsume(self, other_tree):
1073
1101
        tree_transport = self.bzrdir.root_transport.clone(sub_path)
1074
1102
        if tree_transport.base != branch_transport.base:
1075
1103
            tree_bzrdir = format.initialize_on_transport(tree_transport)
1076
 
            branch.BranchReferenceFormat().initialize(tree_bzrdir, new_branch)
 
1104
            branch.BranchReferenceFormat().initialize(tree_bzrdir,
 
1105
                target_branch=new_branch)
1077
1106
        else:
1078
1107
            tree_bzrdir = branch_bzrdir
1079
 
        wt = tree_bzrdir.create_workingtree(NULL_REVISION)
 
1108
        wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
1080
1109
        wt.set_parent_ids(self.get_parent_ids())
1081
1110
        my_inv = self.inventory
1082
 
        child_inv = Inventory(root_id=None)
 
1111
        child_inv = inventory.Inventory(root_id=None)
1083
1112
        new_root = my_inv[file_id]
1084
1113
        my_inv.remove_recursive_id(file_id)
1085
1114
        new_root.parent_id = None
1110
1139
    def _kind(self, relpath):
1111
1140
        return osutils.file_kind(self.abspath(relpath))
1112
1141
 
1113
 
    def list_files(self, include_root=False):
1114
 
        """Recursively list all files as (path, class, kind, id, entry).
 
1142
    def list_files(self, include_root=False, from_dir=None, recursive=True):
 
1143
        """List all files as (path, class, kind, id, entry).
1115
1144
 
1116
1145
        Lists, but does not descend into unversioned directories.
1117
 
 
1118
1146
        This does not include files that have been deleted in this
1119
 
        tree.
 
1147
        tree. Skips the control directory.
1120
1148
 
1121
 
        Skips the control directory.
 
1149
        :param include_root: if True, return an entry for the root
 
1150
        :param from_dir: start from this directory or None for the root
 
1151
        :param recursive: whether to recurse into subdirectories or not
1122
1152
        """
1123
1153
        # list_files is an iterator, so @needs_read_lock doesn't work properly
1124
1154
        # with it. So callers should be careful to always read_lock the tree.
1126
1156
            raise errors.ObjectNotLocked(self)
1127
1157
 
1128
1158
        inv = self.inventory
1129
 
        if include_root is True:
 
1159
        if from_dir is None and include_root is True:
1130
1160
            yield ('', 'V', 'directory', inv.root.file_id, inv.root)
1131
1161
        # Convert these into local objects to save lookup times
1132
1162
        pathjoin = osutils.pathjoin
1139
1169
        fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
1140
1170
 
1141
1171
        # directory file_id, relative path, absolute path, reverse sorted children
1142
 
        children = os.listdir(self.basedir)
 
1172
        if from_dir is not None:
 
1173
            from_dir_id = inv.path2id(from_dir)
 
1174
            if from_dir_id is None:
 
1175
                # Directory not versioned
 
1176
                return
 
1177
            from_dir_abspath = pathjoin(self.basedir, from_dir)
 
1178
        else:
 
1179
            from_dir_id = inv.root.file_id
 
1180
            from_dir_abspath = self.basedir
 
1181
        children = os.listdir(from_dir_abspath)
1143
1182
        children.sort()
1144
1183
        # jam 20060527 The kernel sized tree seems equivalent whether we
1145
1184
        # use a deque and popleft to keep them sorted, or if we use a plain
1146
1185
        # list and just reverse() them.
1147
1186
        children = collections.deque(children)
1148
 
        stack = [(inv.root.file_id, u'', self.basedir, children)]
 
1187
        stack = [(from_dir_id, u'', from_dir_abspath, children)]
1149
1188
        while stack:
1150
1189
            from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
1151
1190
 
1209
1248
                if fk != 'directory':
1210
1249
                    continue
1211
1250
 
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
 
1251
                # But do this child first if recursing down
 
1252
                if recursive:
 
1253
                    new_children = os.listdir(fap)
 
1254
                    new_children.sort()
 
1255
                    new_children = collections.deque(new_children)
 
1256
                    stack.append((f_ie.file_id, fp, fap, new_children))
 
1257
                    # Break out of inner loop,
 
1258
                    # so that we start outer loop with child
 
1259
                    break
1220
1260
            else:
1221
1261
                # if we finished all children, pop it off the stack
1222
1262
                stack.pop()
1400
1440
        inv = self.inventory
1401
1441
        for entry in moved:
1402
1442
            try:
1403
 
                self._move_entry(_RenameEntry(entry.to_rel, entry.from_id,
 
1443
                self._move_entry(WorkingTree._RenameEntry(
 
1444
                    entry.to_rel, entry.from_id,
1404
1445
                    entry.to_tail, entry.to_parent_id, entry.from_rel,
1405
1446
                    entry.from_tail, entry.from_parent_id,
1406
1447
                    entry.only_change_inv))
1457
1498
        from_tail = splitpath(from_rel)[-1]
1458
1499
        from_id = inv.path2id(from_rel)
1459
1500
        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]
 
1501
            # if file is missing in the inventory maybe it's in the basis_tree
 
1502
            basis_tree = self.branch.basis_tree()
 
1503
            from_id = basis_tree.path2id(from_rel)
 
1504
            if from_id is None:
 
1505
                raise errors.BzrRenameFailedError(from_rel,to_rel,
 
1506
                    errors.NotVersionedError(path=str(from_rel)))
 
1507
            # put entry back in the inventory so we can rename it
 
1508
            from_entry = basis_tree.inventory[from_id].copy()
 
1509
            inv.add(from_entry)
 
1510
        else:
 
1511
            from_entry = inv[from_id]
1463
1512
        from_parent_id = from_entry.parent_id
1464
1513
        to_dir, to_tail = os.path.split(to_rel)
1465
1514
        to_dir_id = inv.path2id(to_dir)
1527
1576
        :raises: NoSuchId if any fileid is not currently versioned.
1528
1577
        """
1529
1578
        for file_id in file_ids:
 
1579
            if file_id not in self._inventory:
 
1580
                raise errors.NoSuchId(self, file_id)
 
1581
        for file_id in file_ids:
1530
1582
            if self._inventory.has_id(file_id):
1531
1583
                self._inventory.remove_recursive_id(file_id)
1532
 
            else:
1533
 
                raise errors.NoSuchId(self, file_id)
1534
1584
        if len(file_ids):
1535
1585
            # in the future this should just set a dirty bit to wait for the
1536
1586
            # final unlock. However, until all methods of workingtree start
1555
1605
 
1556
1606
    @needs_write_lock
1557
1607
    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()
 
1608
             change_reporter=None, possible_transports=None, local=False):
1560
1609
        source.lock_read()
1561
1610
        try:
1562
 
            pp = ProgressPhase("Pull phase", 2, top_pb)
1563
 
            pp.next_phase()
1564
1611
            old_revision_info = self.branch.last_revision_info()
1565
1612
            basis_tree = self.basis_tree()
1566
1613
            count = self.branch.pull(source, overwrite, stop_revision,
1567
 
                                     possible_transports=possible_transports)
 
1614
                                     possible_transports=possible_transports,
 
1615
                                     local=local)
1568
1616
            new_revision_info = self.branch.last_revision_info()
1569
1617
            if new_revision_info != old_revision_info:
1570
 
                pp.next_phase()
1571
1618
                repository = self.branch.repository
1572
 
                pb = bzrlib.ui.ui_factory.nested_progress_bar()
1573
1619
                basis_tree.lock_read()
1574
1620
                try:
1575
1621
                    new_basis_tree = self.branch.basis_tree()
1578
1624
                                new_basis_tree,
1579
1625
                                basis_tree,
1580
1626
                                this_tree=self,
1581
 
                                pb=pb,
 
1627
                                pb=None,
1582
1628
                                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())
 
1629
                    basis_root_id = basis_tree.get_root_id()
 
1630
                    new_root_id = new_basis_tree.get_root_id()
 
1631
                    if basis_root_id != new_root_id:
 
1632
                        self.set_root_id(new_root_id)
1586
1633
                finally:
1587
 
                    pb.finished()
1588
1634
                    basis_tree.unlock()
1589
1635
                # TODO - dedup parents list with things merged by pull ?
1590
1636
                # reuse the revisiontree we merged against to set the new
1603
1649
            return count
1604
1650
        finally:
1605
1651
            source.unlock()
1606
 
            top_pb.finished()
1607
1652
 
1608
1653
    @needs_write_lock
1609
1654
    def put_file_bytes_non_atomic(self, file_id, bytes):
1635
1680
 
1636
1681
            fl = []
1637
1682
            for subf in os.listdir(dirabs):
1638
 
                if subf == '.bzr':
 
1683
                if self.bzrdir.is_control_filename(subf):
1639
1684
                    continue
1640
1685
                if subf not in dir_entry.children:
1641
1686
                    try:
1694
1739
        r"""Check whether the filename matches an ignore pattern.
1695
1740
 
1696
1741
        Patterns containing '/' or '\' need to match the whole path;
1697
 
        others match against only the last component.
 
1742
        others match against only the last component.  Patterns starting
 
1743
        with '!' are ignore exceptions.  Exceptions take precedence
 
1744
        over regular patterns and cause the filename to not be ignored.
1698
1745
 
1699
1746
        If the file is ignored, returns the pattern which caused it to
1700
1747
        be ignored, otherwise None.  So this can simply be used as a
1701
1748
        boolean if desired."""
1702
1749
        if getattr(self, '_ignoreglobster', None) is None:
1703
 
            self._ignoreglobster = globbing.Globster(self.get_ignore_list())
 
1750
            self._ignoreglobster = globbing.ExceptionGlobster(self.get_ignore_list())
1704
1751
        return self._ignoreglobster.match(filename)
1705
1752
 
1706
1753
    def kind(self, file_id):
1756
1803
            raise errors.ObjectNotLocked(self)
1757
1804
 
1758
1805
    def lock_read(self):
1759
 
        """See Branch.lock_read, and WorkingTree.unlock."""
 
1806
        """Lock the tree for reading.
 
1807
 
 
1808
        This also locks the branch, and can be unlocked via self.unlock().
 
1809
 
 
1810
        :return: A bzrlib.lock.LogicalLockResult.
 
1811
        """
1760
1812
        if not self.is_locked():
1761
1813
            self._reset_data()
1762
1814
        self.branch.lock_read()
1763
1815
        try:
1764
 
            return self._control_files.lock_read()
 
1816
            self._control_files.lock_read()
 
1817
            return LogicalLockResult(self.unlock)
1765
1818
        except:
1766
1819
            self.branch.unlock()
1767
1820
            raise
1768
1821
 
1769
1822
    def lock_tree_write(self):
1770
 
        """See MutableTree.lock_tree_write, and WorkingTree.unlock."""
 
1823
        """See MutableTree.lock_tree_write, and WorkingTree.unlock.
 
1824
 
 
1825
        :return: A bzrlib.lock.LogicalLockResult.
 
1826
        """
1771
1827
        if not self.is_locked():
1772
1828
            self._reset_data()
1773
1829
        self.branch.lock_read()
1774
1830
        try:
1775
 
            return self._control_files.lock_write()
 
1831
            self._control_files.lock_write()
 
1832
            return LogicalLockResult(self.unlock)
1776
1833
        except:
1777
1834
            self.branch.unlock()
1778
1835
            raise
1779
1836
 
1780
1837
    def lock_write(self):
1781
 
        """See MutableTree.lock_write, and WorkingTree.unlock."""
 
1838
        """See MutableTree.lock_write, and WorkingTree.unlock.
 
1839
 
 
1840
        :return: A bzrlib.lock.LogicalLockResult.
 
1841
        """
1782
1842
        if not self.is_locked():
1783
1843
            self._reset_data()
1784
1844
        self.branch.lock_write()
1785
1845
        try:
1786
 
            return self._control_files.lock_write()
 
1846
            self._control_files.lock_write()
 
1847
            return LogicalLockResult(self.unlock)
1787
1848
        except:
1788
1849
            self.branch.unlock()
1789
1850
            raise
1797
1858
    def _reset_data(self):
1798
1859
        """Reset transient data that cannot be revalidated."""
1799
1860
        self._inventory_is_modified = False
1800
 
        result = self._deserialize(self._transport.get('inventory'))
 
1861
        f = self._transport.get('inventory')
 
1862
        try:
 
1863
            result = self._deserialize(f)
 
1864
        finally:
 
1865
            f.close()
1801
1866
        self._set_inventory(result, dirty=False)
1802
1867
 
1803
1868
    @needs_tree_write_lock
1850
1915
            # revision_id is set. We must check for this full string, because a
1851
1916
            # root node id can legitimately look like 'revision_id' but cannot
1852
1917
            # contain a '"'.
1853
 
            xml = self.branch.repository.get_inventory_xml(new_revision)
 
1918
            xml = self.branch.repository._get_inventory_xml(new_revision)
1854
1919
            firstline = xml.split('\n', 1)[0]
1855
1920
            if (not 'revision_id="' in firstline or
1856
1921
                'format="7"' not in firstline):
1857
 
                inv = self.branch.repository.deserialise_inventory(
1858
 
                    new_revision, xml)
 
1922
                inv = self.branch.repository._serializer.read_inventory_from_string(
 
1923
                    xml, new_revision)
1859
1924
                xml = self._create_basis_xml_from_inventory(new_revision, inv)
1860
1925
            self._write_basis_inventory(xml)
1861
1926
        except (errors.NoSuchRevision, errors.RevisionNotPresent):
1879
1944
        # binary.
1880
1945
        if self._inventory_is_modified:
1881
1946
            raise errors.InventoryModified(self)
1882
 
        result = self._deserialize(self._transport.get('inventory'))
 
1947
        f = self._transport.get('inventory')
 
1948
        try:
 
1949
            result = self._deserialize(f)
 
1950
        finally:
 
1951
            f.close()
1883
1952
        self._set_inventory(result, dirty=False)
1884
1953
        return result
1885
1954
 
1900
1969
 
1901
1970
        new_files=set()
1902
1971
        unknown_nested_files=set()
 
1972
        if to_file is None:
 
1973
            to_file = sys.stdout
1903
1974
 
1904
1975
        def recurse_directory_to_add_files(directory):
1905
1976
            # Recurse directory and add all files
1906
1977
            # so we can check if they have changed.
1907
 
            for parent_info, file_infos in\
1908
 
                self.walkdirs(directory):
 
1978
            for parent_info, file_infos in self.walkdirs(directory):
1909
1979
                for relpath, basename, kind, lstat, fileid, kind in file_infos:
1910
1980
                    # Is it versioned or ignored?
1911
1981
                    if self.path2id(relpath) or self.is_ignored(relpath):
1946
2016
                            # ... but not ignored
1947
2017
                            has_changed_files = True
1948
2018
                            break
1949
 
                    elif content_change and (kind[1] is not None):
1950
 
                        # Versioned and changed, but not deleted
 
2019
                    elif (content_change and (kind[1] is not None) and
 
2020
                            osutils.is_inside_any(files, path[1])):
 
2021
                        # Versioned and changed, but not deleted, and still
 
2022
                        # in one of the dirs to be deleted.
1951
2023
                        has_changed_files = True
1952
2024
                        break
1953
2025
 
1961
2033
                        tree_delta.unversioned.extend((unknown_file,))
1962
2034
                raise errors.BzrRemoveChangedFilesError(tree_delta)
1963
2035
 
1964
 
        # Build inv_delta and delete files where applicaple,
 
2036
        # Build inv_delta and delete files where applicable,
1965
2037
        # do this before any modifications to inventory.
1966
2038
        for f in files:
1967
2039
            fid = self.path2id(f)
1975
2047
                        new_status = 'I'
1976
2048
                    else:
1977
2049
                        new_status = '?'
1978
 
                    textui.show_status(new_status, self.kind(fid), f,
1979
 
                                       to_file=to_file)
 
2050
                    # XXX: Really should be a more abstract reporter interface
 
2051
                    kind_ch = osutils.kind_marker(self.kind(fid))
 
2052
                    to_file.write(new_status + '       ' + f + kind_ch + '\n')
1980
2053
                # Unversion file
1981
2054
                inv_delta.append((f, None, fid, None))
1982
2055
                message = "removed %s" % (f,)
2005
2078
 
2006
2079
    @needs_tree_write_lock
2007
2080
    def revert(self, filenames=None, old_tree=None, backups=True,
2008
 
               pb=DummyProgress(), report_changes=False):
 
2081
               pb=None, report_changes=False):
2009
2082
        from bzrlib.conflicts import resolve
2010
2083
        if filenames == []:
2011
2084
            filenames = None
2024
2097
            if filenames is None and len(self.get_parent_ids()) > 1:
2025
2098
                parent_trees = []
2026
2099
                last_revision = self.last_revision()
2027
 
                if last_revision != NULL_REVISION:
 
2100
                if last_revision != _mod_revision.NULL_REVISION:
2028
2101
                    if basis_tree is None:
2029
2102
                        basis_tree = self.basis_tree()
2030
2103
                        basis_tree.lock_read()
2068
2141
    def set_inventory(self, new_inventory_list):
2069
2142
        from bzrlib.inventory import (Inventory,
2070
2143
                                      InventoryDirectory,
2071
 
                                      InventoryEntry,
2072
2144
                                      InventoryFile,
2073
2145
                                      InventoryLink)
2074
2146
        inv = Inventory(self.get_root_id())
2134
2206
        """
2135
2207
        raise NotImplementedError(self.unlock)
2136
2208
 
2137
 
    def update(self, change_reporter=None, possible_transports=None):
 
2209
    _marker = object()
 
2210
 
 
2211
    def update(self, change_reporter=None, possible_transports=None,
 
2212
               revision=None, old_tip=_marker):
2138
2213
        """Update a working tree along its branch.
2139
2214
 
2140
2215
        This will update the branch if its bound too, which means we have
2158
2233
        - Merge current state -> basis tree of the master w.r.t. the old tree
2159
2234
          basis.
2160
2235
        - Do a 'normal' merge of the old branch basis if it is relevant.
 
2236
 
 
2237
        :param revision: The target revision to update to. Must be in the
 
2238
            revision history.
 
2239
        :param old_tip: If branch.update() has already been run, the value it
 
2240
            returned (old tip of the branch or None). _marker is used
 
2241
            otherwise.
2161
2242
        """
2162
2243
        if self.branch.get_bound_location() is not None:
2163
2244
            self.lock_write()
2164
 
            update_branch = True
 
2245
            update_branch = (old_tip is self._marker)
2165
2246
        else:
2166
2247
            self.lock_tree_write()
2167
2248
            update_branch = False
2169
2250
            if update_branch:
2170
2251
                old_tip = self.branch.update(possible_transports)
2171
2252
            else:
2172
 
                old_tip = None
2173
 
            return self._update_tree(old_tip, change_reporter)
 
2253
                if old_tip is self._marker:
 
2254
                    old_tip = None
 
2255
            return self._update_tree(old_tip, change_reporter, revision)
2174
2256
        finally:
2175
2257
            self.unlock()
2176
2258
 
2177
2259
    @needs_tree_write_lock
2178
 
    def _update_tree(self, old_tip=None, change_reporter=None):
 
2260
    def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
2179
2261
        """Update a tree to the master branch.
2180
2262
 
2181
2263
        :param old_tip: if supplied, the previous tip revision the branch,
2191
2273
        # We MUST save it even if an error occurs, because otherwise the users
2192
2274
        # local work is unreferenced and will appear to have been lost.
2193
2275
        #
2194
 
        result = 0
 
2276
        nb_conflicts = 0
2195
2277
        try:
2196
2278
            last_rev = self.get_parent_ids()[0]
2197
2279
        except IndexError:
2198
2280
            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.
 
2281
        if revision is None:
 
2282
            revision = self.branch.last_revision()
 
2283
 
 
2284
        old_tip = old_tip or _mod_revision.NULL_REVISION
 
2285
 
 
2286
        if not _mod_revision.is_null(old_tip) and old_tip != last_rev:
 
2287
            # the branch we are bound to was updated
 
2288
            # merge those changes in first
 
2289
            base_tree  = self.basis_tree()
 
2290
            other_tree = self.branch.repository.revision_tree(old_tip)
 
2291
            nb_conflicts = merge.merge_inner(self.branch, other_tree,
 
2292
                                             base_tree, this_tree=self,
 
2293
                                             change_reporter=change_reporter)
 
2294
            if nb_conflicts:
 
2295
                self.add_parent_tree((old_tip, other_tree))
 
2296
                trace.note('Rerun update after fixing the conflicts.')
 
2297
                return nb_conflicts
 
2298
 
 
2299
        if last_rev != _mod_revision.ensure_null(revision):
 
2300
            # the working tree is up to date with the branch
 
2301
            # we can merge the specified revision from master
 
2302
            to_tree = self.branch.repository.revision_tree(revision)
 
2303
            to_root_id = to_tree.get_root_id()
 
2304
 
2201
2305
            basis = self.basis_tree()
2202
2306
            basis.lock_read()
2203
2307
            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())
 
2308
                if (basis.inventory.root is None
 
2309
                    or basis.inventory.root.file_id != to_root_id):
 
2310
                    self.set_root_id(to_root_id)
2207
2311
                    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
2312
            finally:
2215
2313
                basis.unlock()
 
2314
 
 
2315
            # determine the branch point
 
2316
            graph = self.branch.repository.get_graph()
 
2317
            base_rev_id = graph.find_unique_lca(self.branch.last_revision(),
 
2318
                                                last_rev)
 
2319
            base_tree = self.branch.repository.revision_tree(base_rev_id)
 
2320
 
 
2321
            nb_conflicts = merge.merge_inner(self.branch, to_tree, base_tree,
 
2322
                                             this_tree=self,
 
2323
                                             change_reporter=change_reporter)
 
2324
            self.set_last_revision(revision)
2216
2325
            # TODO - dedup parents list with things merged by pull ?
2217
2326
            # reuse the tree we've updated to to set the basis:
2218
 
            parent_trees = [(self.branch.last_revision(), to_tree)]
 
2327
            parent_trees = [(revision, to_tree)]
2219
2328
            merges = self.get_parent_ids()[1:]
2220
2329
            # 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
 
2330
            # tree can decide whether to give us the entire tree or give us a
2222
2331
            # lazy initialised tree. dirstate for instance will have the trees
2223
2332
            # in ram already, whereas a last-revision + basis-inventory tree
2224
2333
            # will not, but also does not need them when setting parents.
2225
2334
            for parent in merges:
2226
2335
                parent_trees.append(
2227
2336
                    (parent, self.branch.repository.revision_tree(parent)))
2228
 
            if (old_tip is not None and not _mod_revision.is_null(old_tip)):
 
2337
            if not _mod_revision.is_null(old_tip):
2229
2338
                parent_trees.append(
2230
2339
                    (old_tip, self.branch.repository.revision_tree(old_tip)))
2231
2340
            self.set_parent_trees(parent_trees)
2232
2341
            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
 
2342
        return nb_conflicts
2265
2343
 
2266
2344
    def _write_hashcache_if_dirty(self):
2267
2345
        """Write out the hashcache if it is dirty."""
2367
2445
                    bzrdir_loc = bisect_left(cur_disk_dir_content,
2368
2446
                        ('.bzr', '.bzr'))
2369
2447
                    if (bzrdir_loc < len(cur_disk_dir_content)
2370
 
                        and cur_disk_dir_content[bzrdir_loc][0] == '.bzr'):
 
2448
                        and self.bzrdir.is_control_filename(
 
2449
                            cur_disk_dir_content[bzrdir_loc][0])):
2371
2450
                        # we dont yield the contents of, or, .bzr itself.
2372
2451
                        del cur_disk_dir_content[bzrdir_loc]
2373
2452
            if inv_finished:
2507
2586
        return un_resolved, resolved
2508
2587
 
2509
2588
    @needs_read_lock
2510
 
    def _check(self):
 
2589
    def _check(self, references):
 
2590
        """Check the tree for consistency.
 
2591
 
 
2592
        :param references: A dict with keys matching the items returned by
 
2593
            self._get_check_refs(), and values from looking those keys up in
 
2594
            the repository.
 
2595
        """
2511
2596
        tree_basis = self.basis_tree()
2512
2597
        tree_basis.lock_read()
2513
2598
        try:
2514
 
            repo_basis = self.branch.repository.revision_tree(
2515
 
                self.last_revision())
 
2599
            repo_basis = references[('trees', self.last_revision())]
2516
2600
            if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2517
2601
                raise errors.BzrCheckError(
2518
2602
                    "Mismatched basis inventory content.")
2531
2615
        """
2532
2616
        return
2533
2617
 
2534
 
    @needs_read_lock
2535
2618
    def _get_rules_searcher(self, default_searcher):
2536
2619
        """See Tree._get_rules_searcher."""
2537
2620
        if self._rules_searcher is None:
2564
2647
        if self._inventory is None:
2565
2648
            self.read_working_inventory()
2566
2649
 
 
2650
    def _get_check_refs(self):
 
2651
        """Return the references needed to perform a check of this tree."""
 
2652
        return [('trees', self.last_revision())]
 
2653
 
2567
2654
    def lock_tree_write(self):
2568
2655
        """See WorkingTree.lock_tree_write().
2569
2656
 
2570
2657
        In Format2 WorkingTrees we have a single lock for the branch and tree
2571
2658
        so lock_tree_write() degrades to lock_write().
 
2659
 
 
2660
        :return: An object with an unlock method which will release the lock
 
2661
            obtained.
2572
2662
        """
2573
2663
        self.branch.lock_write()
2574
2664
        try:
2575
 
            return self._control_files.lock_write()
 
2665
            self._control_files.lock_write()
 
2666
            return self
2576
2667
        except:
2577
2668
            self.branch.unlock()
2578
2669
            raise
2615
2706
 
2616
2707
    def _change_last_revision(self, revision_id):
2617
2708
        """See WorkingTree._change_last_revision."""
2618
 
        if revision_id is None or revision_id == NULL_REVISION:
 
2709
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
2619
2710
            try:
2620
2711
                self._transport.delete('last-revision')
2621
2712
            except errors.NoSuchFile:
2626
2717
                mode=self.bzrdir._get_file_mode())
2627
2718
            return True
2628
2719
 
 
2720
    def _get_check_refs(self):
 
2721
        """Return the references needed to perform a check of this tree."""
 
2722
        return [('trees', self.last_revision())]
 
2723
 
2629
2724
    @needs_tree_write_lock
2630
2725
    def set_conflicts(self, conflicts):
2631
2726
        self._put_rio('conflicts', conflicts.to_stanzas(),
2708
2803
        """Return the format for the working tree object in a_bzrdir."""
2709
2804
        try:
2710
2805
            transport = a_bzrdir.get_workingtree_transport(None)
2711
 
            format_string = transport.get("format").read()
 
2806
            format_string = transport.get_bytes("format")
2712
2807
            return klass._formats[format_string]
2713
2808
        except errors.NoSuchFile:
2714
2809
            raise errors.NoWorkingTree(base=transport.base)
2785
2880
        no working tree.  (See bug #43064).
2786
2881
        """
2787
2882
        sio = StringIO()
2788
 
        inv = Inventory()
 
2883
        inv = inventory.Inventory()
2789
2884
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
2790
2885
        sio.seek(0)
2791
2886
        transport.put_file('inventory', sio, file_mode)
2807
2902
            branch.generate_revision_history(revision_id)
2808
2903
        finally:
2809
2904
            branch.unlock()
2810
 
        inv = Inventory()
 
2905
        inv = inventory.Inventory()
2811
2906
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2812
2907
                         branch,
2813
2908
                         inv,
2930
3025
            # only set an explicit root id if there is one to set.
2931
3026
            if basis_tree.inventory.root is not None:
2932
3027
                wt.set_root_id(basis_tree.get_root_id())
2933
 
            if revision_id == NULL_REVISION:
 
3028
            if revision_id == _mod_revision.NULL_REVISION:
2934
3029
                wt.set_parent_trees([])
2935
3030
            else:
2936
3031
                wt.set_parent_trees([(revision_id, basis_tree)])
2943
3038
        return wt
2944
3039
 
2945
3040
    def _initial_inventory(self):
2946
 
        return Inventory()
 
3041
        return inventory.Inventory()
2947
3042
 
2948
3043
    def __init__(self):
2949
3044
        super(WorkingTreeFormat3, self).__init__()
2978
3073
        return self.get_format_string()
2979
3074
 
2980
3075
 
2981
 
__default_format = WorkingTreeFormat4()
 
3076
__default_format = WorkingTreeFormat6()
2982
3077
WorkingTreeFormat.register_format(__default_format)
2983
3078
WorkingTreeFormat.register_format(WorkingTreeFormat5())
 
3079
WorkingTreeFormat.register_format(WorkingTreeFormat4())
2984
3080
WorkingTreeFormat.register_format(WorkingTreeFormat3())
2985
3081
WorkingTreeFormat.set_default_format(__default_format)
2986
3082
# formats which have no format string are not discoverable