~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Mark Hammond
  • Date: 2009-01-12 01:55:34 UTC
  • mto: (3995.8.2 prepare-1.12)
  • mto: This revision was merged to the branch mainline in revision 4007.
  • Revision ID: mhammond@skippinet.com.au-20090112015534-yfxg50p7mpds9j4v
Include all .html files from the tortoise doc directory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008 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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""WorkingTree object and friends.
18
18
 
19
19
A WorkingTree represents the editable working copy of a branch.
20
 
Operations which represent the WorkingTree are also done here,
21
 
such as renaming or adding files.  The WorkingTree has an inventory
22
 
which is updated by these operations.  A commit produces a
 
20
Operations which represent the WorkingTree are also done here, 
 
21
such as renaming or adding files.  The WorkingTree has an inventory 
 
22
which is updated by these operations.  A commit produces a 
23
23
new revision based on the workingtree and its inventory.
24
24
 
25
25
At the moment every WorkingTree has its own branch.  Remote
48
48
import itertools
49
49
import operator
50
50
import stat
 
51
from time import time
 
52
import warnings
51
53
import re
52
54
 
53
55
import bzrlib
55
57
    branch,
56
58
    bzrdir,
57
59
    conflicts as _mod_conflicts,
 
60
    dirstate,
58
61
    errors,
59
62
    generate_ids,
60
63
    globbing,
61
 
    graph as _mod_graph,
62
64
    hashcache,
63
65
    ignores,
64
 
    inventory,
65
66
    merge,
66
67
    revision as _mod_revision,
67
68
    revisiontree,
 
69
    repository,
 
70
    textui,
68
71
    trace,
69
72
    transform,
70
73
    ui,
71
 
    views,
 
74
    urlutils,
72
75
    xml5,
 
76
    xml6,
73
77
    xml7,
74
78
    )
75
79
import bzrlib.branch
76
80
from bzrlib.transport import get_transport
77
 
from bzrlib.workingtree_4 import (
78
 
    WorkingTreeFormat4,
79
 
    WorkingTreeFormat5,
80
 
    WorkingTreeFormat6,
81
 
    )
 
81
import bzrlib.ui
 
82
from bzrlib.workingtree_4 import WorkingTreeFormat4, WorkingTreeFormat5
82
83
""")
83
84
 
84
85
from bzrlib import symbol_versioning
85
86
from bzrlib.decorators import needs_read_lock, needs_write_lock
 
87
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
86
88
from bzrlib.lockable_files import LockableFiles
87
89
from bzrlib.lockdir import LockDir
88
90
import bzrlib.mutabletree
89
91
from bzrlib.mutabletree import needs_tree_write_lock
90
92
from bzrlib import osutils
91
93
from bzrlib.osutils import (
 
94
    compact_date,
92
95
    file_kind,
93
96
    isdir,
94
97
    normpath,
95
98
    pathjoin,
 
99
    rand_chars,
96
100
    realpath,
97
101
    safe_unicode,
98
102
    splitpath,
99
103
    supports_executable,
100
104
    )
101
 
from bzrlib.filters import filtered_input_file
102
105
from bzrlib.trace import mutter, note
103
106
from bzrlib.transport.local import LocalTransport
104
107
from bzrlib.progress import DummyProgress, ProgressPhase
105
 
from bzrlib.revision import CURRENT_REVISION
 
108
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
106
109
from bzrlib.rio import RioReader, rio_file, Stanza
107
 
from bzrlib.symbol_versioning import (
108
 
    deprecated_passed,
109
 
    DEPRECATED_PARAMETER,
110
 
    )
 
110
from bzrlib.symbol_versioning import (deprecated_passed,
 
111
        deprecated_method,
 
112
        deprecated_function,
 
113
        DEPRECATED_PARAMETER,
 
114
        )
111
115
 
112
116
 
113
117
MERGE_MODIFIED_HEADER_1 = "BZR merge-modified list format 1"
119
123
class TreeEntry(object):
120
124
    """An entry that implements the minimum interface used by commands.
121
125
 
122
 
    This needs further inspection, it may be better to have
 
126
    This needs further inspection, it may be better to have 
123
127
    InventoryEntries without ids - though that seems wrong. For now,
124
128
    this is a parallel hierarchy to InventoryEntry, and needs to become
125
129
    one of several things: decorates to that hierarchy, children of, or
128
132
    no InventoryEntry available - i.e. for unversioned objects.
129
133
    Perhaps they should be UnversionedEntry et al. ? - RBC 20051003
130
134
    """
131
 
 
 
135
 
132
136
    def __eq__(self, other):
133
137
        # yes, this us ugly, TODO: best practice __eq__ style.
134
138
        return (isinstance(other, TreeEntry)
135
139
                and other.__class__ == self.__class__)
136
 
 
 
140
 
137
141
    def kind_character(self):
138
142
        return "???"
139
143
 
181
185
    not listed in the Inventory and vice versa.
182
186
    """
183
187
 
184
 
    # override this to set the strategy for storing views
185
 
    def _make_views(self):
186
 
        return views.DisabledViews(self)
187
 
 
188
188
    def __init__(self, basedir='.',
189
189
                 branch=DEPRECATED_PARAMETER,
190
190
                 _inventory=None,
225
225
        wt_trans = self.bzrdir.get_workingtree_transport(None)
226
226
        cache_filename = wt_trans.local_abspath('stat-cache')
227
227
        self._hashcache = hashcache.HashCache(basedir, cache_filename,
228
 
            self.bzrdir._get_file_mode(),
229
 
            self._content_filter_stack_provider())
 
228
            self.bzrdir._get_file_mode())
230
229
        hc = self._hashcache
231
230
        hc.read()
232
231
        # is this scan needed ? it makes things kinda slow.
248
247
            self._set_inventory(_inventory, dirty=False)
249
248
        self._detect_case_handling()
250
249
        self._rules_searcher = None
251
 
        self.views = self._make_views()
252
250
 
253
251
    def _detect_case_handling(self):
254
252
        wt_trans = self.bzrdir.get_workingtree_transport(None)
280
278
        self._control_files.break_lock()
281
279
        self.branch.break_lock()
282
280
 
283
 
    def _get_check_refs(self):
284
 
        """Return the references needed to perform a check of this tree.
285
 
        
286
 
        The default implementation returns no refs, and is only suitable for
287
 
        trees that have no local caching and can commit on ghosts at any time.
288
 
 
289
 
        :seealso: bzrlib.check for details about check_refs.
290
 
        """
291
 
        return []
292
 
 
293
281
    def requires_rich_root(self):
294
282
        return self._format.requires_rich_root
295
283
 
300
288
        return self._format.supports_content_filtering()
301
289
 
302
290
    def supports_views(self):
303
 
        return self.views.supports_views()
 
291
        return self._format.supports_views()
304
292
 
305
293
    def _set_inventory(self, inv, dirty):
