~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Jelmer Vernooij
  • Date: 2011-04-19 10:42:59 UTC
  • mto: This revision was merged to the branch mainline in revision 5806.
  • Revision ID: jelmer@samba.org-20110419104259-g9exlcp1f5jdu3ci
Move Inventory._get_mutable_inventory -> mutable_inventory_from_tree.

Show diffs side-by-side

added added

removed removed

Lines of Context:
68
68
    xml5,
69
69
    xml7,
70
70
    )
 
71
from bzrlib.workingtree_4 import (
 
72
    WorkingTreeFormat4,
 
73
    WorkingTreeFormat5,
 
74
    WorkingTreeFormat6,
 
75
    )
71
76
""")
72
77
 
73
78
from bzrlib import symbol_versioning
74
79
from bzrlib.decorators import needs_read_lock, needs_write_lock
75
80
from bzrlib.lock import LogicalLockResult
 
81
from bzrlib.lockable_files import LockableFiles
 
82
from bzrlib.lockdir import LockDir
76
83
import bzrlib.mutabletree
77
84
from bzrlib.mutabletree import needs_tree_write_lock
78
85
from bzrlib import osutils
87
94
    supports_executable,
88
95
    )
89
96
from bzrlib.trace import mutter, note
 
97
from bzrlib.transport.local import LocalTransport
90
98
from bzrlib.revision import CURRENT_REVISION
91
99
from bzrlib.symbol_versioning import (
92
100
    deprecated_passed,
750
758
        self._set_merges_from_parent_ids(revision_ids)
751
759
 
752
760
    @needs_tree_write_lock
 
761
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
 
762
        """See MutableTree.set_parent_trees."""
 
763
        parent_ids = [rev for (rev, tree) in parents_list]
 
764
        for revision_id in parent_ids:
 
765
            _mod_revision.check_not_reserved_id(revision_id)
 
766
 
 
767
        self._check_parents_for_ghosts(parent_ids,
 
768
            allow_leftmost_as_ghost=allow_leftmost_as_ghost)
 
769
 
 
770
        parent_ids = self._filter_parent_ids_by_ancestry(parent_ids)
 
771
 
 
772
        if len(parent_ids) == 0:
 
773
            leftmost_parent_id = _mod_revision.NULL_REVISION
 
774
            leftmost_parent_tree = None
 
775
        else:
 
776
            leftmost_parent_id, leftmost_parent_tree = parents_list[0]
 
777
 
 
778
        if self._change_last_revision(leftmost_parent_id):
 
779
            if leftmost_parent_tree is None:
 
780
                # If we don't have a tree, fall back to reading the
 
781
                # parent tree from the repository.
 
782
                self._cache_basis_inventory(leftmost_parent_id)
 
783
            else:
 
784
                inv = leftmost_parent_tree.inventory
 
785
                xml = self._create_basis_xml_from_inventory(
 
786
                                        leftmost_parent_id, inv)
 
787
                self._write_basis_inventory(xml)
 
788
        self._set_merges_from_parent_ids(parent_ids)
 
789
 
 
790
    @needs_tree_write_lock
753
791
    def set_pending_merges(self, rev_list):
754
792
        parents = self.get_parent_ids()
755
793
        leftmost = parents[:1]
1226
1264
        when their last revision is set.
1227
1265
        """
1228
1266
        if _mod_revision.is_null(new_revision):
1229
 
            self.branch.set_last_revision_info(0, new_revision)
 
1267
            self.branch.set_revision_history([])
1230
1268
            return False
1231
1269
        try:
1232
1270
            self.branch.generate_revision_history(new_revision)
1233
1271
        except errors.NoSuchRevision:
1234
1272
            # not present in the repo - dont try to set it deeper than the tip
1235
 
            self.branch._set_revision_history([new_revision])
 
1273
            self.branch.set_revision_history([new_revision])
1236
1274
        return True
1237
1275
 
1238
1276
    @needs_tree_write_lock
1947
1985
        """See Tree.iter_all_file_ids"""
1948
1986
        return set(self.inventory)
1949
1987
 
