~bzr-pqm/bzr/bzr.dev

0.12.12 by Aaron Bentley
Implement shelf creator
1
# Copyright (C) 2008 Aaron Bentley <aaron@aaronbentley.com>
2
#
3
#    This program is free software; you can redistribute it and/or modify
4
#    it under the terms of the GNU General Public License as published by
5
#    the Free Software Foundation; either version 2 of the License, or
6
#    (at your option) any later version.
7
#
8
#    This program is distributed in the hope that it will be useful,
9
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
10
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
#    GNU General Public License for more details.
12
#
13
#    You should have received a copy of the GNU General Public License
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
16
0.12.17 by Aaron Bentley
Handle creating symlinks
17
import os
18
0.12.19 by Aaron Bentley
Add support for writing shelves
19
from bzrlib import pack, tests, transform
0.14.7 by Aaron Bentley
Misc test cleanup
20
from bzrlib.plugins.shelf2 import shelf, serialize_transform
0.12.12 by Aaron Bentley
Implement shelf creator
21
22
23
class TestPrepareShelf(tests.TestCaseWithTransport):
24
25
    def test_shelve_rename(self):
26
        tree = self.make_branch_and_tree('.')
27
        self.build_tree(['foo'])
28
        tree.add(['foo'], ['foo-id'])
29
        tree.commit('foo')
30
        tree.rename_one('foo', 'bar')
0.14.7 by Aaron Bentley
Misc test cleanup
31
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.12 by Aaron Bentley
Implement shelf creator
32
        self.addCleanup(creator.finalize)
33
        self.assertEqual([('rename', 'foo-id', 'foo', 'bar')], list(creator))
34
        creator.shelve_rename('foo-id')
35
        work_trans_id = creator.work_transform.trans_id_file_id('foo-id')
36
        self.assertEqual('foo', creator.work_transform.final_name(
37
                         work_trans_id))
38
        shelf_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
39
        self.assertEqual('bar', creator.shelf_transform.final_name(
40
                         shelf_trans_id))
41
42
    def test_shelve_move(self):
43
        tree = self.make_branch_and_tree('.')
44
        self.build_tree(['foo/', 'bar/', 'foo/baz'])
45
        tree.add(['foo', 'bar', 'foo/baz'], ['foo-id', 'bar-id', 'baz-id'])
46
        tree.commit('foo')
47
        tree.rename_one('foo/baz', 'bar/baz')
0.14.7 by Aaron Bentley
Misc test cleanup
48
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.12 by Aaron Bentley
Implement shelf creator
49
        self.addCleanup(creator.finalize)
50
        self.assertEqual([('rename', 'baz-id', 'foo/baz', 'bar/baz')],
51
                         list(creator))
52
        creator.shelve_rename('baz-id')
53
        work_trans_id = creator.work_transform.trans_id_file_id('baz-id')
54
        work_foo = creator.work_transform.trans_id_file_id('foo-id')
55
        self.assertEqual(work_foo, creator.work_transform.final_parent(
56
                         work_trans_id))
57
        shelf_trans_id = creator.shelf_transform.trans_id_file_id('baz-id')
58
        shelf_bar = creator.shelf_transform.trans_id_file_id('bar-id')
59
        self.assertEqual(shelf_bar, creator.shelf_transform.final_parent(
60
                         shelf_trans_id))
0.12.13 by Aaron Bentley
Implement shelving content
61
        creator.transform()
62
        self.assertEqual('foo/baz', tree.id2path('baz-id'))
63
0.12.14 by Aaron Bentley
Add shelving of created files
64
    def assertShelvedFileEqual(self, expected_content, creator, file_id):
65
        s_trans_id = creator.shelf_transform.trans_id_file_id(file_id)
66
        shelf_file = creator.shelf_transform._limbo_name(s_trans_id)
67
        self.assertFileEqual(expected_content, shelf_file)
68
0.12.13 by Aaron Bentley
Implement shelving content
69
    def test_shelve_content_change(self):
70
        tree = self.make_branch_and_tree('.')
71
        tree.lock_write()
72
        self.addCleanup(tree.unlock)
73
        self.build_tree_contents([('foo', 'a\n')])
74
        tree.add('foo', 'foo-id')
75
        tree.commit('Committed foo')
