~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Jelmer Vernooij
  • Date: 2011-05-03 23:16:56 UTC
  • mto: This revision was merged to the branch mainline in revision 5819.
  • Revision ID: jelmer@samba.org-20110503231656-4sxm717yejm8cpuw
Add tariff test to make sure working tree isn't opened by 'bzr serve'
that simply accesses a branch.

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,
750
753
        self._set_merges_from_parent_ids(revision_ids)
751
754
 
752
755
    @needs_tree_write_lock
 
756
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
 
757
        """See MutableTree.set_parent_trees."""
 
758
        parent_ids = [rev for (rev, tree) in parents_list]
 
759
        for revision_id in parent_ids:
 
760
            _mod_revision.check_not_reserved_id(revision_id)
 
761
 
 
762
        self._check_parents_for_ghosts(parent_ids,
 
763
            allow_leftmost_as_ghost=allow_leftmost_as_ghost)
 
764
 
 
765
        parent_ids = self._filter_parent_ids_by_ancestry(parent_ids)
 
766
 
 
767
        if len(parent_ids) == 0:
 
768
            leftmost_parent_id = _mod_revision.NULL_REVISION
 
769
            leftmost_parent_tree = None
 
770
        else:
 
771
            leftmost_parent_id, leftmost_parent_tree = parents_list[0]
 
772
 
 
773
        if self._change_last_revision(leftmost_parent_id):
 
774
            if leftmost_parent_tree is None:
 
775
                # If we don't have a tree, fall back to reading the
 
776
                # parent tree from the repository.
 
777
                self._cache_basis_inventory(leftmost_parent_id)
 
778
            else:
 
779
                inv = leftmost_parent_tree.inventory
 
780
                xml = self._create_basis_xml_from_inventory(
 
781
                                        leftmost_parent_id, inv)
 
782
                self._write_basis_inventory(xml)
 
783
        self._set_merges_from_parent_ids(parent_ids)
 
784
 
 
785
    @needs_tree_write_lock
753
786
    def set_pending_merges(self, rev_list):
754
787
        parents = self.get_parent_ids()
755
788
        leftmost = parents[:1]
1947
1980
        """See Tree.iter_all_file_ids"""
1948
1981
        return set(self.inventory)
1949
1982
 
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
1983
    def _cache_basis_inventory(self, new_revision):
1981
1984
        """Cache new_revision as the basis inventory."""
1982
1985
        # TODO: this should allow the ready-to-use inventory to be passed in,
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
 
2925
2978
        return self._default_format
2926
2979
 
2927
2980
    def set_default(self, format):
2928
 
        """Set the default format."""
2929
2981
        self._default_format = format
2930
2982
        self._default_format_key = None
2931
2983
 
2932
2984
    def set_default_key(self, format_string):
2933
 
        """Set the default format by its format string."""
2934
2985
        self._default_format_key = format_string
2935
2986
        self._default_format = None
2936
2987
 
3078
3129
        format_registry.remove(format)
3079
3130
 
3080
3131
 
 
3132
class WorkingTreeFormat3(WorkingTreeFormat):
 
3133
    """The second working tree format updated to record a format marker.
 
3134
 
 
3135
    This format:
 
3136
        - exists within a metadir controlling .bzr
 
3137
        - includes an explicit version marker for the workingtree control
 
3138
          files, separate from the BzrDir format
 
3139
        - modifies the hash cache format
 
3140
        - is new in bzr 0.8
 
3141
        - uses a LockDir to guard access for writes.
 
3142
    """
 
3143
 
 
3144
    upgrade_recommended = True
 
3145
 
 
3146
    missing_parent_conflicts = True
 
3147
 
 
3148
    def get_format_string(self):
 
3149
        """See WorkingTreeFormat.get_format_string()."""
 
3150
        return "Bazaar-NG Working Tree format 3"
 
3151
 
 
3152
    def get_format_description(self):
 
3153
        """See WorkingTreeFormat.get_format_description()."""
 
3154
        return "Working tree format 3"
 
3155
 
 
3156
    _lock_file_name = 'lock'
 
3157
    _lock_class = LockDir
 
3158
 
 
3159
    _tree_class = WorkingTree3
 
3160
 
 
3161
    def __get_matchingbzrdir(self):
 
3162
        return bzrdir.BzrDirMetaFormat1()
 
3163
 
 
3164
    _matchingbzrdir = property(__get_matchingbzrdir)
 
3165
 
 
3166
    def _open_control_files(self, a_bzrdir):
 
3167
        transport = a_bzrdir.get_workingtree_transport(None)
 
3168
        return LockableFiles(transport, self._lock_file_name,
 
3169
                             self._lock_class)
 
3170
 
 
3171
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
3172
                   accelerator_tree=None, hardlink=False):
 
