~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree_3.py

Turn completion assertions into separate methods.

Many common assertions used to be expressed as arguments to the complete
method.  This makes the checks more explicit, and the code easier to read.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2011 Canonical Ltd
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
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
16
 
 
17
 
"""WorkingTree3 format and implementation.
18
 
 
19
 
"""
20
 
 
21
 
from bzrlib import (
22
 
    bzrdir,
23
 
    errors,
24
 
    inventory,
25
 
    revision as _mod_revision,
26
 
    transform,
27
 
    )
28
 
from bzrlib.decorators import (
29
 
    needs_read_lock,
30
 
    )
31
 
from bzrlib.lockable_files import LockableFiles
32
 
from bzrlib.lockdir import LockDir
33
 
from bzrlib.transport.local import LocalTransport
34
 
from bzrlib.workingtree import (
35
 
    InventoryWorkingTree,
36
 
    WorkingTreeFormat,
37
 
    )
38
 
 
39
 
class WorkingTree3(InventoryWorkingTree):
40
 
    """This is the Format 3 working tree.
41
 
 
42
 
    This differs from the base WorkingTree by:
43
 
     - having its own file lock
44
 
     - having its own last-revision property.
45
 
 
46
 
    This is new in bzr 0.8
47
 
    """
48
 
 
49
 
    @needs_read_lock
50
 
    def _last_revision(self):
51
 
        """See Mutable.last_revision."""
52
 
        try:
53
 
            return self._transport.get_bytes('last-revision')
54
 
        except errors.NoSuchFile:
55
 
            return _mod_revision.NULL_REVISION
56
 
 
57
 
    def _change_last_revision(self, revision_id):
58
 
        """See WorkingTree._change_last_revision."""
59
 
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
60
 
            try:
61
 
                self._transport.delete('last-revision')
62
 
            except errors.NoSuchFile:
63
 
                pass
64
 
            return False
65
 
        else:
66
 
            self._transport.put_bytes('last-revision', revision_id,
67
 
                mode=self.bzrdir._get_file_mode())
68
 
            return True
69
 
 
70
 
    def _get_check_refs(self):
71
 
        """Return the references needed to perform a check of this tree."""
72
 
        return [('trees', self.last_revision())]
73
 
 
74
 
    def unlock(self):
75
 
        if self._control_files._lock_count == 1:
76
 
           # do non-implementation specific cleanup
77
 
            self._cleanup()
78
 
            # _inventory_is_modified is always False during a read lock.
79
 
            if self._inventory_is_modified:
80
 
                self.flush()
81
 
            self._write_hashcache_if_dirty()
82
 
        # reverse order of locking.
83
 
        try:
84
 
            return self._control_files.unlock()
85
 
        finally:
86
 
            self.branch.unlock()
87
 
 
88
 
 
89
 
class WorkingTreeFormat3(WorkingTreeFormat):
90
 
    """The second working tree format updated to record a format marker.
91
 
 
92
 
    This format:
93
 
        - exists within a metadir controlling .bzr
94
 
        - includes an explicit version marker for the workingtree control
95
 
          files, separate from the BzrDir format
96
 
        - modifies the hash cache format
97
 
        - is new in bzr 0.8
98
 
        - uses a LockDir to guard access for writes.
99
 
    """
100
 
 
101
 
    upgrade_recommended = True
102
 
 
103
 
    missing_parent_conflicts = True
104
 
 
105
 
    supports_versioned_directories = True
106
 
 
107
 
    def get_format_string(self):
108
 
        """See WorkingTreeFormat.get_format_string()."""
109
 
        return "Bazaar-NG Working Tree format 3"
110
 
 
111
 
    def get_format_description(self):
112
 
        """See WorkingTreeFormat.get_format_description()."""
113
 
        return "Working tree format 3"
114
 
 
115
 
    _tree_class = WorkingTree3
116
 
 
117
 
    def __get_matchingbzrdir(self):
118
 
        return bzrdir.BzrDirMetaFormat1()
119
 
 
120
 
    _matchingbzrdir = property(__get_matchingbzrdir)