76
        self.build_tree_contents([('foo', 'b\na\nc\n')])
0.14.7 by Aaron Bentley
Misc test cleanup
77
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.13 by Aaron Bentley
Implement shelving content
78
        self.addCleanup(creator.finalize)
79
        self.assertEqual([('modify text', 'foo-id')], list(creator))
0.14.14 by Aaron Bentley
Change shelf_text to shelve_lines
80
        creator.shelve_lines('foo-id', ['a\n', 'c\n'])
0.12.13 by Aaron Bentley
Implement shelving content
81
        creator.transform()
82
        self.assertFileEqual('a\nc\n', 'foo')
0.12.14 by Aaron Bentley
Add shelving of created files
83
        self.assertShelvedFileEqual('b\na\n', creator, 'foo-id')
84
85
    def test_shelve_creation(self):
86
        tree = self.make_branch_and_tree('.')
87
        tree.lock_write()
88
        self.addCleanup(tree.unlock)
89
        tree.commit('Empty tree')
0.12.16 by Aaron Bentley
Handle shelving directory creation
90
        self.build_tree_contents([('foo', 'a\n'), ('bar/',)])
91
        tree.add(['foo', 'bar'], ['foo-id', 'bar-id'])
0.14.7 by Aaron Bentley
Misc test cleanup
92
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.14 by Aaron Bentley
Add shelving of created files
93
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
94
        self.assertEqual([('add file', 'bar-id', 'directory', 'bar'),
95
                          ('add file', 'foo-id', 'file', 'foo')],
0.12.16 by Aaron Bentley
Handle shelving directory creation
96
                          sorted(list(creator)))
0.14.2 by Aaron Bentley
Somewhat clean up shelving
97
        creator.shelve_creation('foo-id')
98
        creator.shelve_creation('bar-id')
0.12.14 by Aaron Bentley
Add shelving of created files
99
        creator.transform()
0.12.15 by Aaron Bentley
Handle file-id when shelving creation
100
        self.assertRaises(StopIteration,
101
                          tree.iter_entries_by_dir(['foo-id']).next)
102
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
103
        self.assertEqual('foo-id',
104
                         creator.shelf_transform.final_file_id(s_trans_id))
0.12.14 by Aaron Bentley
Add shelving of created files
105
        self.failIfExists('foo')
0.12.16 by Aaron Bentley
Handle shelving directory creation
106
        self.failIfExists('bar')
0.12.14 by Aaron Bentley
Add shelving of created files
107
        self.assertShelvedFileEqual('a\n', creator, 'foo-id')
0.12.16 by Aaron Bentley
Handle shelving directory creation
108
        s_bar_trans_id = creator.shelf_transform.trans_id_file_id('bar-id')
109
        self.assertEqual('directory',
110
            creator.shelf_transform.final_kind(s_bar_trans_id))
0.12.17 by Aaron Bentley
Handle creating symlinks
111
112
    def test_shelve_symlink_creation(self):
113
        self.requireFeature(tests.SymlinkFeature)
114
        tree = self.make_branch_and_tree('.')
115
        tree.lock_write()
116
        self.addCleanup(tree.unlock)
117
        tree.commit('Empty tree')
118
        os.symlink('bar', 'foo')
119
        tree.add('foo', 'foo-id')
0.14.7 by Aaron Bentley
Misc test cleanup
120
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.17 by Aaron Bentley
Handle creating symlinks
121
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
122
        self.assertEqual([('add file', 'foo-id', 'symlink', 'foo')],
123
                         list(creator))
0.14.2 by Aaron Bentley
Somewhat clean up shelving
124
        creator.shelve_creation('foo-id')
0.12.17 by Aaron Bentley
Handle creating symlinks
125
        creator.transform()
126
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
127
        self.failIfExists('foo')
128
        limbo_name = creator.shelf_transform._limbo_name(s_trans_id)
129
        self.assertEqual('bar', os.readlink(limbo_name))
0.12.19 by Aaron Bentley
Add support for writing shelves
130
0.14.12 by Aaron Bentley
Handle new dangling ids
131
    def test_shelve_creation_no_contents(self):
132
        tree = self.make_branch_and_tree('.')
133
        tree.lock_write()
134
        self.addCleanup(tree.unlock)
135
        tree.commit('Empty tree')
