~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/memorytree.py

  • Committer: Martin Pool
  • Date: 2010-01-29 10:36:23 UTC
  • mto: This revision was merged to the branch mainline in revision 4992.
  • Revision ID: mbp@sourcefrog.net-20100129103623-hywka5hymo5z13jw
Change url to canonical.com or wiki, plus some doc improvements in passing

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