1950
 
    @needs_tree_write_lock
1951
 
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
1952
 
        """See MutableTree.set_parent_trees."""
1953
 
        parent_ids = [rev for (rev, tree) in parents_list]
1954
 
        for revision_id in parent_ids:
1955
 
            _mod_revision.check_not_reserved_id(revision_id)
1956
 
 
1957
 
        self._check_parents_for_ghosts(parent_ids,
1958
 
            allow_leftmost_as_ghost=allow_leftmost_as_ghost)
1959
 
 
1960
 
        parent_ids = self._filter_parent_ids_by_ancestry(parent_ids)
1961
 
 
1962
 
        if len(parent_ids) == 0:
1963
 
            leftmost_parent_id = _mod_revision.NULL_REVISION
1964
 
            leftmost_parent_tree = None
1965
 
        else:
1966
 
            leftmost_parent_id, leftmost_parent_tree = parents_list[0]
1967
 
 
1968
 
        if self._change_last_revision(leftmost_parent_id):
1969
 
            if leftmost_parent_tree is None:
1970
 
                # If we don't have a tree, fall back to reading the
1971
 
                # parent tree from the repository.
1972
 
                self._cache_basis_inventory(leftmost_parent_id)
1973
 
            else:
1974
 
                inv = leftmost_parent_tree.inventory
1975
 
                xml = self._create_basis_xml_from_inventory(
1976
 
                                        leftmost_parent_id, inv)
1977
 
                self._write_basis_inventory(xml)
1978
 
        self._set_merges_from_parent_ids(parent_ids)
1979
 
 
1980
1988
    def _cache_basis_inventory(self, new_revision):
1981
1989
        """Cache new_revision as the basis inventory."""
1982
1990
        # TODO: this should allow the ready-to-use inventory to be passed in,
2012
2020
        inventory.revision_id = revision_id
2013
2021
        return xml7.serializer_v7.write_inventory_to_string(inventory)
2014
2022
 
2015
 
    @needs_tree_write_lock
2016
 
    def set_conflicts(self, conflicts):
2017
 
        self._put_rio('conflicts', conflicts.to_stanzas(),
2018
 
                      CONFLICT_HEADER_1)
2019
 
 
2020
 
    @needs_tree_write_lock
2021
 
    def add_conflicts(self, new_conflicts):
2022
 
        conflict_set = set(self.conflicts())
2023
 
        conflict_set.update(set(list(new_conflicts)))
2024
 
        self.set_conflicts(_mod_conflicts.ConflictList(sorted(conflict_set,
2025
 
                                       key=_mod_conflicts.Conflict.sort_key)))
2026
 
 
2027
 
    @needs_read_lock
2028
 
    def conflicts(self):
2029
 
        try:
2030
 
            confile = self._transport.get('conflicts')
2031
 
        except errors.NoSuchFile:
2032
 
            return _mod_conflicts.ConflictList()
2033
 
        try:
2034
 
            try:
2035
 
                if confile.next() != CONFLICT_HEADER_1 + '\n':
2036
 
                    raise errors.ConflictFormatError()
2037
 
            except StopIteration:
2038
 
                raise errors.ConflictFormatError()
2039
 
            reader = _mod_rio.RioReader(confile)
2040
 
            return _mod_conflicts.ConflictList.from_stanzas(reader)
2041
 
        finally:
2042
 
            confile.close()
2043
 
 
2044
2023
    def read_basis_inventory(self):
2045
2024
        """Read the cached basis inventory."""
2046
2025
        path = self._basis_inventory_name()
2909
2888
                    pending.append(dir)
2910
2889
 
2911
2890
 
 
2891
class WorkingTree3(InventoryWorkingTree):
 
2892
    """This is the Format 3 working tree.
 
2893
 
 
2894
    This differs from the base WorkingTree by:
 
2895
     - having its own file lock
 
2896
     - having its own last-revision property.
 
2897
 
 
2898
    This is new in bzr 0.8
 
2899
    """
 
2900
 
 
2901
    @needs_read_lock
 
2902
    def _last_revision(self):
 
