~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/memorytree.py

  • Committer: Jelmer Vernooij
  • Date: 2011-12-19 13:23:58 UTC
  • mto: This revision was merged to the branch mainline in revision 6386.
  • Revision ID: jelmer@canonical.com-20111219132358-uvs5a6y92gomzacd
Move importing from future until after doc string, otherwise the doc string will disappear.

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