306
294
        """Set the internal cached inventory.
395
383
 
396
384
    def basis_tree(self):
397
385
        """Return RevisionTree for the current last revision.
398
 
 
 
386
        
399
387
        If the left most parent is a ghost then the returned tree will be an
400
 
        empty tree - one obtained by calling
 
388
        empty tree - one obtained by calling 
401
389
        repository.revision_tree(NULL_REVISION).
402
390
        """
403
391
        try:
419
407
            return self.branch.repository.revision_tree(revision_id)
420
408
        except (errors.RevisionNotPresent, errors.NoSuchRevision):
421
409
            # the basis tree *may* be a ghost or a low level error may have
422
 
            # occurred. If the revision is present, its a problem, if its not
 
410
            # occured. If the revision is present, its a problem, if its not
423
411
            # its a ghost.
424
412
            if self.branch.repository.has_revision(revision_id):
425
413
                raise
432
420
 
433
421
    def relpath(self, path):
434
422
        """Return the local path portion from a given path.
435
 
 
436
 
        The path may be absolute or relative. If its a relative path it is
 
423
        
 
424
        The path may be absolute or relative. If its a relative path it is 
437
425
        interpreted relative to the python current working directory.
438
426
        """
439
427
        return osutils.relpath(self.basedir, path)
441
429
    def has_filename(self, filename):
442
430
        return osutils.lexists(self.abspath(filename))
443
431
 
444
 
    def get_file(self, file_id, path=None, filtered=True):
445
 
        return self.get_file_with_stat(file_id, path, filtered=filtered)[0]
 
432
    def get_file(self, file_id, path=None):
 
433
        return self.get_file_with_stat(file_id, path)[0]
446
434
 
447
 
    def get_file_with_stat(self, file_id, path=None, filtered=True,
448
 
        _fstat=os.fstat):
449
 
        """See Tree.get_file_with_stat."""
 
435
    def get_file_with_stat(self, file_id, path=None, _fstat=os.fstat):
 
436
        """See MutableTree.get_file_with_stat."""
450
437
        if path is None:
451
438
            path = self.id2path(file_id)
452
 
        file_obj = self.get_file_byname(path, filtered=False)
453
 
        stat_value = _fstat(file_obj.fileno())
454
 
        if filtered and self.supports_content_filtering():
455
 
            filters = self._content_filter_stack(path)
456
 
            file_obj = filtered_input_file(file_obj, filters)
457
 
        return (file_obj, stat_value)
458
 
 
459
 
    def get_file_text(self, file_id, path=None, filtered=True):
460
 
        return self.get_file(file_id, path=path, filtered=filtered).read()
461
 
 
462
 
    def get_file_byname(self, filename, filtered=True):
463
 
        path = self.abspath(filename)
464
 
        f = file(path, 'rb')
465
 
        if filtered and self.supports_content_filtering():
466
 
            filters = self._content_filter_stack(filename)
467
 
            return filtered_input_file(f, filters)
468
 
        else:
469
 
            return f
470
 
 
471
 
    def get_file_lines(self, file_id, path=None, filtered=True):
 
439
        file_obj = self.get_file_byname(path)
 
440
        return (file_obj, _fstat(file_obj.fileno()))
 
441
 
 
442
    def get_file_byname(self, filename):
 
443
        return file(self.abspath(filename), 'rb')
 
444
 
 
445
    def get_file_lines(self, file_id, path=None):
472
446
        """See Tree.get_file_lines()"""
473
 
        file = self.get_file(file_id, path, filtered=filtered)
 
447
        file = self.get_file(file_id, path)
474
448
        try:
475
449
            return file.readlines()
476
450
        finally:
487
461
        incorrectly attributed to CURRENT_REVISION (but after committing, the
488
462
        attribution will be correct).
489
463
        """
490
 
        maybe_file_parent_keys = []
491
 
        for parent_id in self.get_parent_ids():
492
 
            try:
493
 
                parent_tree = self.revision_tree(parent_id)
494
 
            except errors.NoSuchRevisionInTree:
495
 
                parent_tree = self.branch.repository.revision_tree(parent_id)
496
 
            parent_tree.lock_read()
497
 
            try:
498
 
                if file_id not in parent_tree:
499
 
                    continue
500
 
                ie = parent_tree.inventory[file_id]
501
 
                if ie.kind != 'file':
502
 
                    # Note: this is slightly unnecessary, because symlinks and
503
 
                    # directories have a "text" which is the empty text, and we
504
 
                    # know that won't mess up annotations. But it seems cleaner
505
 
                    continue
506
 
                parent_text_key = (file_id, ie.revision)
507
 
                if parent_text_key not in maybe_file_parent_keys:
508
 
                    maybe_file_parent_keys.append(parent_text_key)
509
 
            finally:
510
 
                parent_tree.unlock()
511
 
        graph = _mod_graph.Graph(self.branch.repository.texts)
512
 
        heads = graph.heads(maybe_file_parent_keys)
513
 
        file_parent_keys = []
514
 
        for key in maybe_file_parent_keys:
515
 
            if key in heads:
516
 
                file_parent_keys.append(key)
517
 
 
518
 
        # Now we have the parents of this content
519
 
        annotator = self.branch.repository.texts.get_annotator()
520
 
        text = self.get_file(file_id).read()
521
 
        this_key =(file_id, default_revision)
522
 
        annotator.add_special_text(this_key, file_parent_keys, text)
523
 
        annotations = [(key[-1], line)
524
 
                       for key, line in annotator.annotate_flat(this_key)]
525
 
        return annotations
 
464
        basis = self.basis_tree()
 
465
        basis.lock_read()
 
466
        try:
 
467
            changes = self.iter_changes(basis, True, [self.id2path(file_id)],
 
468
                require_versioned=True).next()
 
469
            changed_content, kind = changes[2], changes[6]
 
470
            if not changed_content:
 
471
                return basis.annotate_iter(file_id)
 
472
            if kind[1] is None:
 
473
                return None
 
474
            import annotate
 
475
            if kind[0] != 'file':
 
476
                old_lines = []
 
477
            else:
 
478
                old_lines = list(basis.annotate_iter(file_id))
 
479
            old = [old_lines]
 
480
            for tree in self.branch.repository.revision_trees(
 
481
                self.get_parent_ids()[1:]):
 
482
                if file_id not in tree:
 
483
                    continue
 
484
                old.append(list(tree.annotate_iter(file_id)))
 
485
            return annotate.reannotate(old, self.get_file(file_id).readlines(),
 
486
                                       default_revision)
 
487
        finally:
 
488
            basis.unlock()
526
489
 
527
490
    def _get_ancestors(self, default_revision):
528
491
        ancestors = set([default_revision])
533
496
 
534
497
    def get_parent_ids(self):
535
498
        """See Tree.get_parent_ids.
536
 
 
 
499
        
537
500
        This implementation reads the pending merges list and last_revision
538
501
        value and uses that to decide what the parents list should be.
539
502
        """
543
506
        else:
544
507
            parents = [last_rev]
