1
# Copyright (C) 2006 Canonical Ltd
2
# Authors: Robert Collins <robert.collins@canonical.com>
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
"""Tests for the MemoryTree class."""
20
from bzrlib import errors
21
from bzrlib.memorytree import MemoryTree
22
from bzrlib.tests import TestCaseWithTransport
23
from bzrlib.treebuilder import TreeBuilder
26
class TestMemoryTree(TestCaseWithTransport):
28
def test_create_on_branch(self):
29
"""Creating a mutable tree on a trivial branch works."""
30
branch = self.make_branch('branch')
31
tree = MemoryTree.create_on_branch(branch)
32
self.assertEqual(branch.bzrdir, tree.bzrdir)
33
self.assertEqual(branch, tree.branch)
34
self.assertEqual([], tree.get_parent_ids())
36
def test_create_on_branch_with_content(self):
37
"""Creating a mutable tree on a non-trivial branch works."""
38
branch = self.make_branch('branch')
39
tree = MemoryTree.create_on_branch(branch)
42
builder = TreeBuilder()
43
builder.start_tree(tree)
44
builder.build(['foo'])
46
rev_id = tree.commit('first post')
48
tree = MemoryTree.create_on_branch(branch)
50
self.assertEqual([rev_id], tree.get_parent_ids())
51
self.assertEqual('contents of foo\n',
52
tree.get_file(tree.path2id('foo')).read())
55
def test_get_root_id(self):
56
branch = self.make_branch('branch')
57
tree = MemoryTree.create_on_branch(branch)
61
self.assertIsNot(None, tree.get_root_id())
65
def test_lock_tree_write(self):
66
"""Check we can lock_tree_write and unlock MemoryTrees."""
67
branch = self.make_branch('branch')
68
tree = MemoryTree.create_on_branch(branch)
69
tree.lock_tree_write()
72
def test_lock_tree_write_after_read_fails(self):
73
"""Check that we error when trying to upgrade a read lock to write."""
74
branch = self.make_branch('branch')
75
tree = MemoryTree.create_on_branch(branch)
77
self.assertRaises(errors.ReadOnlyError, tree.lock_tree_write)
80
def test_lock_write(self):
81
"""Check we can lock_write and unlock MemoryTrees."""
82
branch = self.make_branch('branch')
83
tree = MemoryTree.create_on_branch(branch)
87
def test_lock_write_after_read_fails(self):
88
"""Check that we error when trying to upgrade a read lock to write."""
89
branch = self.make_branch('branch')
90
tree = MemoryTree.create_on_branch(branch)
92
self.assertRaises(errors.ReadOnlyError, tree.lock_write)
95
def test_add_with_kind(self):
96
branch = self.make_branch('branch')
97
tree = MemoryTree.create_on_branch(branch)
99
tree.add(['', 'afile', 'adir'], None,
100
['directory', 'file', 'directory'])
101
self.assertEqual('afile', tree.id2path(tree.path2id('afile')))
102
self.assertEqual('adir', tree.id2path(tree.path2id('adir')))
103
self.assertFalse(tree.has_filename('afile'))
104
self.assertFalse(tree.has_filename('adir'))
107
def test_put_new_file(self):
108
branch = self.make_branch('branch')
109
tree = MemoryTree.create_on_branch(branch)
111
tree.add(['', 'foo'], ids=['root-id', 'foo-id'],
112
kinds=['directory', 'file'])
113
tree.put_file_bytes_non_atomic('foo-id', 'barshoom')
114
self.assertEqual('barshoom', tree.get_file('foo-id').read())
117
def test_put_existing_file(self):
118
branch = self.make_branch('branch')
119
tree = MemoryTree.create_on_branch(branch)
121
tree.add(['', 'foo'], ids=['root-id', 'foo-id'],
122
kinds=['directory', 'file'])
123
tree.put_file_bytes_non_atomic('foo-id', 'first-content')
124
tree.put_file_bytes_non_atomic('foo-id', 'barshoom')
125
self.assertEqual('barshoom', tree.get_file('foo-id').read())
128
def test_add_in_subdir(self):
129
branch = self.make_branch('branch')
130
tree = MemoryTree.create_on_branch(branch)
132
self.addCleanup(tree.unlock)
133
tree.add([''], ['root-id'], ['directory'])
134
# Unfortunately, the only way to 'mkdir' is to call 'tree.mkdir', but
135
# that *always* adds the directory as well. So if you want to create a
136
# file in a subdirectory, you have to split out the 'mkdir()' calls
137
# from the add and put_file_bytes_non_atomic calls. :(
138
tree.mkdir('adir', 'dir-id')
139
tree.add(['adir/afile'], ['file-id'], ['file'])
140
self.assertEqual('adir/afile', tree.id2path('file-id'))
141
self.assertEqual('adir', tree.id2path('dir-id'))
142
tree.put_file_bytes_non_atomic('file-id', 'barshoom')
144
def test_commit_trivial(self):
145
"""Smoke test for commit on a MemoryTree.
147
Becamse of commits design and layering, if this works, all commit
148
logic should work quite reliably.
150
branch = self.make_branch('branch')
151
tree = MemoryTree.create_on_branch(branch)
153
tree.add(['', 'foo'], ids=['root-id', 'foo-id'],
154
kinds=['directory', 'file'])
155
tree.put_file_bytes_non_atomic('foo-id', 'barshoom')
156
revision_id = tree.commit('message baby')
157
# the parents list for the tree should have changed.
158
self.assertEqual([revision_id], tree.get_parent_ids())
160
# and we should have a revision that is accessible outside the tree lock
161
revtree = tree.branch.repository.revision_tree(revision_id)
163
self.addCleanup(revtree.unlock)
164
self.assertEqual('barshoom', revtree.get_file('foo-id').read())
166
def test_unversion(self):
167
"""Some test for unversion of a memory tree."""
168
branch = self.make_branch('branch')
169
tree = MemoryTree.create_on_branch(branch)
171
tree.add(['', 'foo'], ids=['root-id', 'foo-id'],
172
kinds=['directory', 'file'])
173
tree.unversion(['foo-id'])
174
self.assertFalse(tree.has_id('foo-id'))
177
def test_last_revision(self):
178
"""There should be a last revision method we can call."""
179
tree = self.make_branch_and_memory_tree('branch')
182
rev_id = tree.commit('first post')
184
self.assertEqual(rev_id, tree.last_revision())
186
def test_rename_file(self):
187
tree = self.make_branch_and_memory_tree('branch')
189
self.addCleanup(tree.unlock)
190
tree.add(['', 'foo'], ['root-id', 'foo-id'], ['directory', 'file'])
191
tree.put_file_bytes_non_atomic('foo-id', 'content\n')
192
tree.commit('one', rev_id='rev-one')
193
tree.rename_one('foo', 'bar')
194
self.assertEqual('bar', tree.id2path('foo-id'))
195
self.assertEqual('content\n', tree._file_transport.get_bytes('bar'))
196
self.assertRaises(errors.NoSuchFile,
197
tree._file_transport.get_bytes, 'foo')
198
tree.commit('two', rev_id='rev-two')
199
self.assertEqual('content\n', tree._file_transport.get_bytes('bar'))
200
self.assertRaises(errors.NoSuchFile,
201
tree._file_transport.get_bytes, 'foo')
203
rev_tree2 = tree.branch.repository.revision_tree('rev-two')
204
self.assertEqual('bar', rev_tree2.id2path('foo-id'))
205
self.assertEqual('content\n', rev_tree2.get_file_text('foo-id'))
207
def test_rename_file_to_subdir(self):
208
tree = self.make_branch_and_memory_tree('branch')
210
self.addCleanup(tree.unlock)
212
tree.mkdir('subdir', 'subdir-id')
213
tree.add('foo', 'foo-id', 'file')
214
tree.put_file_bytes_non_atomic('foo-id', 'content\n')
215
tree.commit('one', rev_id='rev-one')
217
tree.rename_one('foo', 'subdir/bar')
218
self.assertEqual('subdir/bar', tree.id2path('foo-id'))
219
self.assertEqual('content\n',
220
tree._file_transport.get_bytes('subdir/bar'))
221
tree.commit('two', rev_id='rev-two')
222
rev_tree2 = tree.branch.repository.revision_tree('rev-two')
223
self.assertEqual('subdir/bar', rev_tree2.id2path('foo-id'))