121
 
 
122
 
    def _open_control_files(self, a_bzrdir):
123
 
        transport = a_bzrdir.get_workingtree_transport(None)
124
 
        return LockableFiles(transport, 'lock', LockDir)
125
 
 
126
 
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
127
 
                   accelerator_tree=None, hardlink=False):
128
 
        """See WorkingTreeFormat.initialize().
129
 
 
130
 
        :param revision_id: if supplied, create a working tree at a different
131
 
            revision than the branch is at.
132
 
        :param accelerator_tree: A tree which can be used for retrieving file
133
 
            contents more quickly than the revision tree, i.e. a workingtree.
134
 
            The revision tree will be used for cases where accelerator_tree's
135
 
            content is different.
136
 
        :param hardlink: If true, hard-link files from accelerator_tree,
137
 
            where possible.
138
 
        """
139
 
        if not isinstance(a_bzrdir.transport, LocalTransport):
140
 
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
141
 
        transport = a_bzrdir.get_workingtree_transport(self)
142
 
        control_files = self._open_control_files(a_bzrdir)
143
 
        control_files.create_lock()
144
 
        control_files.lock_write()
145
 
        transport.put_bytes('format', self.get_format_string(),
146
 
            mode=a_bzrdir._get_file_mode())
147
 
        if from_branch is not None:
148
 
            branch = from_branch
149
 
        else:
150
 
            branch = a_bzrdir.open_branch()
151
 
        if revision_id is None:
152
 
            revision_id = _mod_revision.ensure_null(branch.last_revision())
153
 
        # WorkingTree3 can handle an inventory which has a unique root id.
154
 
        # as of bzr 0.12. However, bzr 0.11 and earlier fail to handle
155
 
        # those trees. And because there isn't a format bump inbetween, we
156
 
        # are maintaining compatibility with older clients.
157
 
        # inv = Inventory(root_id=gen_root_id())
158
 
        inv = self._initial_inventory()
159
 
        wt = self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
160
 
                         branch,
161
 
                         inv,
162
 
                         _internal=True,
163
 
                         _format=self,
164
 
                         _bzrdir=a_bzrdir,
165
 
                         _control_files=control_files)
166
 
        wt.lock_tree_write()
167
 
        try:
168
 
            basis_tree = branch.repository.revision_tree(revision_id)
169
 
            # only set an explicit root id if there is one to set.
170
 
            if basis_tree.inventory.root is not None:
171
 
                wt.set_root_id(basis_tree.get_root_id())
172
 
            if revision_id == _mod_revision.NULL_REVISION:
173
 
                wt.set_parent_trees([])
174
 
            else:
175
 
                wt.set_parent_trees([(revision_id, basis_tree)])
176
 
            transform.build_tree(basis_tree, wt)
177
 
        finally:
178
 
            # Unlock in this order so that the unlock-triggers-flush in
179
 
            # WorkingTree is given a chance to fire.
180
 
            control_files.unlock()
181
 
            wt.unlock()
182
 
        return wt
183
 
 
184
 
    def _initial_inventory(self):
185
 
        return inventory.Inventory()
186
 
 
187
 
    def open(self, a_bzrdir, _found=False):
188
 
        """Return the WorkingTree object for a_bzrdir
189
 
 
190
 
        _found is a private parameter, do not use it. It is used to indicate
191
 
               if format probing has already been done.
192
 
        """
193
 
        if not _found:
194
 
            # we are being called directly and must probe.
195
 
            raise NotImplementedError
196
 
        if not isinstance(a_bzrdir.transport, LocalTransport):
197
 
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
198
 
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
199
 
        return wt
200
 
 
201
 
    def _open(self, a_bzrdir, control_files):
202
 
        """Open the tree itself.
203
 
 
204
 
        :param a_bzrdir: the dir for the tree.
205
 
        :param control_files: the control files for the tree.
206
 
        """
207
 
        return self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
208
 
                                _internal=True,
209
 
                                _format=self,
210
 
                                _bzrdir=a_bzrdir,
211
 
                                _control_files=control_files)
212
 
 
213
 
    def __str__(self):
214
 
        return self.get_format_string()