545
508
        try:
546
 
            merges_bytes = self._transport.get_bytes('pending-merges')
 
509
            merges_file = self._transport.get('pending-merges')
547
510
        except errors.NoSuchFile:
548
511
            pass
549
512
        else:
550
 
            for l in osutils.split_lines(merges_bytes):
 
513
            for l in merges_file.readlines():
551
514
                revision_id = l.rstrip('\n')
552
515
                parents.append(revision_id)
553
516
        return parents
556
519
    def get_root_id(self):
557
520
        """Return the id of this trees root"""
558
521
        return self._inventory.root.file_id
559
 
 
 
522
        
560
523
    def _get_store_filename(self, file_id):
561
524
        ## XXX: badly named; this is not in the store at all
562
525
        return self.abspath(self.id2path(file_id))
564
527
    @needs_read_lock
565
528
    def clone(self, to_bzrdir, revision_id=None):
566
529
        """Duplicate this working tree into to_bzr, including all state.
567
 
 
 
530
        
568
531
        Specifically modified files are kept as modified, but
569
532
        ignored and unknown files are discarded.
570
533
 
571
534
        If you want to make a new line of development, see bzrdir.sprout()
572
535
 
573
536
        revision
574
 
            If not None, the cloned tree will have its last revision set to
575
 
            revision, and difference between the source trees last revision
 
537
            If not None, the cloned tree will have its last revision set to 
 
538
            revision, and and difference between the source trees last revision
576
539
            and this one merged in.
577
540
        """
578
541
        # assumes the target bzr dir format is compatible.
612
575
 
613
576
    def get_file_size(self, file_id):
614
577
        """See Tree.get_file_size"""
615
 
        # XXX: this returns the on-disk size; it should probably return the
616
 
        # canonical size
617
578
        try:
618
579
            return os.path.getsize(self.id2abspath(file_id))
619
580
        except OSError, e:
635
596
 
636
597
    def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
637
598
        file_id = self.path2id(path)
638
 
        if file_id is None:
639
 
            # For unversioned files on win32, we just assume they are not
640
 
            # executable
641
 
            return False
642
599
        return self._inventory[file_id].executable
643
600
 
644
601
    def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
666
623
        """See MutableTree._add."""
667
624
        # TODO: Re-adding a file that is removed in the working copy
668
625
        # should probably put it back with the previous ID.
669
 
        # the read and write working inventory should not occur in this
 
626
        # the read and write working inventory should not occur in this 
670
627
        # function - they should be part of lock_write and unlock.
671
628
        inv = self.inventory
672
629
        for f, file_id, kind in zip(files, ids, kinds):
754
711
            raise
755
712
        kind = _mapper(stat_result.st_mode)
756
713
        if kind == 'file':
757
 
            return self._file_content_summary(path, stat_result)
 
714
            size = stat_result.st_size
 
715
            # try for a stat cache lookup
 
716
            executable = self._is_executable_from_path_and_stat(path, stat_result)
 
717
            return (kind, size, executable, self._sha_from_stat(
 
718
                path, stat_result))
758
719
        elif kind == 'directory':
759
720
            # perhaps it looks like a plain directory, but it's really a
760
721
            # reference.
762
723
                kind = 'tree-reference'
763
724
            return kind, None, None, None
764
725
        elif kind == 'symlink':
765
 
            target = osutils.readlink(abspath)
766
 
            return ('symlink', None, None, target)
 
726
            return ('symlink', None, None, os.readlink(abspath))
767
727
        else:
768
728
            return (kind, None, None, None)
769
729
 
770
 
    def _file_content_summary(self, path, stat_result):
771
 
        size = stat_result.st_size
772
 
        executable = self._is_executable_from_path_and_stat(path, stat_result)
773
 
        # try for a stat cache lookup
774
 
        return ('file', size, executable, self._sha_from_stat(
775
 
            path, stat_result))
776
 
 
777
730
    def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
778
731
        """Common ghost checking functionality from set_parent_*.
779
732
 
789
742
    def _set_merges_from_parent_ids(self, parent_ids):
790
743
        merges = parent_ids[1:]
791
744
        self._transport.put_bytes('pending-merges', '\n'.join(merges),
792
 
            mode=self.bzrdir._get_file_mode())
 
745
            mode=self._control_files._file_mode)
793
746
 
794
747
    def _filter_parent_ids_by_ancestry(self, revision_ids):
795
748
        """Check that all merged revisions are proper 'heads'.
796
749
 
797
750
        This will always return the first revision_id, and any merged revisions
798
 
        which are
 
751
        which are 
799
752
        """
800
753
        if len(revision_ids) == 0:
801
754
            return revision_ids
813
766
    @needs_tree_write_lock
814
767
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
815
768
        """Set the parent ids to revision_ids.
816
 
 
 
769
        
817
770
        See also set_parent_trees. This api will try to retrieve the tree data
818
771
        for each element of revision_ids from the trees repository. If you have
819
772
        tree data already available, it is more efficient to use
895
848
        self._must_be_locked()
896
849
        my_file = rio_file(stanzas, header)
897
850
        self._transport.put_file(filename, my_file,
898
 
            mode=self.bzrdir._get_file_mode())
 
851
            mode=self._control_files._file_mode)
899
852
 
900
853
    @needs_write_lock # because merge pulls data into the branch.
901
854
    def merge_from_branch(self, branch, to_revision=None, from_revision=None,
902
 
                          merge_type=None, force=False):
 
855
        merge_type=None):
903
856
        """Merge from a branch into this working tree.
904
857
 
905
858
        :param branch: The branch to merge from.
909
862
            branch.last_revision().
910
863
        """
911
864
        from bzrlib.merge import Merger, Merge3Merger
912
 
        pb = ui.ui_factory.nested_progress_bar()
 
865
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
913
866
        try:
914
867
            merger = Merger(self.branch, this_tree=self, pb=pb)
915
868
            merger.pp = ProgressPhase("Merge phase", 5, pb)
916
869
            merger.pp.next_phase()
917
 
            # check that there are no local alterations
918
 
            if not force and self.has_changes():
919
 
                raise errors.UncommittedChanges(self)
 
870
            # check that there are no
 
871
            # local alterations
 
872
            merger.check_basis(check_clean=True, require_commits=False)
920
873
            if to_revision is None:
921
874
                to_revision = _mod_revision.ensure_null(branch.last_revision())
922
875
            merger.other_rev_id = to_revision
952
905
    def merge_modified(self):
