~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Joe Julian
  • Date: 2010-01-10 02:25:31 UTC
  • mto: (4634.119.7 2.0)
  • mto: This revision was merged to the branch mainline in revision 4959.
  • Revision ID: joe@julianfamily.org-20100110022531-wqk61rsagz8xsiga
Added MANIFEST.in to allow bdist_rpm to have all the required include files and tools. bdist_rpm will still fail to build correctly on some distributions due to a disttools bug http://bugs.python.org/issue644744

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, 2006, 2007, 2008, 2009 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
48
48
import itertools
49
49
import operator
50
50
import stat
51
 
from time import time
52
 
import warnings
53
51
import re
54
52
 
55
53
import bzrlib
57
55
    branch,
58
56
    bzrdir,
59
57
    conflicts as _mod_conflicts,
60
 
    dirstate,
61
58
    errors,
62
59
    generate_ids,
63
60
    globbing,
 
61
    graph as _mod_graph,
64
62
    hashcache,
65
63
    ignores,
 
64
    inventory,
66
65
    merge,
67
66
    revision as _mod_revision,
68
67
    revisiontree,
69
 
    repository,
70
68
    textui,
71
69
    trace,
72
70
    transform,
73
71
    ui,
74
 
    urlutils,
75
72
    views,
76
73
    xml5,
77
 
    xml6,
78
74
    xml7,
79
75
    )
80
76
import bzrlib.branch
81
77
from bzrlib.transport import get_transport
82
 
