~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/memorytree.py

  • Committer: Martin Pool
  • Date: 2007-04-04 06:17:31 UTC
  • mto: This revision was merged to the branch mainline in revision 2397.
  • Revision ID: mbp@sourcefrog.net-20070404061731-tt2xrzllqhbodn83
Contents of TODO file moved into bug tracker

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