~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

(jelmer) Skip tests that require an inventory when run against a WorkingTree
 that is not inventory based. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
73
73
from bzrlib import symbol_versioning
74
74
from bzrlib.decorators import needs_read_lock, needs_write_lock
75
75
from bzrlib.lock import LogicalLockResult
 
76
from bzrlib.lockable_files import LockableFiles
 
77
from bzrlib.lockdir import LockDir
76
78
import bzrlib.mutabletree
77
79
from bzrlib.mutabletree import needs_tree_write_lock
78
80
from bzrlib import osutils
87
89
    supports_executable,
88
90
    )
89
91
from bzrlib.trace import mutter, note
 
92
from bzrlib.transport.local import LocalTransport
90
93
from bzrlib.revision import CURRENT_REVISION
91
94
from bzrlib.symbol_versioning import (
92
95
    deprecated_passed,
2012
2015
        inventory.revision_id = revision_id
2013
2016
        return xml7.serializer_v7.write_inventory_to_string(inventory)
2014
2017
 
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
2018
    def read_basis_inventory(self):
2045
2019
        """Read the cached basis inventory."""
2046
2020
        path = self._basis_inventory_name()
2909
2883
                    pending.append(dir)
2910
2884
 
2911
2885
 
 
2886
class WorkingTree3(InventoryWorkingTree):
 
2887
    """This is the Format 3 working tree.
 
2888
 
 
2889
    This differs from the base WorkingTree by:
 
2890
     - having its own file lock
 
2891
     - having its own last-revision property.
 
2892
 
 
2893
    This is new in bzr 0.8
 
2894
    """
 
2895
 
 
2896
    @needs_read_lock
 
2897
    def _last_revision(self):
 
2898
        """See Mutable.last_revision."""
 
2899
        try:
 
2900
            return self._transport.get_bytes('last-revision')
 
2901
        except errors.NoSuchFile:
 
2902
            return _mod_revision.NULL_REVISION
 
2903
 
 
2904
    def _change_last_revision(self, revision_id):
 
2905
        """See WorkingTree._change_last_revision."""
 
2906
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
 
2907
            try:
 
2908
                self._transport.delete('last-revision')
 
2909
            except errors.NoSuchFile:
 
2910
                pass
 
2911
            return False
 
2912
        else:
 
2913
            self._transport.put_bytes('last-revision', revision_id,
 
2914
                mode=self.bzrdir._get_file_mode())
 
2915
            return True
 
2916
 
 
2917
    def _get_check_refs(self):
 
2918
        """Return the references needed to perform a check of this tree."""
 
2919
        return [('trees', self.last_revision())]
 
2920
 
 
2921
    @needs_tree_write_lock
 
2922
    def set_conflicts(self, conflicts):
 
2923
        self._put_rio('conflicts', conflicts.to_stanzas(),
 
2924
                      CONFLICT_HEADER_1)
 
2925
 
 
2926
    @needs_tree_write_lock
 
2927
    def add_conflicts(self, new_conflicts):
 
2928
        conflict_set = set(self.conflicts())
 
2929
        conflict_set.update(set(list(new_conflicts)))
 
2930
        self.set_conflicts(_mod_conflicts.ConflictList(sorted(conflict_set,
 
2931
                                       key=_mod_conflicts.Conflict.sort_key)))
 
2932
 
 
2933
    @needs_read_lock
 
2934
    def conflicts(self):
 
2935
        try:
 
2936
            confile = self._transport.get('conflicts')
 
2937
        except errors.NoSuchFile:
 
2938
            return _mod_conflicts.ConflictList()
 
2939
        try:
 
2940
            try:
 
2941
                if confile.next() != CONFLICT_HEADER_1 + '\n':
 
2942
                    raise errors.ConflictFormatError()
 
2943
            except StopIteration:
 
2944
                raise errors.ConflictFormatError()
 
2945
            reader = _mod_rio.RioReader(confile)
 
2946
            return _mod_conflicts.ConflictList.from_stanzas(reader)
 
2947
        finally:
 
2948
            confile.close()
 
2949
 
 
2950
    def unlock(self):
 
2951
        # do non-implementation specific cleanup
 
2952
        self._cleanup()
 
2953
        if self._control_files._lock_count == 1:
 
2954
            # _inventory_is_modified is always False during a read lock.
 
2955
            if self._inventory_is_modified:
 
2956
                self.flush()
 
2957
            self._write_hashcache_if_dirty()
 
2958
        # reverse order of locking.
 
2959
        try:
 
2960
            return self._control_files.unlock()
 
2961
        finally:
 
2962
            self.branch.unlock()
 
2963
 
 
2964
 
2912
2965
class WorkingTreeFormatRegistry(controldir.ControlComponentFormatRegistry):
2913
2966
    """Registry for working tree formats."""
2914
2967
 
3078
3131
        format_registry.remove(format)
3079
3132
 
3080
3133
 
 
3134
class WorkingTreeFormat3(WorkingTreeFormat):
 
3135
    """The second working tree format updated to record a format marker.
 
3136
 
 
3137
    This format:
 
3138
        - exists within a metadir controlling .bzr
 
3139
        - includes an explicit version marker for the workingtree control
 
3140
          files, separate from the BzrDir format
 
3141
        - modifies the hash cache format
 
3142
        - is new in bzr 0.8
 
3143
        - uses a LockDir to guard access for writes.
 
3144
    """
 
3145
 
 
3146
    upgrade_recommended = True
 
3147
 
 
3148
    missing_parent_conflicts = True
 
3149
 
 
3150
    def get_format_string(self):
 
3151
        """See WorkingTreeFormat.get_format_string()."""
 
3152
        return "Bazaar-NG Working Tree format 3"
 
3153
 
 
3154
    def get_format_description(self):
 
3155
        """See WorkingTreeFormat.get_format_description()."""
 
3156
        return "Working tree format 3"
 
3157
 
 
3158
    _lock_file_name = 'lock'
 
3159
    _lock_class = LockDir
 
3160
 
 
3161
    _tree_class = WorkingTree3
 
3162
 
 
3163
    def __get_matchingbzrdir(self):
 
3164
        return bzrdir.BzrDirMetaFormat1()
 
3165
 
 
3166
    _matchingbzrdir = property(__get_matchingbzrdir)
 
3167
 
 
3168
    def _open_control_files(self, a_bzrdir):
 
3169
        transport = a_bzrdir.get_workingtree_transport(None)
 
3170
        return LockableFiles(transport, self._lock_file_name,
 
3171
                             self._lock_class)
 
3172
 
 
3173
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
3174
                   accelerator_tree=None, hardlink=False):
 