136
        self.build_tree(['foo'])
137
        tree.add('foo', 'foo-id')
138
        os.unlink('foo')
139
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
140
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
141
        self.assertEqual([('add file', 'foo-id', None, 'foo')],
0.14.12 by Aaron Bentley
Handle new dangling ids
142
                         sorted(list(creator)))
143
        creator.shelve_creation('foo-id')
144
        creator.transform()
145
        self.assertRaises(StopIteration,
146
                          tree.iter_entries_by_dir(['foo-id']).next)
147
        self.assertShelvedFileEqual('', creator, 'foo-id')
148
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
149
        self.assertEqual('foo-id',
150
                         creator.shelf_transform.final_file_id(s_trans_id))
151
        self.failIfExists('foo')
152
0.14.4 by Aaron Bentley
Implement shelving deletion
153
    def test_shelve_deletion(self):
154
        tree = self.make_branch_and_tree('tree')
0.14.11 by Aaron Bentley
Fix re-versioning
155
        tree.lock_write()
156
        self.addCleanup(tree.unlock)
0.14.4 by Aaron Bentley
Implement shelving deletion
157
        self.build_tree_contents([('tree/foo/',), ('tree/foo/bar', 'baz')])
158
        tree.add(['foo', 'foo/bar'], ['foo-id', 'bar-id'])
159
        tree.commit('Added file and directory')
0.14.9 by Aaron Bentley
Shelve deleted files properly
160
        tree.unversion(['foo-id', 'bar-id'])
0.14.4 by Aaron Bentley
Implement shelving deletion
161
        os.unlink('tree/foo/bar')
162
        os.rmdir('tree/foo')
0.14.7 by Aaron Bentley
Misc test cleanup
163
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.14.4 by Aaron Bentley
Implement shelving deletion
164
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
165
        self.assertEqual([('delete file', 'bar-id', 'file', 'foo/bar'),
166
                          ('delete file', 'foo-id', 'directory', 'foo')],
0.14.4 by Aaron Bentley
Implement shelving deletion
167
                          sorted(list(creator)))
168
        creator.shelve_deletion('foo-id')
169
        creator.shelve_deletion('bar-id')
0.14.6 by Aaron Bentley
Fix deletion test
170
        creator.transform()
0.14.11 by Aaron Bentley
Fix re-versioning
171
        self.assertTrue('foo-id' in tree)
172
        self.assertTrue('bar-id' in tree)
0.14.4 by Aaron Bentley
Implement shelving deletion
173
        self.assertFileEqual('baz', 'tree/foo/bar')
174
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
175
    def test_shelve_delete_contents(self):
176
        tree = self.make_branch_and_tree('tree')
177
        self.build_tree(['tree/foo',])
178
        tree.add('foo', 'foo-id')
179
        tree.commit('Added file and directory')
180
        os.unlink('tree/foo')
181
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
182
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
183
        self.assertEqual([('delete file', 'foo-id', 'file', 'foo')],
184
                         sorted(list(creator)))
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
185
        creator.shelve_deletion('foo-id')
186
        creator.transform()
187
        self.failUnlessExists('tree/foo')
188
189
    def test_shelve_unversion(self):
190
        tree = self.make_branch_and_tree('tree')
191
        self.build_tree(['tree/foo',])
192
        tree.add('foo', 'foo-id')
193
        tree.commit('Added file and directory')
194
        tree.unversion(['foo-id'])
195
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
196
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
197
        self.assertEqual([('delete file', 'foo-id', 'file', 'foo')],
198
                         sorted(list(creator)))
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
199
        creator.shelve_deletion('foo-id')
200
        creator.transform()
201
        self.failUnlessExists('tree/foo')
202
0.12.19 by Aaron Bentley
Add support for writing shelves
203
    def test_write_shelf(self):
204
        tree = self.make_branch_and_tree('tree')
205
        self.build_tree(['tree/foo'])
206
        tree.add('foo', 'foo-id')
0.14.7 by Aaron Bentley
Misc test cleanup
207
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
208
        self.addCleanup(creator.finalize)
0.12.19 by Aaron Bentley
Add support for writing shelves
209
        list(creator)
0.14.2 by Aaron Bentley
Somewhat clean up shelving
210
        creator.shelve_creation('foo-id')
