/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,
40
    WorkingTreeFormat,
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
139
class WorkingTreeFormat3(WorkingTreeFormat):
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
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
157
    def get_format_string(self):
158
        """See WorkingTreeFormat.get_format_string()."""
159
        return "Bazaar-NG Working Tree format 3"
160
161
    def get_format_description(self):
162
        """See WorkingTreeFormat.get_format_description()."""
163
        return "Working tree format 3"
164
165
    _tree_class = WorkingTree3
166
167
    def __get_matchingbzrdir(self):
168
        return bzrdir.BzrDirMetaFormat1()
169
170
    _matchingbzrdir = property(__get_matchingbzrdir)
171
172
    def _open_control_files(self, a_bzrdir):
173
        transport = a_bzrdir.get_workingtree_transport(None)
174
        return LockableFiles(transport, 'lock', LockDir)
175
176
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
177
                   accelerator_tree=None, hardlink=False):
178
        """See WorkingTreeFormat.initialize().
179
180
        :param revision_id: if supplied, create a working tree at a different
181
            revision than the branch is at.
182
        :param accelerator_tree: A tree which can be used for retrieving file
183
            contents more quickly than the revision tree, i.e. a workingtree.
184
            The revision tree will be used for cases where accelerator_tree's
185
            content is different.
186
        :param hardlink: If true, hard-link files from accelerator_tree,
187
            where possible.
188
        """
189
        if not isinstance(a_bzrdir.transport, LocalTransport):
190
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
191
        transport = a_bzrdir.get_workingtree_transport(self)
192
        control_files = self._open_control_files(a_bzrdir)
193
        control_files.create_lock()
194
        control_files.lock_write()
195
        transport.put_bytes('format', self.get_format_string(),
196
            mode=a_bzrdir._get_file_mode())
197
        if from_branch is not None:
198
            branch = from_branch
199
        else:
200
            branch = a_bzrdir.open_branch()
201
        if revision_id is None:
202
            revision_id = _mod_revision.ensure_null(branch.last_revision())
203
        # WorkingTree3 can handle an inventory which has a unique root id.
204
        # as of bzr 0.12. However, bzr 0.11 and earlier fail to handle
205
        # those trees. And because there isn't a format bump inbetween, we
206
        # are maintaining compatibility with older clients.
207
        # inv = Inventory(root_id=gen_root_id())
208
        inv = self._initial_inventory()
209
        wt = self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
6313.1.4 by Jelmer Vernooij
Fix tests.
210
                         branch,
5816.5.1 by Jelmer Vernooij
Move WorkingTree3 to bzrlib.workingtree_3.
211
                         inv,
212
                         _internal=True,
213
                         _format=self,
214
                         _bzrdir=a_bzrdir,
215
                         _control_files=control_files)
216
        wt.lock_tree_write()
217
        try:
218
            basis_tree = branch.repository.revision_tree(revision_id)
219
            # only set an explicit root id if there is one to set.
220
            if basis_tree.inventory.root is not None:
221
                wt.set_root_id(basis_tree.get_root_id())
222
            if revision_id == _mod_revision.NULL_REVISION:
223
                wt.set_parent_trees([])
224
            else:
225
                wt.set_parent_trees([(revision_id, basis_tree)])
226
            transform.build_tree(basis_tree, wt)
227
        finally:
228
            # Unlock in this order so that the unlock-triggers-flush in
229
            # WorkingTree is given a chance to fire.
230
            control_files.unlock()
231
            wt.unlock()
232
        return wt
233
234
    def _initial_inventory(self):
235
        return inventory.Inventory()
236
237
    def open(self, a_bzrdir, _found=False):
238
        """Return the WorkingTree object for a_bzrdir
239
240
        _found is a private parameter, do not use it. It is used to indicate
241
               if format probing has already been done.
242
        """
243
        if not _found:
244
            # we are being called directly and must probe.
245
            raise NotImplementedError
246
        if not isinstance(a_bzrdir.transport, LocalTransport):
247
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
248
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
249
        return wt
250
251
    def _open(self, a_bzrdir, control_files):
252
        """Open the tree itself.
253
254
        :param a_bzrdir: the dir for the tree.
255
        :param control_files: the control files for the tree.
256
        """
257
        return self._tree_class(a_bzrdir.root_transport.local_abspath('.'),
258
                                _internal=True,
259
                                _format=self,
260
                                _bzrdir=a_bzrdir,
261
                                _control_files=control_files)
262
263
    def __str__(self):
264
        return self.get_format_string()