953
906
        """Return a dictionary of files modified by a merge.
954
907
 
955
 
        The list is initialized by WorkingTree.set_merge_modified, which is
 
908
        The list is initialized by WorkingTree.set_merge_modified, which is 
956
909
        typically called after we make some automatic updates to the tree
957
910
        because of a merge.
958
911
 
992
945
        return file_id
993
946
 
994
947
    def get_symlink_target(self, file_id):
995
 
        abspath = self.id2abspath(file_id)
996
 
        target = osutils.readlink(abspath)
997
 
        return target
 
948
        return os.readlink(self.id2abspath(file_id))
998
949
 
999
950
    @needs_write_lock
1000
951
    def subsume(self, other_tree):
1050
1001
        return False
1051
1002
 
1052
1003
    def _directory_may_be_tree_reference(self, relpath):
1053
 
        # as a special case, if a directory contains control files then
 
1004
        # as a special case, if a directory contains control files then 
1054
1005
        # it's a tree reference, except that the root of the tree is not
1055
1006
        return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
1056
1007
        # TODO: We could ask all the control formats whether they
1067
1018
    @needs_tree_write_lock
1068
1019
    def extract(self, file_id, format=None):
1069
1020
        """Extract a subtree from this tree.
1070
 
 
 
1021
        
1071
1022
        A new branch will be created, relative to the path for this tree.
1072
1023
        """
1073
1024
        self.flush()
1078
1029
                transport = transport.clone(name)
1079
1030
                transport.ensure_base()
1080
1031
            return transport
1081
 
 
 
1032
            
1082
1033
        sub_path = self.id2path(file_id)
1083
1034
        branch_transport = mkdirs(sub_path)
1084
1035
        if format is None:
1101
1052
            branch.BranchReferenceFormat().initialize(tree_bzrdir, new_branch)
1102
1053
        else:
1103
1054
            tree_bzrdir = branch_bzrdir
1104
 
        wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
 
1055
        wt = tree_bzrdir.create_workingtree(NULL_REVISION)
1105
1056
        wt.set_parent_ids(self.get_parent_ids())
1106
1057
        my_inv = self.inventory
1107
 
        child_inv = inventory.Inventory(root_id=None)
 
1058
        child_inv = Inventory(root_id=None)
1108
1059
        new_root = my_inv[file_id]
1109
1060
        my_inv.remove_recursive_id(file_id)
1110
1061
        new_root.parent_id = None
1129
1080
        self._serialize(self._inventory, sio)
1130
1081
        sio.seek(0)
1131
1082
        self._transport.put_file('inventory', sio,
1132
 
            mode=self.bzrdir._get_file_mode())
 
1083
            mode=self._control_files._file_mode)
1133
1084
        self._inventory_is_modified = False
1134
1085
 
1135
1086
    def _kind(self, relpath):
1136
1087
        return osutils.file_kind(self.abspath(relpath))
1137
1088
 
1138
 
    def list_files(self, include_root=False, from_dir=None, recursive=True):
1139
 
        """List all files as (path, class, kind, id, entry).
 
1089
    def list_files(self, include_root=False):
 
1090
        """Recursively list all files as (path, class, kind, id, entry).
1140
1091
 
1141
1092
        Lists, but does not descend into unversioned directories.
 
1093
 
1142
1094
        This does not include files that have been deleted in this
1143
 
        tree. Skips the control directory.
 
1095
        tree.
1144
1096
 
1145
 
        :param include_root: if True, do not 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
 
1097
        Skips the control directory.
1148
1098
        """
1149
1099
        # list_files is an iterator, so @needs_read_lock doesn't work properly
1150
1100
        # with it. So callers should be careful to always read_lock the tree.
1152
1102
            raise errors.ObjectNotLocked(self)
1153
1103
 
1154
1104
        inv = self.inventory
1155
 
        if from_dir is None and include_root is True:
 
1105
        if include_root is True:
1156
1106
            yield ('', 'V', 'directory', inv.root.file_id, inv.root)
1157
1107
        # Convert these into local objects to save lookup times
1158
1108
        pathjoin = osutils.pathjoin
1165
1115
        fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
1166
1116
 
1167
1117
        # directory file_id, relative path, absolute path, reverse sorted children
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)
 
1118
        children = os.listdir(self.basedir)
1178
1119
        children.sort()
1179
 
        # jam 20060527 The kernel sized tree seems equivalent whether we
 
1120
        # jam 20060527 The kernel sized tree seems equivalent whether we 
1180
1121
        # use a deque and popleft to keep them sorted, or if we use a plain
1181
1122
        # list and just reverse() them.
1182
1123
        children = collections.deque(children)
1183
 
        stack = [(from_dir_id, u'', from_dir_abspath, children)]
 
1124
        stack = [(inv.root.file_id, u'', self.basedir, children)]
1184
1125
        while stack:
1185
1126
            from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
1186
1127
 
1202
1143
 
1203
1144
                # absolute path
1204
1145
                fap = from_dir_abspath + '/' + f
1205
 
 
 
1146
                
1206
1147
                f_ie = inv.get_child(from_dir_id, f)
1207
1148
                if f_ie:
1208
1149
                    c = 'V'
1240
1181
                    except KeyError:
1241
1182
                        yield fp[1:], c, fk, None, TreeEntry()
1242
1183
                    continue
1243
 
 
 
1184
                
1244
1185
                if fk != 'directory':
1245
1186
                    continue
1246
1187
 
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
 
1188
                # But do this child first
 
1189
                new_children = os.listdir(fap)
 
1190
                new_children.sort()
 
1191
                new_children = collections.deque(new_children)
 
1192
                stack.append((f_ie.file_id, fp, fap, new_children))
 
1193
                # Break out of inner loop,
 
1194
                # so that we start outer loop with child
 
1195
                break
1256
1196
            else:
1257
1197
                # if we finished all children, pop it off the stack
1258
1198
                stack.pop()
1264
1204
        to_dir must exist in the inventory.
1265
1205
 
1266
1206
        If to_dir exists and is a directory, the files are moved into
1267
 
        it, keeping their old names.
 
1207
        it, keeping their old names.  
1268
1208
 
1269
1209
        Note that to_dir is only the last component of the new name;
1270
1210
        this doesn't change the directory.
1436
1376
        inv = self.inventory
1437
1377
        for entry in moved:
1438
1378
            try:
