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