~jelmer/brz/cachedir

« back to all changes in this revision

Viewing changes to breezy/memorytree.py

  • Committer: Jelmer Vernooij
  • Date: 2018-04-02 23:59:32 UTC
  • mfrom: (6060.2.879 work)
  • Revision ID: jelmer@jelmer.uk-20180402235932-9gbg95uo4d0qu6bs
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
See MemoryTree for more details.
20
20
"""
21
21
 
 
22
from __future__ import absolute_import
22
23
 
23
24
import os
24
25
 
25
 
from bzrlib import (
 
26
from . import (
26
27
    errors,
27
 
    mutabletree,
 
28
    lock,
28
29
    revision as _mod_revision,
29
30
    )
30
 
from bzrlib.decorators import needs_read_lock
31
 
from bzrlib.inventory import Inventory
32
 
from bzrlib.osutils import sha_file
33
 
from bzrlib.mutabletree import needs_tree_write_lock
34
 
from bzrlib.transport.memory import MemoryTransport
35
 
 
36
 
 
37
 
class MemoryTree(mutabletree.MutableInventoryTree):
 
31
from .bzr.inventory import Inventory
 
32
from .bzr.inventorytree import MutableInventoryTree
 
33
from .osutils import sha_file
 
34
from .transport.memory import MemoryTransport
 
35
 
 
36
 
 
37
class MemoryTree(MutableInventoryTree):
38
38
    """A MemoryTree is a specialisation of MutableTree.
39
39
 
40
40
    It maintains nearly no state outside of read_lock and write_lock
45
45
    def __init__(self, branch, revision_id):
46
46
        """Construct a MemoryTree for branch using revision_id."""
47
47
        self.branch = branch
48
 
        self.bzrdir = branch.bzrdir
 
48
        self.controldir = branch.controldir
49
49
        self._branch_revision_id = revision_id
50
50
        self._locks = 0
51
51
        self._lock_mode = None
52
52
 
 
53
    def get_config_stack(self):
 
54
        return self.branch.get_config_stack()
 
55
 
53
56
    def is_control_filename(self, filename):
54
57
        # Memory tree doesn't have any control filenames
55
58
        return False
56
59
 
57
 
    @needs_tree_write_lock
58
60
    def _add(self, files, ids, kinds):
59
61
        """See MutableTree._add."""
60
 
        for f, file_id, kind in zip(files, ids, kinds):
61
 
            if kind is None:
62
 
                kind = 'file'
63
 
            if file_id is None:
64
 
                self._inventory.add_path(f, kind=kind)
65
 
            else:
66
 
                self._inventory.add_path(f, kind=kind, file_id=file_id)
 
62
        with self.lock_tree_write():
 
63
            for f, file_id, kind in zip(files, ids, kinds):
 
64
                if kind is None:
 
65
                    kind = 'file'
 
66
                if file_id is None:
 
67
                    self._inventory.add_path(f, kind=kind)
 
68
                else:
 
69
                    self._inventory.add_path(f, kind=kind, file_id=file_id)
67
70
 
68
71
    def basis_tree(self):
69
72
        """See Tree.basis_tree()."""
82
85
        missing files, so is a no-op.
83
86
        """
84
87
 
85
 
    def get_file(self, file_id, path=None):
 
88
    def get_file(self, path, file_id=None):
86
89
        """See Tree.get_file."""
87
 
        if path is None:
88
 
            path = self.id2path(file_id)
89
90
        return self._file_transport.get(path)
90
91
 
91
 
    def get_file_sha1(self, file_id, path=None, stat_value=None):
 
92
    def get_file_sha1(self, path, file_id=None, stat_value=None):
92
93
        """See Tree.get_file_sha1()."""
93
 
        if path is None:
94
 
            path = self.id2path(file_id)
95
94
        stream = self._file_transport.get(path)
96
95
        return sha_file(stream)
97
96
 
104
103
            return None, False, None
105
104
        return entry.kind, entry.executable, None
106
105
 
107
 
    @needs_tree_write_lock
108
106
    def rename_one(self, from_rel, to_rel):
109
 
        file_id = self.path2id(from_rel)
110
 
        to_dir, to_tail = os.path.split(to_rel)
111
 
        to_parent_id = self.path2id(to_dir)
112
 
        self._file_transport.move(from_rel, to_rel)
113
 
        self._inventory.rename(file_id, to_parent_id, to_tail)
 
107
        with self.lock_tree_write():
 
108
            file_id = self.path2id(from_rel)
 
109
            to_dir, to_tail = os.path.split(to_rel)
 
110
            to_parent_id = self.path2id(to_dir)
 
111
            self._file_transport.move(from_rel, to_rel)
 
112
            self._inventory.rename(file_id, to_parent_id, to_tail)
114
113
 
115
114
    def path_content_summary(self, path):
116
115
        """See Tree.path_content_summary."""
117
116
        id = self.path2id(path)
118
117
        if id is None:
119
118
            return 'missing', None, None, None
120
 
        kind = self.kind(id)
 
119
        kind = self.kind(path, id)
121
120
        if kind == 'file':
122
121
            bytes = self._file_transport.get_bytes(path)
123
122
            size = len(bytes)
132
131
        else:
133
132
            raise NotImplementedError('unknown kind')
134
133
 
135
 
    def _file_size(self, entry, stat_value):
136
 
        """See Tree._file_size."""
137
 
        if entry is None:
138
 
            return 0
139
 
        return entry.text_size
140
 
 
141
 
    @needs_read_lock
142
134
    def get_parent_ids(self):
143
135
        """See Tree.get_parent_ids.