3173
        """See WorkingTreeFormat.initialize().
 
3174
 
 
3175
        :param revision_id: if supplied, create a working tree at a different
 
3176
            revision than the branch is at.
 
3177
        :param accelerator_tree: A tree which can be used for retrieving file
 
3178
            contents more quickly than the revision tree, i.e. a workingtree.
 
3179
            The revision tree will be used for cases where accelerator_tree's
 
3180
            content is different.
 
3181
        :param hardlink: If true, hard-link files from accelerator_tree,
 
3182
            where possible.
 
3183
        """
 
3184
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
3185
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
3186
        transport = a_bzrdir.get_workingtree_transport(self)
 
3187
        control_files = self._open_control_files(a_bzrdir)
 
3188
        control_files.create_lock()
 
3189
        control_files.lock_write()
 
3190
        transport.put_bytes('format', self.get_format_string(),
 
3191
            mode=a_bzrdir._get_file_mode())
 
3192
        if from_branch is not None:
 
3193
            branch = from_branch
 
3194
        else:
 
3195
            branch = a_bzrdir.open_branch()
 
3196
        if revision_id is None:
 
3197
            revision_id = _mod_revision.ensure_null(branch.last_revision())
 
3198
        # WorkingTree3 can handle an inventory which has a unique root id.
 
3199
        # as of bzr 0.12. However, bzr 0.11 and earlier fail to handle
 
3200
        # those trees. And because there isn't a format bump inbetween, we
 
3201
        # are maintaining compatibility with older clients.
 
3202
        # inv = Inventory(root_id=gen_root_id())
 
3203
        inv = self._initial_inventory()
 
3204
        wt = self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
 
3205
                         branch,
 
3206
                         inv,
 
3207
                         _internal=True,
 
3208
                         _format=self,
 
3209
                         _bzrdir=a_bzrdir,
 
3210
                         _control_files=control_files)
 
3211
        wt.lock_tree_write()
 
3212
        try:
 
3213
            basis_tree = branch.repository.revision_tree(revision_id)
 
3214
            # only set an explicit root id if there is one to set.
 
3215
            if basis_tree.inventory.root is not None:
 
3216
                wt.set_root_id(basis_tree.get_root_id())
 
3217
            if revision_id == _mod_revision.NULL_REVISION:
 
3218
                wt.set_parent_trees([])
 
3219
            else:
 
3220
                wt.set_parent_trees([(revision_id, basis_tree)])
 
3221
            transform.build_tree(basis_tree, wt)
 
3222
        finally:
 
3223
            # Unlock in this order so that the unlock-triggers-flush in
 
3224
            # WorkingTree is given a chance to fire.
 
3225
            control_files.unlock()
 
3226
            wt.unlock()
 
3227
        return wt
 
3228
 
 
3229
    def _initial_inventory(self):
 
3230
        return inventory.Inventory()
 
3231
 
 
3232
    def __init__(self):
 
3233
        super(WorkingTreeFormat3, self).__init__()
 
3234
 
 
3235
    def open(self, a_bzrdir, _found=False):
 
3236
        """Return the WorkingTree object for a_bzrdir
 
3237
 
 
3238
        _found is a private parameter, do not use it. It is used to indicate
 
3239
               if format probing has already been done.
 
3240
        """
 
3241
        if not _found:
 
3242
            # we are being called directly and must probe.
 
3243
            raise NotImplementedError
 
3244
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
3245
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
3246
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
 
3247
        return wt
 
3248
 
 
3249
    def _open(self, a_bzrdir, control_files):
 
3250
        """Open the tree itself.
 
3251
 
 
3252
        :param a_bzrdir: the dir for the tree.
 
3253
        :param control_files: the control files for the tree.
 
3254
        """
 
3255
        return self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
 
3256
                                _internal=True,
 
3257
                                _format=self,
 
3258
                                _bzrdir=a_bzrdir,
 
3259
                                _control_files=control_files)
 
3260
 
 
3261
    def __str__(self):
 
3262
        return self.get_format_string()
 
3263
 
 
3264
 
3081
3265
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3082
3266
    "bzrlib.workingtree_4", "WorkingTreeFormat4")
3083
3267
format_registry.register_lazy("Bazaar Working Tree Format 5 (bzr 1.11)\n",
3084
3268
    "bzrlib.workingtree_4", "WorkingTreeFormat5")
3085
3269
format_registry.register_lazy("Bazaar Working Tree Format 6 (bzr 1.14)\n",
3086
3270
    "bzrlib.workingtree_4", "WorkingTreeFormat6")
3087
 
format_registry.register_lazy("Bazaar-NG Working Tree format 3",
3088
 
    "bzrlib.workingtree_3", "WorkingTreeFormat3")
 
3271
format_registry.register(WorkingTreeFormat3())
3089
3272
format_registry.set_default_key("Bazaar Working Tree Format 6 (bzr 1.14)\n")