1439
 
                self._move_entry(WorkingTree._RenameEntry(
1440
 
                    entry.to_rel, entry.from_id,
 
1379
                self._move_entry(_RenameEntry(entry.to_rel, entry.from_id,
1441
1380
                    entry.to_tail, entry.to_parent_id, entry.from_rel,
1442
1381
                    entry.from_tail, entry.from_parent_id,
1443
1382
                    entry.only_change_inv))
1494
1433
        from_tail = splitpath(from_rel)[-1]
1495
1434
        from_id = inv.path2id(from_rel)
1496
1435
        if from_id is None:
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]
 
1436
            raise errors.BzrRenameFailedError(from_rel,to_rel,
 
1437
                errors.NotVersionedError(path=str(from_rel)))
 
1438
        from_entry = inv[from_id]
1508
1439
        from_parent_id = from_entry.parent_id
1509
1440
        to_dir, to_tail = os.path.split(to_rel)
1510
1441
        to_dir_id = inv.path2id(to_dir)
1556
1487
        These are files in the working directory that are not versioned or
1557
1488
        control files or ignored.
1558
1489
        """
1559
 
        # force the extras method to be fully executed before returning, to
 
1490
        # force the extras method to be fully executed before returning, to 
1560
1491
        # prevent race conditions with the lock
1561
1492
        return iter(
1562
1493
            [subp for subp in self.extras() if not self.is_ignored(subp)])
1572
1503
        :raises: NoSuchId if any fileid is not currently versioned.
1573
1504
        """
1574
1505
        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:
1578
1506
            if self._inventory.has_id(file_id):
1579
1507
                self._inventory.remove_recursive_id(file_id)
 
1508
            else:
 
1509
                raise errors.NoSuchId(self, file_id)
1580
1510
        if len(file_ids):
1581
 
            # in the future this should just set a dirty bit to wait for the
 
1511
            # in the future this should just set a dirty bit to wait for the 
1582
1512
            # final unlock. However, until all methods of workingtree start
1583
 
            # with the current in -memory inventory rather than triggering
 
1513
            # with the current in -memory inventory rather than triggering 
1584
1514
            # a read, it is more complex - we need to teach read_inventory
1585
1515
            # to know when to read, and when to not read first... and possibly
1586
1516
            # to save first when the in memory one may be corrupted.
1587
1517
            # so for now, we just only write it if it is indeed dirty.
1588
1518
            # - RBC 20060907
1589
1519
            self._write_inventory(self._inventory)
1590
 
 
 
1520
    
1591
1521
    def _iter_conflicts(self):
1592
1522
        conflicted = set()
1593
1523
        for info in self.list_files():
1601
1531
 
1602
1532
    @needs_write_lock
1603
1533
    def pull(self, source, overwrite=False, stop_revision=None,
1604
 
             change_reporter=None, possible_transports=None, local=False):
1605
 
        top_pb = ui.ui_factory.nested_progress_bar()
 
1534
             change_reporter=None, possible_transports=None):
 
1535
        top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1606
1536
        source.lock_read()
1607
1537
        try:
1608
1538
            pp = ProgressPhase("Pull phase", 2, top_pb)
1610
1540
            old_revision_info = self.branch.last_revision_info()
1611
1541
            basis_tree = self.basis_tree()
1612
1542
            count = self.branch.pull(source, overwrite, stop_revision,
1613
 
                                     possible_transports=possible_transports,
1614
 
                                     local=local)
 
1543
                                     possible_transports=possible_transports)
1615
1544
            new_revision_info = self.branch.last_revision_info()
1616
1545
            if new_revision_info != old_revision_info:
1617
1546
                pp.next_phase()
1618
1547
                repository = self.branch.repository
1619
 
                pb = ui.ui_factory.nested_progress_bar()
 
1548
                pb = bzrlib.ui.ui_factory.nested_progress_bar()
1620
1549
                basis_tree.lock_read()
1621
1550
                try:
1622
1551
                    new_basis_tree = self.branch.basis_tree()
1627
1556
                                this_tree=self,
1628
1557
                                pb=pb,
1629
1558
                                change_reporter=change_reporter)
1630
 
                    basis_root_id = basis_tree.get_root_id()
1631
 
                    new_root_id = new_basis_tree.get_root_id()
1632
 
                    if basis_root_id != new_root_id:
1633
 
                        self.set_root_id(new_root_id)
 
1559
                    if (basis_tree.inventory.root is None and
 
1560
                        new_basis_tree.inventory.root is not None):
 
1561
                        self.set_root_id(new_basis_tree.get_root_id())
1634
1562
                finally:
1635
1563
                    pb.finished()
1636
1564
                    basis_tree.unlock()
1638
1566
                # reuse the revisiontree we merged against to set the new
1639
1567
                # tree data.
1640
1568
                parent_trees = [(self.branch.last_revision(), new_basis_tree)]
1641
 
                # we have to pull the merge trees out again, because
1642
 
                # merge_inner has set the ids. - this corner is not yet
 
1569
                # we have to pull the merge trees out again, because 
 
1570
                # merge_inner has set the ids. - this corner is not yet 
1643
1571
                # layered well enough to prevent double handling.
1644
1572
                # XXX TODO: Fix the double handling: telling the tree about
1645
1573
                # the already known parent data is wasteful.
1683
1611
 
1684
1612
            fl = []
1685
1613
            for subf in os.listdir(dirabs):
1686
 
                if self.bzrdir.is_control_filename(subf):
 
1614
                if subf == '.bzr':
1687
1615
                    continue
1688
1616
                if subf not in dir_entry.children:
1689
1617
                    try:
1699
1627
                            fl.append(subf_norm)
1700
1628
                    else:
1701
1629
                        fl.append(subf)
1702
 
 
 
1630
            
1703
1631
            fl.sort()
1704
1632
            for subf in fl:
1705
1633
                subp = pathjoin(path, subf)
1845
1773
    def _reset_data(self):
1846
1774
        """Reset transient data that cannot be revalidated."""
1847
1775
        self._inventory_is_modified = False
1848
 
        f = self._transport.get('inventory')
1849
 
        try:
1850
 
            result = self._deserialize(f)
1851
 
        finally:
1852
 
            f.close()
 
1776
        result = self._deserialize(self._transport.get('inventory'))
1853
1777
        self._set_inventory(result, dirty=False)
1854
1778
 
1855
1779
    @needs_tree_write_lock
1860
1784
 
1861
1785
    def _change_last_revision(self, new_revision):
1862
1786
        """Template method part of set_last_revision to perform the change.
1863
 
 
 
1787
        
1864
1788
        This is used to allow WorkingTree3 instances to not affect branch
1865
1789
        when their last revision is set.
1866
1790
        """
1879
1803
        path = self._basis_inventory_name()
1880
1804
        sio = StringIO(xml)
1881
1805
        self._transport.put_file(path, sio,
1882
 
            mode=self.bzrdir._get_file_mode())
 
1806
            mode=self._control_files._file_mode)
1883
1807
 
1884
1808
    def _create_basis_xml_from_inventory(self, revision_id, inventory):
1885
1809
        """Create the text that will be saved in basis-inventory"""
1892
1816
        # as commit already has that ready-to-use [while the format is the
1893
1817
        # same, that is].
1894
1818
        try:
1895
 
            # this double handles the inventory - unpack and repack -
 
1819
            # this double handles the inventory - unpack and repack - 
1896
1820
            # but is easier to understand. We can/should put a conditional
1897
1821
            # in here based on whether the inventory is in the latest format
1898
1822
            # - perhaps we should repack all inventories on a repository
1899
1823
            # upgrade ?
1900
1824
            # the fast path is to copy the raw xml from the repository. If the
1901
 
            # xml contains 'revision_id="', then we assume the right
 
1825
            # xml contains 'revision_id="', then we assume the right 
1902
1826
            # revision_id is set. We must check for this full string, because a
1903
1827
            # root node id can legitimately look like 'revision_id' but cannot
1904
1828
            # contain a '"'.