2903
        """See Mutable.last_revision."""
 
2904
        try:
 
2905
            return self._transport.get_bytes('last-revision')
 
2906
        except errors.NoSuchFile:
 
2907
            return _mod_revision.NULL_REVISION
 
2908
 
 
2909
    def _change_last_revision(self, revision_id):
 
2910
        """See WorkingTree._change_last_revision."""
 
2911
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
 
2912
            try:
 
2913
                self._transport.delete('last-revision')
 
2914
            except errors.NoSuchFile:
 
2915
                pass
 
2916
            return False
 
2917
        else:
 
2918
            self._transport.put_bytes('last-revision', revision_id,
 
2919
                mode=self.bzrdir._get_file_mode())
 
2920
            return True
 
2921
 
 
2922
    def _get_check_refs(self):
 
2923
        """Return the references needed to perform a check of this tree."""
 
2924
        return [('trees', self.last_revision())]
 
2925
 
 
2926
    @needs_tree_write_lock
 
2927
    def set_conflicts(self, conflicts):
 
2928
        self._put_rio('conflicts', conflicts.to_stanzas(),
 
2929
                      CONFLICT_HEADER_1)
 
2930
 
 
2931
    @needs_tree_write_lock
 
2932
    def add_conflicts(self, new_conflicts):
 
2933
        conflict_set = set(self.conflicts())
 
2934
        conflict_set.update(set(list(new_conflicts)))
 
2935
        self.set_conflicts(_mod_conflicts.ConflictList(sorted(conflict_set,
 
2936
                                       key=_mod_conflicts.Conflict.sort_key)))
 
2937
 
 
2938
    @needs_read_lock
 
2939
    def conflicts(self):
 
2940
        try:
 
2941
            confile = self._transport.get('conflicts')
 
2942
        except errors.NoSuchFile:
 
2943
            return _mod_conflicts.ConflictList()
 
2944
        try:
 
2945
            try:
 
2946
                if confile.next() != CONFLICT_HEADER_1 + '\n':
 
2947
                    raise errors.ConflictFormatError()
 
2948
            except StopIteration:
 
2949
                raise errors.ConflictFormatError()
 
2950
            reader = _mod_rio.RioReader(confile)
 
2951
            return _mod_conflicts.ConflictList.from_stanzas(reader)
 
2952
        finally:
 
2953
            confile.close()
 
2954
 
 
2955
    def unlock(self):
 
2956
        # do non-implementation specific cleanup
 
2957
        self._cleanup()
 
2958
        if self._control_files._lock_count == 1:
 
2959
            # _inventory_is_modified is always False during a read lock.
 
2960
            if self._inventory_is_modified:
 
2961
                self.flush()
 
2962
            self._write_hashcache_if_dirty()
 
2963
        # reverse order of locking.
 
2964
        try:
 
2965
            return self._control_files.unlock()
 
2966
        finally:
 
2967
            self.branch.unlock()
 
2968
 
 
2969
 
2912
2970
class WorkingTreeFormatRegistry(controldir.ControlComponentFormatRegistry):
2913
2971
    """Registry for working tree formats."""
2914
2972
 
2915
2973
    def __init__(self, other_registry=None):
2916
2974
        super(WorkingTreeFormatRegistry, self).__init__(other_registry)
2917
2975
        self._default_format = None
2918
 
        self._default_format_key = None
2919
2976
 
2920
2977
    def get_default(self):
2921
2978
        """Return the current default format."""
2922
 
        if (self._default_format_key is not None and
2923
 
            self._default_format is None):
2924
 
            self._default_format = self.get(self._default_format_key)
2925
2979
        return self._default_format
2926
2980
 
2927
2981
    def set_default(self, format):
2928
 
        """Set the default format."""
2929
2982
        self._default_format = format
2930
 
        self._default_format_key = None
2931
 
 
2932
 
    def set_default_key(self, format_string):
2933
 
        """Set the default format by its format string."""
2934
 
        self._default_format_key = format_string
2935
 
        self._default_format = None
2936
2983
 
2937
2984
 
