~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/memorytree.py

  • Committer: Robert Collins
  • Date: 2010-05-06 23:49:39 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506234939-prhk3x301ag1y1ai
Document the API break.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""MemoryTree object.
18
18
 
20
20
"""
21
21
 
22
22
 
23
 
from copy import deepcopy
 
23
import os
24
24
 
25
 
from bzrlib import errors, mutabletree
26
 
from bzrlib.decorators import needs_read_lock, needs_write_lock
 
25
from bzrlib import (
 
26
    errors,
 
27
    mutabletree,
 
28
    revision as _mod_revision,
 
29
    )
 
30
from bzrlib.decorators import needs_read_lock
27
31
from bzrlib.osutils import sha_file
28
32
from bzrlib.mutabletree import needs_tree_write_lock
29
33
from bzrlib.transport.memory import MemoryTransport
31
35
 
32
36
class MemoryTree(mutabletree.MutableTree):
33
37
    """A MemoryTree is a specialisation of MutableTree.
34
 
    
 
38
 
35
39
    It maintains nearly no state outside of read_lock and write_lock
36
40
    transactions. (it keeps a reference to the branch, and its last-revision
37
41
    only).
63
67
    @staticmethod
64
68
    def create_on_branch(branch):
65
69
        """Create a MemoryTree for branch, using the last-revision of branch."""
66
 
        return MemoryTree(branch, branch.last_revision())
 
70
        revision_id = _mod_revision.ensure_null(branch.last_revision())
 
71
        return MemoryTree(branch, revision_id)
67
72
 
68
73
    def _gather_kinds(self, files, kinds):
69
74
        """See MutableTree._gather_kinds.
70
 
        
 
75
 
71
76
        This implementation does not care about the file kind of
72
77
        missing files, so is a no-op.
73
78
        """
74
79
 
75
 
    def get_file(self, file_id):
 
80
    def get_file(self, file_id, path=None):
76
81
        """See Tree.get_file."""
77
 
        return self._file_transport.get(self.id2path(file_id))
 
82
        if path is None:
 
83
            path = self.id2path(file_id)
 
84
        return self._file_transport.get(path)
78
85
 
79
 
    def get_file_sha1(self, file_id, path=None):
 
86
    def get_file_sha1(self, file_id, path=None, stat_value=None):
80
87
        """See Tree.get_file_sha1()."""
81
88
        if path is None:
82
89
            path = self.id2path(file_id)
83
90
        stream = self._file_transport.get(path)
84
91
        return sha_file(stream)
85
92
 
 
93
    def get_root_id(self):
 
94
        return self.path2id('')
 
95
 
 
96
    def _comparison_data(self, entry, path):
 
97
        """See Tree._comparison_data."""
 
98
        if entry is None:
 
99
            return None, False, None
 
100
        return entry.kind, entry.executable, None
 
101
 
 
102
    @needs_tree_write_lock
 
103
    def rename_one(self, from_rel, to_rel):
 
104
        file_id = self.path2id(from_rel)
 
105
        to_dir, to_tail = os.path.split(to_rel)
 
106
        to_parent_id = self.path2id(to_dir)
 
107
        self._file_transport.move(from_rel, to_rel)
 
108
        self._inventory.rename(file_id, to_parent_id, to_tail)
 
109
 
 
110
    def path_content_summary(self, path):
 
111
        """See Tree.path_content_summary."""
 
112
        id = self.path2id(path)
 
113
        if id is None:
 
114
            return 'missing', None, None, None
 
115
        kind = self.kind(id)
 
116
        if kind == 'file':
 
117
            bytes = self._file_transport.get_bytes(path)
 
118
            size = len(bytes)
 
119
            executable = self._inventory[id].executable
 
120
            sha1 = None # no stat cache
 
121
            return (kind, size, executable, sha1)
 
122
        elif kind == 'directory':
 
123
            # memory tree does not support nested trees yet.
 
124
            return kind, None, None, None
 
125
        elif kind == 'symlink':
 
126
            raise NotImplementedError('symlink support')
 