1905
1829
            xml = self.branch.repository.get_inventory_xml(new_revision)
1906
1830
            firstline = xml.split('\n', 1)[0]
1907
 
            if (not 'revision_id="' in firstline or
 
1831
            if (not 'revision_id="' in firstline or 
1908
1832
                'format="7"' not in firstline):
1909
 
                inv = self.branch.repository._serializer.read_inventory_from_string(
1910
 
                    xml, new_revision)
 
1833
                inv = self.branch.repository.deserialise_inventory(
 
1834
                    new_revision, xml)
1911
1835
                xml = self._create_basis_xml_from_inventory(new_revision, inv)
1912
1836
            self._write_basis_inventory(xml)
1913
1837
        except (errors.NoSuchRevision, errors.RevisionNotPresent):
1917
1841
        """Read the cached basis inventory."""
1918
1842
        path = self._basis_inventory_name()
1919
1843
        return self._transport.get_bytes(path)
1920
 
 
 
1844
        
1921
1845
    @needs_read_lock
1922
1846
    def read_working_inventory(self):
1923
1847
        """Read the working inventory.
1924
 
 
 
1848
        
1925
1849
        :raises errors.InventoryModified: read_working_inventory will fail
1926
1850
            when the current in memory inventory has been modified.
1927
1851
        """
1928
 
        # conceptually this should be an implementation detail of the tree.
 
1852
        # conceptually this should be an implementation detail of the tree. 
1929
1853
        # XXX: Deprecate this.
1930
1854
        # ElementTree does its own conversion from UTF-8, so open in
1931
1855
        # binary.
1932
1856
        if self._inventory_is_modified:
1933
1857
            raise errors.InventoryModified(self)
1934
 
        f = self._transport.get('inventory')
1935
 
        try:
1936
 
            result = self._deserialize(f)
1937
 
        finally:
1938
 
            f.close()
 
1858
        result = self._deserialize(self._transport.get('inventory'))
1939
1859
        self._set_inventory(result, dirty=False)
1940
1860
        return result
1941
1861
 
1956
1876
 
1957
1877
        new_files=set()
1958
1878
        unknown_nested_files=set()
1959
 
        if to_file is None:
1960
 
            to_file = sys.stdout
1961
1879
 
1962
1880
        def recurse_directory_to_add_files(directory):
1963
1881
            # Recurse directory and add all files
2019
1937
                        tree_delta.unversioned.extend((unknown_file,))
2020
1938
                raise errors.BzrRemoveChangedFilesError(tree_delta)
2021
1939
 
2022
 
        # Build inv_delta and delete files where applicable,
 
1940
        # Build inv_delta and delete files where applicaple,
2023
1941
        # do this before any modifications to inventory.
2024
1942
        for f in files:
2025
1943
            fid = self.path2id(f)
2033
1951
                        new_status = 'I'
2034
1952
                    else:
2035
1953
                        new_status = '?'
2036
 
                    # XXX: Really should be a more abstract reporter interface
2037
 
                    kind_ch = osutils.kind_marker(self.kind(fid))
2038
 
                    to_file.write(new_status + '       ' + f + kind_ch + '\n')
 
1954
                    textui.show_status(new_status, self.kind(fid), f,
 
1955
                                       to_file=to_file)
2039
1956
                # Unversion file
2040
1957
                inv_delta.append((f, None, fid, None))
2041
1958
                message = "removed %s" % (f,)
2083
2000
            if filenames is None and len(self.get_parent_ids()) > 1:
2084
2001
                parent_trees = []
2085
2002
                last_revision = self.last_revision()
2086
 
                if last_revision != _mod_revision.NULL_REVISION:
 
2003
                if last_revision != NULL_REVISION:
2087
2004
                    if basis_tree is None:
2088
2005
                        basis_tree = self.basis_tree()
2089
2006
                        basis_tree.lock_read()
2127
2044
    def set_inventory(self, new_inventory_list):
2128
2045
        from bzrlib.inventory import (Inventory,
2129
2046
                                      InventoryDirectory,
 
2047
                                      InventoryEntry,
2130
2048
                                      InventoryFile,
2131
2049
                                      InventoryLink)
2132
2050
        inv = Inventory(self.get_root_id())
2134
2052
            name = os.path.basename(path)
2135
2053
            if name == "":
2136
2054
                continue
2137
 
            # fixme, there should be a factory function inv,add_??
 
2055
            # fixme, there should be a factory function inv,add_?? 
2138
2056
            if kind == 'directory':
2139
2057
                inv.add(InventoryDirectory(file_id, name, parent))
2140
2058
            elif kind == 'file':
2148
2066
    @needs_tree_write_lock
2149
2067
    def set_root_id(self, file_id):
2150
2068
        """Set the root id for this tree."""
2151
 
        # for compatability
 
2069
        # for compatability 
2152
2070
        if file_id is None:
2153
2071
            raise ValueError(
2154
2072
                'WorkingTree.set_root_id with fileid=None')
2158
2076
    def _set_root_id(self, file_id):
2159
2077
        """Set the root id for this tree, in a format specific manner.
2160
2078
 
2161
 
        :param file_id: The file id to assign to the root. It must not be
 
2079
        :param file_id: The file id to assign to the root. It must not be 
2162
2080
            present in the current inventory or an error will occur. It must
2163
2081
            not be None, but rather a valid file id.
2164
2082
        """
2183
2101
 
2184
2102
    def unlock(self):
2185
2103
        """See Branch.unlock.
2186
 
 
 
2104
        
2187
2105
        WorkingTree locking just uses the Branch locking facilities.
2188
2106
        This is current because all working trees have an embedded branch
2189
2107
        within them. IF in the future, we were to make branch data shareable
2190
 
        between multiple working trees, i.e. via shared storage, then we
 
2108
        between multiple working trees, i.e. via shared storage, then we 
2191
2109
        would probably want to lock both the local tree, and the branch.
2192
2110
        """
2193
2111
        raise NotImplementedError(self.unlock)
2194
2112
 
2195
 
    _marker = object()
2196
 
 
2197
 
    def update(self, change_reporter=None, possible_transports=None,
2198
 
               revision=None, old_tip=_marker):
 
2113
    def update(self, change_reporter=None, possible_transports=None):
2199
2114
        """Update a working tree along its branch.
2200
2115
 
2201
2116
        This will update the branch if its bound too, which means we have
2219
2134
        - Merge current state -> basis tree of the master w.r.t. the old tree
2220
2135
          basis.
2221
2136
        - Do a 'normal' merge of the old branch basis if it is relevant.
2222
 
 
2223
 
        :param revision: The target revision to update to. Must be in the
2224
 
            revision history.
2225
 
        :param old_tip: If branch.update() has already been run, the value it
2226
 
            returned (old tip of the branch or None). _marker is used
2227
 
            otherwise.
2228
2137
        """
2229
2138
        if self.branch.get_bound_location() is not None:
2230
2139
            self.lock_write()
2231
 
            update_branch = (old_tip is self._marker)
 
2140
            update_branch = True
2232
2141
        else:
2233
2142
            self.lock_tree_write()
2234
2143
            update_branch = False
2236
2145
            if update_branch:
2237
2146
                old_tip = self.branch.update(possible_transports)
2238
2147
            else:
2239
 
                if old_tip is self._marker:
2240
 
                    old_tip = None
2241
 
            return self._update_tree(old_tip, change_reporter, revision)
 
2148
                old_tip = None
 
2149
            return self._update_tree(old_tip, change_reporter)
2242
2150
        finally:
2243
2151
            self.unlock()
2244
2152
 
2245
2153
    @needs_tree_write_lock
2246
 
    def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
 
2154
    def _update_tree(self, old_tip=None, change_reporter=None):
2247
2155
        """Update a tree to the master branch.
2248
2156
 
2249
2157
        :param old_tip: if supplied, the previous tip revision the branch,
2255
2163
        # cant set that until we update the working trees last revision to be
2256
2164
        # one from the new branch, because it will just get absorbed by the
2257
2165
        # parent de-duplication logic.
2258
 
        #
 
2166
        # 
2259
2167
        # We MUST save it even if an error occurs, because otherwise the users
2260
2168
        # local work is unreferenced and will appear to have been lost.
2261
 
        #
 
2169
        # 
2262
2170
        result = 0
2263
2171
        try:
2264
2172
            last_rev = self.get_parent_ids()[0]
2265
2173
        except IndexError:
2266
2174
            last_rev = _mod_revision.NULL_REVISION
2267
 
        if revision is None:
2268
 
            revision = self.branch.last_revision()
2269
 
        else:
2270
 
            if revision not in self.branch.revision_history():
2271
 
                raise errors.NoSuchRevision(self.branch, revision)
2272
 
        if last_rev != _mod_revision.ensure_null(revision):
2273
 
            # merge tree state up to specified revision.
 
2175
        if last_rev != _mod_revision.ensure_null(self.branch.last_revision()):
 
2176
            # merge tree state up to new branch tip.
2274
2177
            basis = self.basis_tree()
2275
2178
            basis.lock_read()
2276
2179
            try:
2277
 
                to_tree = self.branch.repository.revision_tree(revision)
2278
 
                to_root_id = to_tree.get_root_id()
2279
 
                if (basis.inventory.root is None
2280
 
                    or basis.inventory.root.file_id != to_root_id):
2281
 
                    self.set_root_id(to_root_id)
 
2180
                to_tree = self.branch.basis_tree()
 
2181
                if basis.inventory.root is None:
 
2182
                    self.set_root_id(to_tree.get_root_id())
2282
2183
                    self.flush()
2283
2184
                result += merge.merge_inner(
2284
2185
                                      self.branch,
2286
2187
                                      basis,
2287
2188
                                      this_tree=self,
2288
2189
                                      change_reporter=change_reporter)
2289
 
                self.set_last_revision(revision)
2290
2190
            finally:
2291
2191
                basis.unlock()
2292
2192
            # TODO - dedup parents list with things merged by pull ?
2293
2193
            # reuse the tree we've updated to to set the basis:
2294
 
            parent_trees = [(revision, to_tree)]
 
2194
            parent_trees = [(self.branch.last_revision(), to_tree)]
2295
2195
            merges = self.get_parent_ids()[1:]
2296
2196
            # Ideally we ask the tree for the trees here, that way the working
2297
 
            # tree can decide whether to give us the entire tree or give us a
 
2197
            # tree can decide whether to give us teh entire tree or give us a
2298
2198
            # lazy initialised tree. dirstate for instance will have the trees
2299
2199
            # in ram already, whereas a last-revision + basis-inventory tree
2300
2200
            # will not, but also does not need them when setting parents.
2327
2227
            #       should be able to remove this extra flush.
2328
2228
            self.flush()
2329
2229
            graph = self.branch.repository.get_graph()
2330
 
            base_rev_id = graph.find_unique_lca(revision, old_tip)
 
2230
            base_rev_id = graph.find_unique_lca(self.branch.last_revision(),
 
2231
                                                old_tip)
2331
2232
            base_tree = self.branch.repository.revision_tree(base_rev_id)
2332
2233
            other_tree = self.branch.repository.revision_tree(old_tip)
2333
2234
            result += merge.merge_inner(
2442
2343
                    bzrdir_loc = bisect_left(cur_disk_dir_content,
2443
2344
                        ('.bzr', '.bzr'))
2444
2345
                    if (bzrdir_loc < len(cur_disk_dir_content)
2445
 
                        and self.bzrdir.is_control_filename(
2446
 
                            cur_disk_dir_content[bzrdir_loc][0])):
 
2346
                        and cur_disk_dir_content[bzrdir_loc][0] == '.bzr'):
2447
2347
                        # we dont yield the contents of, or, .bzr itself.
2448
2348
                        del cur_disk_dir_content[bzrdir_loc]
2449
2349
            if inv_finished:
2583
2483
        return un_resolved, resolved
2584
2484
 
2585
2485
    @needs_read_lock
2586
 
    def _check(self, references):
2587
 
        """Check the tree for consistency.
2588
 
 
2589
 
        :param references: A dict with keys matching the items returned by
2590
 
            self._get_check_refs(), and values from looking those keys up in
2591
 
            the repository.
2592
 
        """
 
2486
    def _check(self):
2593
2487
        tree_basis = self.basis_tree()
2594
2488
        tree_basis.lock_read()
2595
2489
        try:
2596
 
            repo_basis = references[('trees', self.last_revision())]
 
2490
            repo_basis = self.branch.repository.revision_tree(
 
2491
                self.last_revision())
2597
2492
            if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2598
2493
                raise errors.BzrCheckError(
2599
2494
                    "Mismatched basis inventory content.")
2612
2507
        """
2613
2508
        return
2614
2509
 
 
2510
    @needs_read_lock
2615
2511
    def _get_rules_searcher(self, default_searcher):
2616
2512
        """See Tree._get_rules_searcher."""
2617
2513
        if self._rules_searcher is None:
2628
2524
class WorkingTree2(WorkingTree):
2629
2525
    """This is the Format 2 working tree.
2630
2526
 
2631
 
    This was the first weave based working tree.
 
2527
    This was the first weave based working tree. 
2632
2528
     - uses os locks for locking.
2633
2529
     - uses the branch last-revision.
2634
2530
    """
2644
2540
        if self._inventory is None:
2645
2541
            self.read_working_inventory()
2646
2542
 
2647
 
    def _get_check_refs(self):
2648
 
        """Return the references needed to perform a check of this tree."""
2649
 
        return [('trees', self.last_revision())]
2650
 
 
2651
2543
    def lock_tree_write(self):
2652
2544
        """See WorkingTree.lock_tree_write().
2653
2545
 
2671
2563
            if self._inventory_is_modified:
2672
2564
                self.flush()
2673
2565
            self._write_hashcache_if_dirty()
2674
 
 
 
2566
                    
2675
2567
        # reverse order of locking.
2676
2568
        try:
2677
2569
            return self._control_files.unlock()
2699
2591
 
2700
2592
    def _change_last_revision(self, revision_id):
2701
2593
        """See WorkingTree._change_last_revision."""
2702
 
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
 
2594
        if revision_id is None or revision_id == NULL_REVISION:
2703
2595
            try:
2704
2596
                self._transport.delete('last-revision')
2705
2597
            except errors.NoSuchFile:
2707
2599
            return False
2708
2600
        else:
2709
2601
            self._transport.put_bytes('last-revision', revision_id,
2710
 
                mode=self.bzrdir._get_file_mode())
 
2602
                mode=self._control_files._file_mode)
2711
2603
            return True
2712
2604
 
2713
 
    def _get_check_refs(self):
2714
 
        """Return the references needed to perform a check of this tree."""
2715
 
        return [('trees', self.last_revision())]
2716
 
 
2717
2605
    @needs_tree_write_lock
2718
2606
    def set_conflicts(self, conflicts):
2719
 
        self._put_rio('conflicts', conflicts.to_stanzas(),
 
2607
        self._put_rio('conflicts', conflicts.to_stanzas(), 
2720
2608
                      CONFLICT_HEADER_1)
2721
2609
 
2722
2610
    @needs_tree_write_lock
2771
2659
     * a format string,
2772
2660
     * an open routine.
2773
2661
 
2774
 
    Formats are placed in an dict by their format string for reference
 
2662
    Formats are placed in an dict by their format string for reference 
2775
2663
    during workingtree opening. Its not required that these be instances, they
2776
 
    can be classes themselves with class methods - it simply depends on
 
2664
    can be classes themselves with class methods - it simply depends on 
2777
2665
    whether state is needed for a given format or not.
2778
2666
 
2779
2667
    Once a format is deprecated, just deprecate the initialize and open
2780
 
    methods on the format class. Do not deprecate the object, as the
 
2668
    methods on the format class. Do not deprecate the object, as the 
2781
2669
    object will be created every time regardless.
2782
2670
    """
2783
2671
 
2796
2684
        """Return the format for the working tree object in a_bzrdir."""
2797
2685
        try:
2798
2686
            transport = a_bzrdir.get_workingtree_transport(None)
2799
 
            format_string = transport.get_bytes("format")
 
2687
            format_string = transport.get("format").read()
2800
2688
            return klass._formats[format_string]
2801
2689
        except errors.NoSuchFile:
2802
2690
            raise errors.NoWorkingTree(base=transport.base)
2827
2715
        """Is this format supported?
2828
2716
 
2829
2717
        Supported formats can be initialized and opened.
2830
 
        Unsupported formats may not support initialization or committing or
 
2718
        Unsupported formats may not support initialization or committing or 
2831
2719
        some other features depending on the reason for not being supported.
2832
2720
        """
2833
2721
        return True
2854
2742
 
2855
2743
 
2856
2744
class WorkingTreeFormat2(WorkingTreeFormat):
2857
 
    """The second working tree format.
 
2745
    """The second working tree format. 
2858
2746
 
2859
2747
    This format modified the hash cache from the format 1 hash cache.
2860
2748
    """
2873
2761
        no working tree.  (See bug #43064).
2874
2762
        """
2875
2763
        sio = StringIO()
2876
 
        inv = inventory.Inventory()
 
2764
        inv = Inventory()
2877
2765
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
2878
2766
        sio.seek(0)
2879
2767
        transport.put_file('inventory', sio, file_mode)
2895
2783
            branch.generate_revision_history(revision_id)
2896
2784
        finally:
2897
2785
            branch.unlock()
2898
 
        inv = inventory.Inventory()
 
2786
        inv = Inventory()
2899
2787
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2900
2788
                         branch,
2901
2789
                         inv,
2946
2834
        - is new in bzr 0.8
2947
2835
        - uses a LockDir to guard access for writes.
2948
2836
    """
2949
 
 
 
2837
    
2950
2838
    upgrade_recommended = True
2951
2839
 
2952
2840
    def get_format_string(self):
2969
2857
 
2970
2858
    def _open_control_files(self, a_bzrdir):
2971
2859
        transport = a_bzrdir.get_workingtree_transport(None)
2972
 
        return LockableFiles(transport, self._lock_file_name,
 
2860
        return LockableFiles(transport, self._lock_file_name, 
2973
2861
                             self._lock_class)
2974
2862
 
2975
2863
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2976
2864
                   accelerator_tree=None, hardlink=False):
2977
2865
        """See WorkingTreeFormat.initialize().
2978
 
 
 
2866
        
2979
2867
        :param revision_id: if supplied, create a working tree at a different
2980
2868
            revision than the branch is at.
2981
2869
        :param accelerator_tree: A tree which can be used for retrieving file
2992
2880
        control_files.create_lock()
2993
2881
        control_files.lock_write()
2994
2882
        transport.put_bytes('format', self.get_format_string(),
2995
 
            mode=a_bzrdir._get_file_mode())
 
2883
            mode=control_files._file_mode)