import bzrlib.ui
83
78
from bzrlib.workingtree_4 import (
84
79
    WorkingTreeFormat4,
85
80
    WorkingTreeFormat5,
89
84
 
90
85
from bzrlib import symbol_versioning
91
86
from bzrlib.decorators import needs_read_lock, needs_write_lock
92
 
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
93
87
from bzrlib.lockable_files import LockableFiles
94
88
from bzrlib.lockdir import LockDir
95
89
import bzrlib.mutabletree
96
90
from bzrlib.mutabletree import needs_tree_write_lock
97
91
from bzrlib import osutils
98
92
from bzrlib.osutils import (
99
 
    compact_date,
100
93
    file_kind,
101
94
    isdir,
102
95
    normpath,
103
96
    pathjoin,
104
 
    rand_chars,
105
97
    realpath,
106
98
    safe_unicode,
107
99
    splitpath,
111
103
from bzrlib.trace import mutter, note
112
104
from bzrlib.transport.local import LocalTransport
113
105
from bzrlib.progress import DummyProgress, ProgressPhase
114
 
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
 
106
from bzrlib.revision import CURRENT_REVISION
115
107
from bzrlib.rio import RioReader, rio_file, Stanza
116
 
from bzrlib.symbol_versioning import (deprecated_passed,
117
 
        deprecated_method,
118
 
        deprecated_function,
119
 
        DEPRECATED_PARAMETER,
120
 
        )
 
108
from bzrlib.symbol_versioning import (
 
109
    deprecated_passed,
 
110
    DEPRECATED_PARAMETER,
 
111
    )
121
112
 
122
113
 
123
114
MERGE_MODIFIED_HEADER_1 = "BZR merge-modified list format 1"
290
281
        self._control_files.break_lock()
291
282
        self.branch.break_lock()
292
283
 
 
284
    def _get_check_refs(self):
 
285
        """Return the references needed to perform a check of this tree.
 
286
        
 
287
        The default implementation returns no refs, and is only suitable for
 
288
        trees that have no local caching and can commit on ghosts at any time.
 
289
 
 
290
        :seealso: bzrlib.check for details about check_refs.
 
291
        """
 
292
        return []
 
293
 
293
294
    def requires_rich_root(self):
294
295
        return self._format.requires_rich_root
295
296
 
446
447
 
447
448
    def get_file_with_stat(self, file_id, path=None, filtered=True,
448
449
        _fstat=os.fstat):
449
 
        """See MutableTree.get_file_with_stat."""
 
450
        """See Tree.get_file_with_stat."""
450
451
        if path is None:
451
452
            path = self.id2path(file_id)
452
453
        file_obj = self.get_file_byname(path, filtered=False)
453
454
        stat_value = _fstat(file_obj.fileno())
454
 
        if self.supports_content_filtering() and filtered:
 
455
        if filtered and self.supports_content_filtering():
455
456
            filters = self._content_filter_stack(path)
456
457
            file_obj = filtered_input_file(file_obj, filters)
457
458
        return (file_obj, stat_value)
462
463
    def get_file_byname(self, filename, filtered=True):
463
464
        path = self.abspath(filename)
464
465
        f = file(path, 'rb')
465
 
        if self.supports_content_filtering() and filtered:
 
466
        if filtered and self.supports_content_filtering():
466
467
            filters = self._content_filter_stack(filename)
467
468
            return filtered_input_file(f, filters)
468
469
        else:
487
488
        incorrectly attributed to CURRENT_REVISION (but after committing, the
488
489
        attribution will be correct).
489
490
        """
490
 
        basis = self.basis_tree()
491
 
        basis.lock_read()
492
 
        try:
493
 
            changes = self.iter_changes(basis, True, [self.id2path(file_id)],
494
 
                require_versioned=True).next()
495
 
            changed_content, kind = changes[2], changes[6]
496
 
            if not changed_content:
497
 
                return basis.annotate_iter(file_id)
498
 
            if kind[1] is None:
499
 
                return None
500
 
            import annotate
501
 
            if kind[0] != 'file':
502
 
                old_lines = []
503
 
            else:
504
 
                old_lines = list(basis.annotate_iter(file_id))
505
 
            old = [old_lines]
506
 
            for tree in self.branch.repository.revision_trees(
507
 
                self.get_parent_ids()[1:]):
508
 
                if file_id not in tree:
509
 
                    continue
510
 
                old.append(list(tree.annotate_iter(file_id)))
511
 
            return annotate.reannotate(old, self.get_file(file_id).readlines(),
512
 
                                       default_revision)
513
 
        finally:
514
 
            basis.unlock()
 
491
        maybe_file_parent_keys = []
 
492
        for parent_id in self.get_parent_ids():
 
493
            try:
 
494
                parent_tree = self.revision_tree(parent_id)
 
495
            except errors.NoSuchRevisionInTree:
 
496
                parent_tree = self.branch.repository.revision_tree(parent_id)
 
497
            parent_tree.lock_read()
 
498
            try:
 
499
                if file_id not in parent_tree:
 
500
                    continue
 
501
                ie = parent_tree.inventory[file_id]
 
502
                if ie.kind != 'file':
 
503
                    # Note: this is slightly unnecessary, because symlinks and
 
504
                    # directories have a "text" which is the empty text, and we
 
505
                    # know that won't mess up annotations. But it seems cleaner
 
506
                    continue
 
507
                parent_text_key = (file_id, ie.revision)
 
508
                if parent_text_key not in maybe_file_parent_keys:
 
509
                    maybe_file_parent_keys.append(parent_text_key)
 
510
            finally:
 
511
                parent_tree.unlock()
 
512
        graph = _mod_graph.Graph(self.branch.repository.texts)
 
513
        heads = graph.heads(maybe_file_parent_keys)
 
514
        file_parent_keys = []
 
515
        for key in maybe_file_parent_keys:
 
516
            if key in heads:
 
517
                file_parent_keys.append(key)
 
518
 
 
519
        # Now we have the parents of this content
 
520
        annotator = self.branch.repository.texts.get_annotator()
 
521
        text = self.get_file(file_id).read()
 
522
        this_key =(file_id, default_revision)
 
523
        annotator.add_special_text(this_key, file_parent_keys, text)
 
524
        annotations = [(key[-1], line)
 
525
                       for key, line in annotator.annotate_flat(this_key)]
 
526
        return annotations
515
527
 
516
528
    def _get_ancestors(self, default_revision):
517
529
        ancestors = set([default_revision])
601
613
 
602
614
    def get_file_size(self, file_id):
603
615
        """See Tree.get_file_size"""
 
616
        # XXX: this returns the on-disk size; it should probably return the
 
617
        # canonical size
604
618
        try:
605
619
            return os.path.getsize(self.id2abspath(file_id))
606
620
        except OSError, e:
737
751
            raise
738
752
        kind = _mapper(stat_result.st_mode)
739
753
        if kind == 'file':
740
 
            size = stat_result.st_size
741
 
            # try for a stat cache lookup
742
 
            executable = self._is_executable_from_path_and_stat(path, stat_result)
743
 
            return (kind, size, executable, self._sha_from_stat(
744
 
                path, stat_result))
 
754
            return self._file_content_summary(path, stat_result)
745
755
        elif kind == 'directory':
746
756
            # perhaps it looks like a plain directory, but it's really a
747
757
            # reference.
749
759
                kind = 'tree-reference'
750
760
            return kind, None, None, None
751
761
        elif kind == 'symlink':
752
 
            return ('symlink', None, None,
753
 
                    os.readlink(abspath.encode(osutils._fs_enc)
754
 
                                ).decode(osutils._fs_enc))
 
762
            target = osutils.readlink(abspath)
 
763
            return ('symlink', None, None, target)
755
764
        else:
756
765
            return (kind, None, None, None)
757
766
 
 
767
    def _file_content_summary(self, path, stat_result):
 
768
        size = stat_result.st_size
 
769
        executable = self._is_executable_from_path_and_stat(path, stat_result)
 
770
        # try for a stat cache lookup
 
771
        return ('file', size, executable, self._sha_from_stat(
 
772
            path, stat_result))
 
773
 
758
774
    def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
759
775
        """Common ghost checking functionality from set_parent_*.
760
776
 
890
906
            branch.last_revision().
891
907
        """
892
908
        from bzrlib.merge import Merger, Merge3Merger
893
 
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
909
        pb = ui.ui_factory.nested_progress_bar()
894
910
        try:
895
911
            merger = Merger(self.branch, this_tree=self, pb=pb)
896
912
            merger.pp = ProgressPhase("Merge phase", 5, pb)
973
989
        return file_id
974
990
 
975
991
    def get_symlink_target(self, file_id):
976
 
        return os.readlink(self.id2abspath(file_id).encode(osutils._fs_enc)
977
 
            ).decode(osutils._fs_enc)
 
992
        abspath = self.id2abspath(file_id)
 
993
        target = osutils.readlink(abspath)
 
994
        return target
978
995
 
979
996
    @needs_write_lock
980
997
    def subsume(self, other_tree):
1081
1098
            branch.BranchReferenceFormat().initialize(tree_bzrdir, new_branch)
1082
1099
        else:
1083
1100
            tree_bzrdir = branch_bzrdir
1084
 
        wt = tree_bzrdir.create_workingtree(NULL_REVISION)
 
1101
        wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
1085
1102
        wt.set_parent_ids(self.get_parent_ids())
1086
1103
        my_inv = self.inventory
1087
 
        child_inv = Inventory(root_id=None)
 
1104
        child_inv = inventory.Inventory(root_id=None)
1088
1105
        new_root = my_inv[file_id]
1089
1106
        my_inv.remove_recursive_id(file_id)
1090
1107
        new_root.parent_id = None
1115
1132
    def _kind(self, relpath):
1116
1133
        return osutils.file_kind(self.abspath(relpath))
1117
1134
 
1118
 
    def list_files(self, include_root=False):
1119
 
        """Recursively list all files as (path, class, kind, id, entry).
 
1135
    def list_files(self, include_root=False, from_dir=None, recursive=True):
 
1136
        """List all files as (path, class, kind, id, entry).
1120
1137
 
1121
1138
        Lists, but does not descend into unversioned directories.
1122
 
 
1123
1139
        This does not include files that have been deleted in this
1124
 
        tree.
 
1140
        tree. Skips the control directory.
1125
1141
 
1126
 
        Skips the control directory.
 
1142
        :param include_root: if True, do not return an entry for the root
 
1143
        :param from_dir: start from this directory or None for the root
 
1144
        :param recursive: whether to recurse into subdirectories or not
1127
1145
        """
1128
1146
        # list_files is an iterator, so @needs_read_lock doesn't work properly
1129
1147
        # with it. So callers should be careful to always read_lock the tree.
1131
1149
            raise errors.ObjectNotLocked(self)
1132
1150
 
1133
1151
        inv = self.inventory
1134
 
        if include_root is True:
 
1152
        if from_dir is None and include_root is True:
1135
1153
            yield ('', 'V', 'directory', inv.root.file_id, inv.root)
1136
1154
        # Convert these into local objects to save lookup times
1137
1155
        pathjoin = osutils.pathjoin
1144
1162
        fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
1145
1163
 
1146
1164
        # directory file_id, relative path, absolute path, reverse sorted children
1147
 
        children = os.listdir(self.basedir)
 
1165
        if from_dir is not None:
 
1166
            from_dir_id = inv.path2id(from_dir)
 
1167
            if from_dir_id is None:
 
1168
                # Directory not versioned
 
1169
                return
 
1170
            from_dir_abspath = pathjoin(self.basedir, from_dir)
 
1171
        else:
 
1172
            from_dir_id = inv.root.file_id
 
1173
            from_dir_abspath = self.basedir
 
1174
        children = os.listdir(from_dir_abspath)
1148
1175
        children.sort()
1149
1176
        # jam 20060527 The kernel sized tree seems equivalent whether we
1150
1177
        # use a deque and popleft to keep them sorted, or if we use a plain
1151
1178
        # list and just reverse() them.
1152
1179
        children = collections.deque(children)
1153
 
        stack = [(inv.root.file_id, u'', self.basedir, children)]
 
1180
        stack = [(from_dir_id, u'', from_dir_abspath, children)]
1154
1181
        while stack:
1155
1182
            from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
1156
1183
 
1214
1241
                if fk != 'directory':
1215
1242
                    continue
1216
1243
 
1217
 
                # But do this child first
1218
 
                new_children = os.listdir(fap)
1219
 
                new_children.sort()
1220
 
                new_children = collections.deque(new_children)
1221
 
                stack.append((f_ie.file_id, fp, fap, new_children))
1222
 
                # Break out of inner loop,
1223
 
                # so that we start outer loop with child
1224
 
                break
 
1244
                # But do this child first if recursing down
 
1245
                if recursive:
 
1246
                    new_children = os.listdir(fap)
 
1247
                    new_children.sort()
 
1248
                    new_children = collections.deque(new_children)
 
1249
                    stack.append((f_ie.file_id, fp, fap, new_children))
 
1250
                    # Break out of inner loop,
 
1251
                    # so that we start outer loop with child
 
1252
                    break
1225
1253
            else:
1226
1254
                # if we finished all children, pop it off the stack
1227
1255
                stack.pop()
1405
1433
        inv = self.inventory
1406
1434
        for entry in moved:
1407
1435
            try:
1408
 
                self._move_entry(_RenameEntry(entry.to_rel, entry.from_id,
 
1436
                self._move_entry(WorkingTree._RenameEntry(
 
1437
                    entry.to_rel, entry.from_id,
1409
1438
                    entry.to_tail, entry.to_parent_id, entry.from_rel,
1410
1439
                    entry.from_tail, entry.from_parent_id,
1411
1440
                    entry.only_change_inv))
1462
1491
        from_tail = splitpath(from_rel)[-1]
1463
1492
        from_id = inv.path2id(from_rel)
1464
1493
        if from_id is None:
1465
 
            raise errors.BzrRenameFailedError(from_rel,to_rel,
1466
 
                errors.NotVersionedError(path=str(from_rel)))
1467
 
        from_entry = inv[from_id]
 
1494
            # if file is missing in the inventory maybe it's in the basis_tree
 
1495
            basis_tree = self.branch.basis_tree()
 
1496
            from_id = basis_tree.path2id(from_rel)
 
1497
            if from_id is None:
 
1498
                raise errors.BzrRenameFailedError(from_rel,to_rel,
 
1499
                    errors.NotVersionedError(path=str(from_rel)))
 
1500
            # put entry back in the inventory so we can rename it
 
1501
            from_entry = basis_tree.inventory[from_id].copy()
 
1502
            inv.add(from_entry)
 
1503
        else:
 
1504
            from_entry = inv[from_id]
1468
1505
        from_parent_id = from_entry.parent_id
1469
1506
        to_dir, to_tail = os.path.split(to_rel)
1470
1507
        to_dir_id = inv.path2id(to_dir)
1561
1598
 
1562
1599
    @needs_write_lock
1563
1600
    def pull(self, source, overwrite=False, stop_revision=None,
1564
 
             change_reporter=None, possible_transports=None):
1565
 
        top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
1601
             change_reporter=None, possible_transports=None, local=False):
 
1602
        top_pb = ui.ui_factory.nested_progress_bar()
1566
1603
        source.lock_read()
1567
1604
        try:
1568
1605
            pp = ProgressPhase("Pull phase", 2, top_pb)
1570
1607
            old_revision_info = self.branch.last_revision_info()
1571
1608
            basis_tree = self.basis_tree()
1572
1609
            count = self.branch.pull(source, overwrite, stop_revision,
1573
 
                                     possible_transports=possible_transports)
 
1610
                                     possible_transports=possible_transports,
 
1611
                                     local=local)
1574
1612
            new_revision_info = self.branch.last_revision_info()
1575
1613
            if new_revision_info != old_revision_info:
1576
1614
                pp.next_phase()
1577
1615
                repository = self.branch.repository
1578
 
                pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
1616
                pb = ui.ui_factory.nested_progress_bar()
1579
1617
                basis_tree.lock_read()
1580
1618
                try:
1581
1619
                    new_basis_tree = self.branch.basis_tree()
1641
1679
 
1642
1680
            fl = []
1643
1681
            for subf in os.listdir(dirabs):
1644
 
                if subf == '.bzr':
 
1682
                if self.bzrdir.is_control_filename(subf):
1645
1683
                    continue
1646
1684
                if subf not in dir_entry.children:
1647
1685
                    try:
1860
1898
            firstline = xml.split('\n', 1)[0]
1861
1899
            if (not 'revision_id="' in firstline or
1862
1900
                'format="7"' not in firstline):
1863
 
                inv = self.branch.repository.deserialise_inventory(
1864
 
                    new_revision, xml)
 
1901
                inv = self.branch.repository._serializer.read_inventory_from_string(
 
1902
                    xml, new_revision)
1865
1903
                xml = self._create_basis_xml_from_inventory(new_revision, inv)
1866
1904
            self._write_basis_inventory(xml)
1867
1905
        except (errors.NoSuchRevision, errors.RevisionNotPresent):
2030
2068
            if filenames is None and len(self.get_parent_ids()) > 1:
2031
2069
                parent_trees = []
2032
2070
                last_revision = self.last_revision()
2033
 
                if last_revision != NULL_REVISION:
 
2071
                if last_revision != _mod_revision.NULL_REVISION:
2034
2072
                    if basis_tree is None:
2035
2073
                        basis_tree = self.basis_tree()
2036
2074
                        basis_tree.lock_read()
2074
2112
    def set_inventory(self, new_inventory_list):
2075
2113
        from bzrlib.inventory import (Inventory,
2076
2114
                                      InventoryDirectory,
2077
 
                                      InventoryEntry,
2078
2115
                                      InventoryFile,
2079
2116
                                      InventoryLink)
2080
2117
        inv = Inventory(self.get_root_id())
2373
2410
                    bzrdir_loc = bisect_left(cur_disk_dir_content,
2374
2411
                        ('.bzr', '.bzr'))
2375
2412
                    if (bzrdir_loc < len(cur_disk_dir_content)
2376
 
                        and cur_disk_dir_content[bzrdir_loc][0] == '.bzr'):
 
2413
                        and self.bzrdir.is_control_filename(
 
2414
                            cur_disk_dir_content[bzrdir_loc][0])):
2377
2415
                        # we dont yield the contents of, or, .bzr itself.
2378
2416
                        del cur_disk_dir_content[bzrdir_loc]
2379
2417
            if inv_finished:
2513
2551
        return un_resolved, resolved
2514
2552
 
2515
2553
    @needs_read_lock
2516
 
    def _check(self):
 
2554
    def _check(self, references):
 
2555
        """Check the tree for consistency.
 
2556
 
 
2557
        :param references: A dict with keys matching the items returned by
 
2558
            self._get_check_refs(), and values from looking those keys up in
 
2559
            the repository.
 
2560
        """
2517
2561
        tree_basis = self.basis_tree()
2518
2562
        tree_basis.lock_read()
2519
2563
        try:
2520
 
            repo_basis = self.branch.repository.revision_tree(
2521
 
                self.last_revision())
 
2564
            repo_basis = references[('trees', self.last_revision())]
2522
2565
            if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2523
2566
                raise errors.BzrCheckError(
2524
2567
                    "Mismatched basis inventory content.")
2570
2613
        if self._inventory is None:
2571
2614
            self.read_working_inventory()
2572
2615
 
 
2616
    def _get_check_refs(self):
 
2617
        """Return the references needed to perform a check of this tree."""
 
2618
        return [('trees', self.last_revision())]
 
2619
 
2573
2620
    def lock_tree_write(self):
2574
2621
        """See WorkingTree.lock_tree_write().
2575
2622
 
2621
2668
 
2622
2669
    def _change_last_revision(self, revision_id):
2623
2670
        """See WorkingTree._change_last_revision."""
2624
 
        if revision_id is None or revision_id == NULL_REVISION:
 
2671
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
2625
2672
            try:
2626
2673
                self._transport.delete('last-revision')
2627
2674
            except errors.NoSuchFile:
2632
2679
                mode=self.bzrdir._get_file_mode())
2633
2680
            return True
2634
2681
 
 
2682
    def _get_check_refs(self):
 
2683
        """Return the references needed to perform a check of this tree."""
 
2684
        return [('trees', self.last_revision())]
 
2685
 
2635
2686
    @needs_tree_write_lock
2636
2687
    def set_conflicts(self, conflicts):
2637
2688
        self._put_rio('conflicts', conflicts.to_stanzas(),
2791
2842
        no working tree.  (See bug #43064).
2792
2843
        """
2793
2844
        sio = StringIO()
2794
 
        inv = Inventory()
 
2845
        inv = inventory.Inventory()
2795
2846
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
2796
2847
        sio.seek(0)
2797
2848
        transport.put_file('inventory', sio, file_mode)
2813
2864
            branch.generate_revision_history(revision_id)
2814
2865
        finally:
2815
2866
            branch.unlock()
2816
 
        inv = Inventory()
 
2867
        inv = inventory.Inventory()
2817
2868
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2818
2869
                         branch,
2819
2870
                         inv,
2936
2987
            # only set an explicit root id if there is one to set.
2937
2988
            if basis_tree.inventory.root is not None:
2938
2989
                wt.set_root_id(basis_tree.get_root_id())
2939
 
            if revision_id == NULL_REVISION:
 
2990
            if revision_id == _mod_revision.NULL_REVISION:
2940
2991
                wt.set_parent_trees([])
2941
2992
            else:
2942
2993
                wt.set_parent_trees([(revision_id, basis_tree)])
2949
3000
        return wt
2950
3001
 
2951
3002
    def _initial_inventory(self):
2952
 
        return Inventory()
 
3003
        return inventory.Inventory()
2953
3004
 
2954
3005
    def __init__(self):
2955
3006
        super(WorkingTreeFormat3, self).__init__()
2984
3035
        return self.get_format_string()
2985
3036
 
2986
3037
 
2987
 
__default_format = WorkingTreeFormat4()
 
3038
__default_format = WorkingTreeFormat6()
2988
3039
WorkingTreeFormat.register_format(__default_format)
2989
 
WorkingTreeFormat.register_format(WorkingTreeFormat6())
2990
3040
WorkingTreeFormat.register_format(WorkingTreeFormat5())
 
3041
WorkingTreeFormat.register_format(WorkingTreeFormat4())
2991
3042
WorkingTreeFormat.register_format(WorkingTreeFormat3())
2992
3043
WorkingTreeFormat.set_default_format(__default_format)
2993
3044
# formats which have no format string are not discoverable