127
        else:
 
128
            raise NotImplementedError('unknown kind')
 
129
 
 
130
    def _file_size(self, entry, stat_value):
 
131
        """See Tree._file_size."""
 
132
        if entry is None:
 
133
            return 0
 
134
        return entry.text_size
 
135
 
86
136
    @needs_read_lock
87
137
    def get_parent_ids(self):
88
138
        """See Tree.get_parent_ids.
99
149
    def is_executable(self, file_id, path=None):
100
150
        return self._inventory[file_id].executable
101
151
 
 
152
    def kind(self, file_id):
 
153
        return self._inventory[file_id].kind
 
154
 
102
155
    def mkdir(self, path, file_id=None):
103
156
        """See MutableTree.mkdir()."""
104
157
        self.add(path, file_id, 'directory')
157
210
 
158
211
    def _populate_from_branch(self):
159
212
        """Populate the in-tree state from the branch."""
160
 
        self._basis_tree = self.branch.repository.revision_tree(
161
 
            self._branch_revision_id)
162
 
        if self._branch_revision_id is None:
 
213
        self._set_basis()
 
214
        if self._branch_revision_id == _mod_revision.NULL_REVISION:
163
215
            self._parent_ids = []
164
216
        else:
165
217
            self._parent_ids = [self._branch_revision_id]
166
 
        self._inventory = deepcopy(self._basis_tree._inventory)
 
218
        self._inventory = self._basis_tree._inventory._get_mutable_inventory()
167
219
        self._file_transport = MemoryTransport()
168
220
        # TODO copy the revision trees content, or do it lazy, or something.
169
221
        inventory_entries = self._inventory.iter_entries()
219
271
            else:
220
272
                raise errors.NoSuchId(self, file_id)
221
273
 
 
274
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
 
275
        """See MutableTree.set_parent_trees()."""
 
276
        for revision_id in revision_ids:
 
277
            _mod_revision.check_not_reserved_id(revision_id)
 
278
        if len(revision_ids) == 0:
 
279
            self._parent_ids = []
 
280
            self._branch_revision_id = _mod_revision.NULL_REVISION
 
281
        else:
 
282
            self._parent_ids = revision_ids
 
283
            self._branch_revision_id = revision_ids[0]
 
284
        self._allow_leftmost_as_ghost = allow_leftmost_as_ghost
 
285
        self._set_basis()
 
286
    
 
287
    def _set_basis(self):
 
288
        try:
 
289
            self._basis_tree = self.branch.repository.revision_tree(
 
290
                self._branch_revision_id)
 
291
        except errors.NoSuchRevision:
 
292
            if self._allow_leftmost_as_ghost:
 
293
                self._basis_tree = self.branch.repository.revision_tree(
 
294
                    _mod_revision.NULL_REVISION)
 
295
            else:
 
296
                raise
 
297
 
222
298
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
223
299
        """See MutableTree.set_parent_trees()."""
224
300
        if len(parents_list) == 0:
225
301
            self._parent_ids = []
226
 
            self._basis_tree = self.branch.repository.revisiontree(None)
 
302
            self._basis_tree = self.branch.repository.revision_tree(
 
303
                                   _mod_revision.NULL_REVISION)
227
304
        else:
228
305
            if parents_list[0][1] is None and not allow_leftmost_as_ghost:
229
306
                # a ghost in the left most parent
230
307
                raise errors.GhostRevisionUnusableHere(parents_list[0][0])
231
308
            self._parent_ids = [parent_id for parent_id, tree in parents_list]
232
 
            if parents_list[0][1] is None:
233
 
                self._basis_tree = self.branch.repository.revisiontree(None)
 
309
            if parents_list[0][1] is None or parents_list[0][1] == 'null:':
 
310
                self._basis_tree = self.branch.repository.revision_tree(
 
311
                                       _mod_revision.NULL_REVISION)
234
312
            else:
235
313
                self._basis_tree = parents_list[0][1]
236
314
            self._branch_revision_id = parents_list[0][0]