2996
2884
        if from_branch is not None:
2997
2885
            branch = from_branch
2998
2886
        else:
3018
2906
            # only set an explicit root id if there is one to set.
3019
2907
            if basis_tree.inventory.root is not None:
3020
2908
                wt.set_root_id(basis_tree.get_root_id())
3021
 
            if revision_id == _mod_revision.NULL_REVISION:
 
2909
            if revision_id == NULL_REVISION:
3022
2910
                wt.set_parent_trees([])
3023
2911
            else:
3024
2912
                wt.set_parent_trees([(revision_id, basis_tree)])
3031
2919
        return wt
3032
2920
 
3033
2921
    def _initial_inventory(self):
3034
 
        return inventory.Inventory()
 
2922
        return Inventory()
3035
2923
 
3036
2924
    def __init__(self):
3037
2925
        super(WorkingTreeFormat3, self).__init__()
3052
2940
 
3053
2941
    def _open(self, a_bzrdir, control_files):
3054
2942
        """Open the tree itself.
3055
 
 
 
2943
        
3056
2944
        :param a_bzrdir: the dir for the tree.
3057
2945
        :param control_files: the control files for the tree.
3058
2946
        """
3066
2954
        return self.get_format_string()
3067
2955
 
3068
2956
 
3069
 
__default_format = WorkingTreeFormat6()
 
2957
__default_format = WorkingTreeFormat4()
3070
2958
WorkingTreeFormat.register_format(__default_format)
3071
2959
WorkingTreeFormat.register_format(WorkingTreeFormat5())
3072
 
WorkingTreeFormat.register_format(WorkingTreeFormat4())
3073
2960
WorkingTreeFormat.register_format(WorkingTreeFormat3())
3074
2961
WorkingTreeFormat.set_default_format(__default_format)
3075
2962
# formats which have no format string are not discoverable