2938
2985
format_registry = WorkingTreeFormatRegistry()
2968
3015
    """If this format supports missing parent conflicts."""
2969
3016
 
2970
3017
    @classmethod
2971
 
    def find_format_string(klass, a_bzrdir):
2972
 
        """Return format name for the working tree object in a_bzrdir."""
2973
 
        try:
2974
 
            transport = a_bzrdir.get_workingtree_transport(None)
2975
 
            return transport.get_bytes("format")
2976
 
        except errors.NoSuchFile:
2977
 
            raise errors.NoWorkingTree(base=transport.base)
2978
 
 
2979
 
    @classmethod
2980
3018
    def find_format(klass, a_bzrdir):
2981
3019
        """Return the format for the working tree object in a_bzrdir."""
2982
3020
        try:
2983
 
            format_string = klass.find_format_string(a_bzrdir)
 
3021
            transport = a_bzrdir.get_workingtree_transport(None)
 
3022
            format_string = transport.get_bytes("format")
2984
3023
            return format_registry.get(format_string)
 
3024
        except errors.NoSuchFile:
 
3025
            raise errors.NoWorkingTree(base=transport.base)
2985
3026
        except KeyError:
2986
3027
            raise errors.UnknownFormatError(format=format_string,
2987
3028
                                            kind="working tree")
3078
3119
        format_registry.remove(format)
3079
3120
 
3080
3121
 
 
3122
class WorkingTreeFormat3(WorkingTreeFormat):
 
3123
    """The second working tree format updated to record a format marker.
 
3124
 
 
3125
    This format:
 
3126
        - exists within a metadir controlling .bzr
 
3127
        - includes an explicit version marker for the workingtree control
 
3128
          files, separate from the BzrDir format
 
3129
        - modifies the hash cache format
 
3130
        - is new in bzr 0.8
 
3131
        - uses a LockDir to guard access for writes.
 
3132
    """
 
3133
 
 
3134
    upgrade_recommended = True
 
3135
 
 
3136
    missing_parent_conflicts = True
 
3137
 
 
3138
    def get_format_string(self):
 
3139
        """See WorkingTreeFormat.get_format_string()."""
 
3140
        return "Bazaar-NG Working Tree format 3"
 
3141
 
 
3142
    def get_format_description(self):
 
3143
        """See WorkingTreeFormat.get_format_description()."""
 
3144
        return "Working tree format 3"
 
3145
 
 
3146
    _lock_file_name = 'lock'
 
3147
    _lock_class = LockDir
 
3148
 
 
3149
    _tree_class = WorkingTree3
 
3150
 
 
3151
    def __get_matchingbzrdir(self):
 
3152
        return bzrdir.BzrDirMetaFormat1()
 
3153
 
 
3154
    _matchingbzrdir = property(__get_matchingbzrdir)
 
3155
 
 
3156
    def _open_control_files(self, a_bzrdir):
 
3157
        transport = a_bzrdir.get_workingtree_transport(None)
 
3158
        return LockableFiles(transport, self._lock_file_name,
 
3159
                             self._lock_class)
 
3160
 
 
3161
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
3162
                   accelerator_tree=None, hardlink=False):
 
3163
        """See WorkingTreeFormat.initialize().
 
3164
 
 
3165
        :param revision_id: if supplied, create a working tree at a different
 
3166
            revision than the branch is at.
 
3167
        :param accelerator_tree: A tree which can be used for retrieving file
 
3168
            contents more quickly than the revision tree, i.e. a workingtree.
 
3169
            The revision tree will be used for cases where accelerator_tree's
 
3170
            content is different.
 
3171
        :param hardlink: If true, hard-link files from accelerator_tree,
 
3172
            where possible.
 
3173
        """
 
3174
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
3175
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
3176
        transport = a_bzrdir.get_workingtree_transport(self)
 
3177
        control_files = self._open_control_files(a_bzrdir)
 
3178
        control_files.create_lock()
 
3179
        control_files.lock_write()
 
3180
        transport.put_bytes('format', self.get_format_string(),
 
3181
            mode=a_bzrdir._get_file_mode())
 