144
136
 
145
137
        This implementation returns the current cached value from
146
138
            self._parent_ids.
147
139
        """
148
 
        return list(self._parent_ids)
 
140
        with self.lock_read():
 
141
            return list(self._parent_ids)
149
142
 
150
143
    def has_filename(self, filename):
151
144
        """See Tree.has_filename()."""
152
145
        return self._file_transport.has(filename)
153
146
 
154
 
    def is_executable(self, file_id, path=None):
 
147
    def is_executable(self, path, file_id=None):
155
148
        return self._inventory[file_id].executable
156
149
 
157
 
    def kind(self, file_id):
 
150
    def kind(self, path, file_id=None):
 
151
        if file_id is None:
 
152
            file_id = self.path2id(path)
158
153
        return self._inventory[file_id].kind
159
154
 
160
155
    def mkdir(self, path, file_id=None):
165
160
        self._file_transport.mkdir(path)
166
161
        return file_id
167
162
 
168
 
    @needs_read_lock
169
163
    def last_revision(self):
170
164
        """See MutableTree.last_revision."""
171
 
        return self._branch_revision_id
 
165
        with self.lock_read():
 
166
            return self._branch_revision_id
172
167
 
173
168
    def lock_read(self):
174
169
        """Lock the memory tree for reading.
181
176
                self.branch.lock_read()
182
177
                self._lock_mode = "r"
183
178
                self._populate_from_branch()
 
179
            return lock.LogicalLockResult(self.unlock)
184
180
        except:
185
181
            self._locks -= 1
186
182
            raise
198
194
        except:
199
195
            self._locks -= 1
200
196
            raise
 
197
        return lock.LogicalLockResult(self.unlock)
201
198
 
202
199
    def lock_write(self):
203
200
        """See MutableTree.lock_write()."""
209
206
                self._populate_from_branch()
210
207
            elif self._lock_mode == "r":
211
208
                raise errors.ReadOnlyError(self)
 
209
            return lock.LogicalLockResult(self.unlock)
212
210
        except:
213
211
            self._locks -= 1
214
212
            raise
232
230
                self._file_transport.mkdir(path)
233
231
            elif entry.kind == 'file':
234
232
                self._file_transport.put_file(path,
235
 
                    self._basis_tree.get_file(entry.file_id))
 
233
                    self._basis_tree.get_file(path, entry.file_id))
236
234
            else:
237
235
                raise NotImplementedError(self._populate_from_branch)
238
236
 
239
 
    def put_file_bytes_non_atomic(self, file_id, bytes):
 
237
    def put_file_bytes_non_atomic(self, path, bytes, file_id=None):
240
238
        """See MutableTree.put_file_bytes_non_atomic."""
241
 
        self._file_transport.put_bytes(self.id2path(file_id), bytes)
 
239
        self._file_transport.put_bytes(path, bytes)
242
240
 
243
241
    def unlock(self):
244
242
        """Release a lock.
258
256
        else:
259
257
            self._locks -= 1
260
258
 
261
 
    @needs_tree_write_lock
262
 
    def unversion(self, file_ids):
263
 
        """Remove the file ids in file_ids from the current versioned set.
 
259
    def unversion(self, paths, file_ids=None):
 
260
        """Remove the paths from the current versioned set.
264
261
 
265
262
        When a file_id is unversioned, all of its children are automatically
266
263
        unversioned.
267
264
 
268
 
        :param file_ids: The file ids to stop versioning.
 
265
        :param paths: The paths to stop versioning.
269
266
        :raises: NoSuchId if any fileid is not currently versioned.
270
267
        """
271
 
        # XXX: This should be in mutabletree, but the inventory-save action
272
 
        # is not relevant to memory tree. Until that is done in unlock by
273
 
        # working tree, we cannot share the implementation.
274
 
        for file_id in file_ids:
275
 
            if self._inventory.has_id(file_id):
276
 
                self._inventory.remove_recursive_id(file_id)
277
 
            else:
278
 
                raise errors.NoSuchId(self, file_id)
 
268
        with self.lock_tree_write():
 
269
            # XXX: This should be in mutabletree, but the inventory-save action
 
270
            # is not relevant to memory tree. Until that is done in unlock by
 
271
            # working tree, we cannot share the implementation.
 
272
            if file_ids is None:
 
273
                file_ids = set()
 
274
                for path in paths:
 
275
                    file_id = self.path2id(path)
 
276
                    if file_id is None:
 
277
                        raise errors.NoSuchFile(path)
 
278
                    file_ids.add(file_id)
 
279
            for file_id in file_ids:
 
280
                if self._inventory.has_id(file_id):
 
281
                    self._inventory.remove_recursive_id(file_id)
 
282
                else:
 
283
                    raise errors.NoSuchId(self, file_id)
279
284
 
280
285
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
281
286
        """See MutableTree.set_parent_trees()."""
289
294
            self._branch_revision_id = revision_ids[0]
290
295
        self._allow_leftmost_as_ghost = allow_leftmost_as_ghost
291
296
        self._set_basis()
292
 
    
 
297
 
293
298
    def _set_basis(self):
294
299
        try:
295
300
            self._basis_tree = self.branch.repository.revision_tree(