/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
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
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
21
from __future__ import absolute_import
22
6110.4.2 by Jelmer Vernooij
Move hashcache use to bzrlib.workingtree_3 and bzrlib.plugins.weave_fmt.workingtree.
23
import errno
24
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
25
from bzrlib import (
26
    bzrdir,
27
    errors,
6110.4.2 by Jelmer Vernooij
Move hashcache use to bzrlib.workingtree_3 and bzrlib.plugins.weave_fmt.workingtree.
28
    hashcache,
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
29
    inventory,
30
    revision as _mod_revision,
6110.4.2 by Jelmer Vernooij
Move hashcache use to bzrlib.workingtree_3 and bzrlib.plugins.weave_fmt.workingtree.
31
    trace,
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
32
    transform,
33
    )
34
from bzrlib.decorators import (
35
    needs_read_lock,
36
    )
37
from bzrlib.lockable_files import LockableFiles
38
from bzrlib.lockdir import LockDir
39
from bzrlib.transport.local import LocalTransport
40
from bzrlib.workingtree import (
41
    InventoryWorkingTree,
6213.1.9 by Jelmer Vernooij
Add metadir working tree format with feature support.
42
    WorkingTreeFormatMetaDir,
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
43
    )
44
6110.4.4 by Jelmer Vernooij
Add common base class.
45
46
class PreDirStateWorkingTree(InventoryWorkingTree):
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
47
6110.4.2 by Jelmer Vernooij
Move hashcache use to bzrlib.workingtree_3 and bzrlib.plugins.weave_fmt.workingtree.
48
    def __init__(self, basedir='.', *args, **kwargs):
6110.4.4 by Jelmer Vernooij
Add common base class.
49
        super(PreDirStateWorkingTree, self).__init__(basedir, *args, **kwargs)
6110.4.2 by Jelmer Vernooij
Move hashcache use to bzrlib.workingtree_3 and bzrlib.plugins.weave_fmt.workingtree.
50
        # update the whole cache up front and write to disk if anything changed;
51
        # in the future we might want to do this more selectively
52
        # two possible ways offer themselves : in self._unlock, write the cache
53
        # if needed, or, when the cache sees a change, append it to the hash
54
        # cache file, and have the parser take the most recent entry for a
55
        # given path only.
56
        wt_trans = self.bzrdir.get_workingtree_transport(None)
57
        cache_filename = wt_trans.local_abspath('stat-cache')
58
        self._hashcache = hashcache.HashCache(basedir, cache_filename,
59
            self.bzrdir._get_file_mode(),
60
            self._content_filter_stack_provider())
61
        hc = self._hashcache
62
        hc.read()
63
        # is this scan needed ? it makes things kinda slow.
64
        #hc.scan()
65
66
        if hc.needs_write:
67
            trace.mutter("write hc")
68
            hc.write()
69
6110.4.4 by Jelmer Vernooij
Add common base class.
70
    def _write_hashcache_if_dirty(self):
71
        """Write out the hashcache if it is dirty."""
72
        if self._hashcache.needs_write:
73
            try:
74
                self._hashcache.write()
75
            except OSError, e:
76
                if e.errno not in (errno.EPERM, errno.EACCES):
77
                    raise
78
                # TODO: jam 20061219 Should this be a warning? A single line
79
                #       warning might be sufficient to let the user know what
80
                #       is going on.
81
                trace.mutter('Could not write hashcache for %s\nError: %s',
82
                              self._hashcache.cache_file_name(), e)
83
84
    @needs_read_lock
85
    def get_file_sha1(self, file_id, path=None, stat_value=None):
86
        if not path:
87
            path = self._inventory.id2path(file_id)
88
        return self._hashcache.get_sha1(path, stat_value)
89
90
91
class WorkingTree3(PreDirStateWorkingTree):
92
    """This is the Format 3 working tree.
93
94
    This differs from the base WorkingTree by:
95
     - having its own file lock
96
     - having its own last-revision property.
97
98
    This is new in bzr 0.8
99
    """
100
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
101
    @needs_read_lock
102
    def _last_revision(self):
103
        """See Mutable.last_revision."""
104
        try:
105
            return self._transport.get_bytes('last-revision')
106
        except errors.NoSuchFile:
107
            return _mod_revision.NULL_REVISION
108
109
    def _change_last_revision(self, revision_id):
110
        """See WorkingTree._change_last_revision."""
111
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
112
            try:
113
                self._transport.delete('last-revision')
114
            except errors.NoSuchFile:
115
                pass
116
            return False
117
        else:
118
            self._transport.put_bytes('last-revision', revision_id,
119
                mode=self.bzrdir._get_file_mode())
120
            return True
121
122
    def _get_check_refs(self):
123
        """Return the references needed to perform a check of this tree."""
124
        return [('trees', self.last_revision())]
125
126
    def unlock(self):
127
        if self._control_files._lock_count == 1:
5900.1.1 by Jelmer Vernooij
Make sure only the last unlock resets the cached ignore glob.
128
           # do non-implementation specific cleanup
129
            self._cleanup()
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
130
            # _inventory_is_modified is always False during a read lock.
131
            if self._inventory_is_modified:
132
                self.flush()
133
            self._write_hashcache_if_dirty()
134
        # reverse order of locking.