3175
        """See WorkingTreeFormat.initialize().
 
3176
 
 
3177
        :param revision_id: if supplied, create a working tree at a different
 
3178
            revision than the branch is at.
 
3179
        :param accelerator_tree: A tree which can be used for retrieving file
 
3180
            contents more quickly than the revision tree, i.e. a workingtree.
 
3181
            The revision tree will be used for cases where accelerator_tree's
 
3182
            content is different.
 
3183
        :param hardlink: If true, hard-link files from accelerator_tree,
 
3184
            where possible.
 
3185
        """
 
3186
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
3187
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
3188
        transport = a_bzrdir.get_workingtree_transport(self)
 
3189
        control_files = self._open_control_files(a_bzrdir)
 
3190
        control_files.create_lock()
 
3191
        control_files.lock_write()
 
3192
        transport.put_bytes('format', self.get_format_string(),
 
3193
            mode=a_bzrdir._get_file_mode())
 
3194
        if from_branch is not None:
 
3195
            branch = from_branch
 
3196
        else:
 
3197
            branch = a_bzrdir.open_branch()
 
3198
        if revision_id is None:
 
3199
            revision_id = _mod_revision.ensure_null(branch.last_revision())
 
3200
        # WorkingTree3 can handle an inventory which has a unique root id.
 
3201
        # as of bzr 0.12. However, bzr 0.11 and earlier fail to handle
 
3202
        # those trees. And because there isn't a format bump inbetween, we
 
3203
        # are maintaining compatibility with older clients.
 
3204
        # inv = Inventory(root_id=gen_root_id())
 
3205
        inv = self._initial_inventory()
 
3206
        wt = self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
 
3207
                         branch,
 
3208
                         inv,
 
3209
                         _internal=True,
 
3210
                         _format=self,
 
3211
                         _bzrdir=a_bzrdir,
 
3212
                         _control_files=control_files)
 
3213
        wt.lock_tree_write()
 
3214
        try:
 
3215
            basis_tree = branch.repository.revision_tree(revision_id)
 
3216
            # only set an explicit root id if there is one to set.
 
3217
            if basis_tree.inventory.root is not None:
 
3218
                wt.set_root_id(basis_tree.get_root_id())
 
3219
            if revision_id == _mod_revision.NULL_REVISION:
 
3220
                wt.set_parent_trees([])
 
3221
            else:
 
3222
                wt.set_parent_trees([(revision_id, basis_tree)])
 
3223
            transform.build_tree(basis_tree, wt)
 
3224
        finally:
 
3225
            # Unlock in this order so that the unlock-triggers-flush in
 
3226
            # WorkingTree is given a chance to fire.
 
3227
            control_files.unlock()
 
3228
            wt.unlock()
 
3229
        return wt
 
3230
 
 
3231
    def _initial_inventory(self):
 
3232
        return inventory.Inventory()
 
3233
 
 
3234
    def __init__(self):
 
3235
        super(WorkingTreeFormat3, self).__init__()
 
3236
 
 
3237
    def open(self, a_bzrdir, _found=False):
 
3238
        """Return the WorkingTree object for a_bzrdir
 
3239
 
 
3240
        _found is a private parameter, do not use it. It is used to indicate
 
3241
               if format probing has already been done.
 
3242
        """
 
3243
        if not _found:
 
3244
            # we are being called directly and must probe.
 
3245
            raise NotImplementedError
 
3246
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
3247
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
3248
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
 
3249
        return wt
 
3250
 
 
3251
    def _open(self, a_bzrdir, control_files):
 
3252
        """Open the tree itself.
 
3253
 
 
3254
        :param a_bzrdir: the dir for the tree.
 
3255
        :param control_files: the control files for the tree.
 
3256
        """
 
3257
        return self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
 
3258
                                _internal=True,
 
3259
                                _format=self,
 
3260
                                _bzrdir=a_bzrdir,
 
3261
                                _control_files=control_files)
 
3262
 
 
3263
    def __str__(self):
 
3264
        return self.get_format_string()
 
3265
 
 
3266
 
3081
3267
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3082
3268
    "bzrlib.workingtree_4", "WorkingTreeFormat4")
3083
3269
format_registry.register_lazy("Bazaar Working Tree Format 5 (bzr 1.11)\n",
3084
3270
    "bzrlib.workingtree_4", "WorkingTreeFormat5")
3085
3271
format_registry.register_lazy("Bazaar Working Tree Format 6 (bzr 1.14)\n",
3086
3272
    "bzrlib.workingtree_4", "WorkingTreeFormat6")
3087
 
format_registry.register_lazy("Bazaar-NG Working Tree format 3",
3088
 
    "bzrlib.workingtree_3", "WorkingTreeFormat3")
 
3273
format_registry.register(WorkingTreeFormat3())
3089
3274
format_registry.set_default_key("Bazaar Working Tree Format 6 (bzr 1.14)\n")