3182
        if from_branch is not None:
 
3183
            branch = from_branch
 
3184
        else:
 
3185
            branch = a_bzrdir.open_branch()
 
3186
        if revision_id is None:
 
3187
            revision_id = _mod_revision.ensure_null(branch.last_revision())
 
3188
        # WorkingTree3 can handle an inventory which has a unique root id.
 
3189
        # as of bzr 0.12. However, bzr 0.11 and earlier fail to handle
 
3190
        # those trees. And because there isn't a format bump inbetween, we
 
3191
        # are maintaining compatibility with older clients.
 
3192
        # inv = Inventory(root_id=gen_root_id())
 
3193
        inv = self._initial_inventory()
 
3194
        wt = self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
 
3195
                         branch,
 
3196
                         inv,
 
3197
                         _internal=True,
 
3198
                         _format=self,
 
3199
                         _bzrdir=a_bzrdir,
 
3200
                         _control_files=control_files)
 
3201
        wt.lock_tree_write()
 
3202
        try:
 
3203
            basis_tree = branch.repository.revision_tree(revision_id)
 
3204
            # only set an explicit root id if there is one to set.
 
3205
            if basis_tree.inventory.root is not None:
 
3206
                wt.set_root_id(basis_tree.get_root_id())
 
3207
            if revision_id == _mod_revision.NULL_REVISION:
 
3208
                wt.set_parent_trees([])
 
3209
            else:
 
3210
                wt.set_parent_trees([(revision_id, basis_tree)])
 
3211
            transform.build_tree(basis_tree, wt)
 
3212
        finally:
 
3213
            # Unlock in this order so that the unlock-triggers-flush in
 
3214
            # WorkingTree is given a chance to fire.
 
3215
            control_files.unlock()
 
3216
            wt.unlock()
 
3217
        return wt
 
3218
 
 
3219
    def _initial_inventory(self):
 
3220
        return inventory.Inventory()
 
3221
 
 
3222
    def __init__(self):
 
3223
        super(WorkingTreeFormat3, self).__init__()
 
3224
 
 
3225
    def open(self, a_bzrdir, _found=False):
 
3226
        """Return the WorkingTree object for a_bzrdir
 
3227
 
 
3228
        _found is a private parameter, do not use it. It is used to indicate
 
3229
               if format probing has already been done.
 
3230
        """
 
3231
        if not _found:
 
3232
            # we are being called directly and must probe.
 
3233
            raise NotImplementedError
 
3234
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
3235
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
3236
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
 
3237
        return wt
 
3238
 
 
3239
    def _open(self, a_bzrdir, control_files):
 
3240
        """Open the tree itself.
 
3241
 
 
3242
        :param a_bzrdir: the dir for the tree.
 
3243
        :param control_files: the control files for the tree.
 
3244
        """
 
3245
        return self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
 
3246
                                _internal=True,
 
3247
                                _format=self,
 
3248
                                _bzrdir=a_bzrdir,
 
3249
                                _control_files=control_files)
 
3250
 
 
3251
    def __str__(self):
 
3252
        return self.get_format_string()
 
3253
 
 
3254
 
 
3255
__default_format = WorkingTreeFormat6()
3081
3256
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3082
3257
    "bzrlib.workingtree_4", "WorkingTreeFormat4")
3083
3258
format_registry.register_lazy("Bazaar Working Tree Format 5 (bzr 1.11)\n",
3084
3259
    "bzrlib.workingtree_4", "WorkingTreeFormat5")
3085
3260
format_registry.register_lazy("Bazaar Working Tree Format 6 (bzr 1.14)\n",
3086
3261
    "bzrlib.workingtree_4", "WorkingTreeFormat6")
3087
 
format_registry.register_lazy("Bazaar-NG Working Tree format 3",
3088
 
    "bzrlib.workingtree_3", "WorkingTreeFormat3")
3089
 
format_registry.set_default_key("Bazaar Working Tree Format 6 (bzr 1.14)\n")
 
3262
format_registry.register(WorkingTreeFormat3())
 
3263
format_registry.set_default(__default_format)