135
        try:
136
            return self._control_files.unlock()
137
        finally:
138
            self.branch.unlock()
139
140
6213.1.9 by Jelmer Vernooij
Add metadir working tree format with feature support.
141
class WorkingTreeFormat3(WorkingTreeFormatMetaDir):
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
142
    """The second working tree format updated to record a format marker.
143
144
    This format:
145
        - exists within a metadir controlling .bzr
146
        - includes an explicit version marker for the workingtree control
6207.3.3 by jelmer at samba
Fix tests and the like.
147
          files, separate from the ControlDir format
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
148
        - modifies the hash cache format
149
        - is new in bzr 0.8
150
        - uses a LockDir to guard access for writes.
151
    """
152
153
    upgrade_recommended = True
154
155
    missing_parent_conflicts = True
156
5993.3.1 by Jelmer Vernooij
Add WorkingTreeFormat.supports_versioned_directories attribute.
157
    supports_versioned_directories = True
158
6213.1.24 by Jelmer Vernooij
More refactoring.
159
    @classmethod
160
    def get_format_string(cls):
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
161
        """See WorkingTreeFormat.get_format_string()."""
162
        return "Bazaar-NG Working Tree format 3"
163
164
    def get_format_description(self):
165
        """See WorkingTreeFormat.get_format_description()."""
166
        return "Working tree format 3"
167
168
    _tree_class = WorkingTree3
169
170
    def __get_matchingbzrdir(self):
171
        return bzrdir.BzrDirMetaFormat1()
172
173
    _matchingbzrdir = property(__get_matchingbzrdir)
174
175
    def _open_control_files(self, a_bzrdir):
176
        transport = a_bzrdir.get_workingtree_transport(None)
177
        return LockableFiles(transport, 'lock', LockDir)
178
179
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
180
                   accelerator_tree=None, hardlink=False):
181
        """See WorkingTreeFormat.initialize().
182
183
        :param revision_id: if supplied, create a working tree at a different
184
            revision than the branch is at.
185
        :param accelerator_tree: A tree which can be used for retrieving file
186
            contents more quickly than the revision tree, i.e. a workingtree.
187
            The revision tree will be used for cases where accelerator_tree's
188
            content is different.
189
        :param hardlink: If true, hard-link files from accelerator_tree,
190
            where possible.
191
        """
192
        if not isinstance(a_bzrdir.transport, LocalTransport):
193
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
194
        transport = a_bzrdir.get_workingtree_transport(self)
195
        control_files = self._open_control_files(a_bzrdir)
196
        control_files.create_lock()
197
        control_files.lock_write()
6213.1.24 by Jelmer Vernooij
More refactoring.
198
        transport.put_bytes('format', self.as_string(),
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
199
            mode=a_bzrdir._get_file_mode())
200
        if from_branch is not None:
201
            branch = from_branch
202
        else:
203
            branch = a_bzrdir.open_branch()
204
        if revision_id is None:
205
            revision_id = _mod_revision.ensure_null(branch.last_revision())
206
        # WorkingTree3 can handle an inventory which has a unique root id.
207
        # as of bzr 0.12. However, bzr 0.11 and earlier fail to handle
208
        # those trees. And because there isn't a format bump inbetween, we
209
        # are maintaining compatibility with older clients.
210
        # inv = Inventory(root_id=gen_root_id())
211
        inv = self._initial_inventory()
212
        wt = self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
6313.1.4 by Jelmer Vernooij
Fix tests.
213
                         branch,
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
214
                         inv,
215
                         _internal=True,
216
                         _format=self,
217
                         _bzrdir=a_bzrdir,
218
                         _control_files=control_files)
219
        wt.lock_tree_write()
220
        try:
221
            basis_tree = branch.repository.revision_tree(revision_id)
222
            # only set an explicit root id if there is one to set.
223
            if basis_tree.inventory.root is not None:
224
                wt.set_root_id(basis_tree.get_root_id())
225
            if revision_id == _mod_revision.NULL_REVISION:
226
                wt.set_parent_trees([])
227
            else:
228
                wt.set_parent_trees([(revision_id, basis_tree)])
229
            transform.build_tree(basis_tree, wt)
230
        finally:
231
            # Unlock in this order so that the unlock-triggers-flush in
232
            # WorkingTree is given a chance to fire.
233
            control_files.unlock()
234
            wt.unlock()
235
        return wt
236
237
    def _initial_inventory(self):
238
        return inventory.Inventory()
239
240
    def open(self, a_bzrdir, _found=False):
241
        """Return the WorkingTree object for a_bzrdir
242
243
        _found is a private parameter, do not use it. It is used to indicate
244
               if format probing has already been done.
245
        """
246
        if not _found:
247
            # we are being called directly and must probe.
248
            raise NotImplementedError
249
        if not isinstance(a_bzrdir.transport, LocalTransport):
250
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
251
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
252
        return wt
253
254
    def _open(self, a_bzrdir, control_files):
255
        """Open the tree itself.
256
257
        :param a_bzrdir: the dir for the tree.
258
        :param control_files: the control files for the tree.
259
        """
260
        return self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
261
                                _internal=True,
262
                                _format=self,
263
                                _bzrdir=a_bzrdir,
264
                                _control_files=control_files)