0.12.29 by Aaron Bentley
Update failing tests
211
        shelf_file = open('shelf', 'wb')
212
        try:
213
            filename = creator.write_shelf(shelf_file)
214
        finally:
215
            shelf_file.close()
0.12.19 by Aaron Bentley
Add support for writing shelves
216
        parser = pack.ContainerPushParser()
0.12.29 by Aaron Bentley
Update failing tests
217
        shelf_file = open('shelf', 'rb')
0.12.19 by Aaron Bentley
Add support for writing shelves
218
        try:
219
            parser.accept_bytes(shelf_file.read())
220
        finally:
221
            shelf_file.close()
222
        tt = transform.TransformPreview(tree)
0.14.7 by Aaron Bentley
Misc test cleanup
223
        self.addCleanup(tt.finalize)
0.12.29 by Aaron Bentley
Update failing tests
224
        records = iter(parser.read_pending_records())
225
        #skip revision-id
226
        records.next()
227
        serialize_transform.deserialize(tt, records)
0.12.21 by Aaron Bentley
Add failing test of unshelver
228
229
230
class TestUnshelver(tests.TestCaseWithTransport):
231
232
    def test_unshelve(self):
233
        tree = self.make_branch_and_tree('tree')
0.12.30 by Aaron Bentley
Fix test by using non NULL base tree
234
        tree.commit('first commit')
0.12.21 by Aaron Bentley
Add failing test of unshelver
235
        self.build_tree_contents([('tree/foo', 'bar')])
0.12.24 by Aaron Bentley
Get unshelve using merge codepath, not applying transform directly
236
        tree.lock_write()
237
        self.addCleanup(tree.unlock)
0.12.21 by Aaron Bentley
Add failing test of unshelver
238
        tree.add('foo', 'foo-id')
0.15.5 by Aaron Bentley
Rename to shelf
239
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
240
        self.addCleanup(creator.finalize)
0.12.21 by Aaron Bentley
Add failing test of unshelver
241
        list(creator)
0.12.23 by Aaron Bentley
Fix up unshelve some more
242
        creator.shelve_creation('foo-id')
0.12.29 by Aaron Bentley
Update failing tests
243
        shelf_file = open('shelf-file', 'w+b')
244
        try:
245
            filename = creator.write_shelf(shelf_file)
246
            creator.transform()
247
            shelf_file.seek(0)
0.12.34 by Aaron Bentley
merge with unshelve
248
            unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
0.12.29 by Aaron Bentley
Update failing tests
249
            unshelver.unshelve()
250
            self.assertFileEqual('bar', 'tree/foo')
251
        finally:
252
            shelf_file.close()
0.12.26 by Aaron Bentley
Use correct base for shelving
253
254
    def test_unshelve_base(self):
255
        tree = self.make_branch_and_tree('tree')
256
        tree.lock_write()
257
        self.addCleanup(tree.unlock)
258
        tree.commit('rev1', rev_id='rev1')
0.15.5 by Aaron Bentley
Rename to shelf
259
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.42 by Aaron Bentley
Get shelf from tree
260
        manager = tree.get_shelf_manager()
0.12.29 by Aaron Bentley
Update failing tests
261
        shelf_id, shelf_file = manager.new_shelf()
262
        try:
263
            filename = creator.write_shelf(shelf_file)
264
        finally:
265
            shelf_file.close()
0.12.26 by Aaron Bentley
Use correct base for shelving
266
        tree.commit('rev2', rev_id='rev2')
0.12.29 by Aaron Bentley
Update failing tests
267
        shelf_file = manager.read_shelf(1)
268
        try:
0.12.34 by Aaron Bentley
merge with unshelve
269
            unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
0.12.29 by Aaron Bentley
Update failing tests
270
        finally:
271
            shelf_file.close()
0.12.26 by Aaron Bentley
Use correct base for shelving
272
        self.assertEqual('rev1', unshelver.base_tree.get_revision_id())
0.12.27 by Aaron Bentley
Implement shelf manager
273
274
275
class TestShelfManager(tests.TestCaseWithTransport):
276
0.12.42 by Aaron Bentley
Get shelf from tree
277
    def test_get_shelf_manager(self):
0.12.27 by Aaron Bentley
Implement shelf manager
278
        tree = self.make_branch_and_tree('.')
0.12.42 by Aaron Bentley
Get shelf from tree
279
        manager = tree.get_shelf_manager()
0.12.41 by Aaron Bentley
Change shelf to use WT control dir for shelves
280
        self.assertEqual(tree._transport.base + 'shelf/',
0.12.27 by Aaron Bentley
Implement shelf manager
281
                         manager.transport.base)
282
283
    def get_manager(self):
0.12.42 by Aaron Bentley
Get shelf from tree
284
        return self.make_branch_and_tree('.').get_shelf_manager()
0.12.27 by Aaron Bentley
Implement shelf manager
285
286
    def test_new_shelf(self):
287
        manager = self.get_manager()
288
        shelf_id, shelf_file = manager.new_shelf()
289
        shelf_file.close()
290
        self.assertEqual(1, shelf_id)
291
        shelf_id, shelf_file = manager.new_shelf()
292
        shelf_file.close()
293
        self.assertEqual(2, shelf_id)
294
        manager.delete_shelf(1)
295
        shelf_id, shelf_file = manager.new_shelf()
296
        shelf_file.close()
297
        self.assertEqual(3, shelf_id)
298
299
    def test_active_shelves(self):
300
        manager = self.get_manager()
301
        self.assertEqual([], manager.active_shelves())
302
        shelf_id, shelf_file = manager.new_shelf()
303
        shelf_file.close()
304
        self.assertEqual([1], manager.active_shelves())
305
306
    def test_delete_shelf(self):
307
        manager = self.get_manager()
308
        shelf_id, shelf_file = manager.new_shelf()
309
        shelf_file.close()
310
        self.assertEqual([1], manager.active_shelves())
311
        manager.delete_shelf(1)
312
        self.assertEqual([], manager.active_shelves())
313
314
    def test_last_shelf(self):
315
        manager = self.get_manager()
316
        self.assertIs(None, manager.last_shelf())
317
        shelf_id, shelf_file = manager.new_shelf()
318
        shelf_file.close()
319
        self.assertEqual(1, manager.last_shelf())
320
321
    def test_read_shelf(self):
322
        manager = self.get_manager()
323
        shelf_id, shelf_file = manager.new_shelf()
324
        try:
325
            shelf_file.write('foo')
326
        finally:
327
            shelf_file.close()
328
        shelf_id, shelf_file = manager.new_shelf()
329
        try:
330
            shelf_file.write('bar')
331
        finally:
332
            shelf_file.close()
333
        shelf_file = manager.read_shelf(1)
334
        try:
335
            self.assertEqual('foo', shelf_file.read())
336
        finally:
337
            shelf_file.close()
338
        shelf_file = manager.read_shelf(2)
339
        try:
340
            self.assertEqual('bar', shelf_file.read())
341
        finally:
342
            shelf_file.close()
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
343
0.12.50 by Aaron Bentley
Improve error handling for non-existant shelf-ids
344
    def test_read_non_existant(self):
345
        manager = self.get_manager()
346
        e = self.assertRaises(shelf.NoSuchShelfId, manager.read_shelf, 1)
347
        self.assertEqual('No changes are shelved with id "1".', str(e))
348
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
349
    def test_shelve_changes(self):
350
        tree = self.make_branch_and_tree('tree')
0.12.44 by Aaron Bentley
Give manager responsibility for applying transform
351
        tree.commit('no-change commit')
352
        tree.lock_write()
353
        self.addCleanup(tree.unlock)
354
        self.build_tree_contents([('tree/foo', 'bar')])
355
        self.assertFileEqual('bar', 'tree/foo')
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
356
        tree.add('foo', 'foo-id')
357
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
358
        self.addCleanup(creator.finalize)
359
        list(creator)
360
        creator.shelve_creation('foo-id')
361
        shelf_manager = tree.get_shelf_manager()
362
        shelf_id = shelf_manager.shelve_changes(creator)
0.12.44 by Aaron Bentley
Give manager responsibility for applying transform
363
        self.failIfExists('tree/foo')
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
364
        unshelver = shelf_manager.get_unshelver(shelf_id)
0.12.44 by Aaron Bentley
Give manager responsibility for applying transform
365
        unshelver.unshelve()
366
        self.assertFileEqual('bar', 'tree/foo')