~bzr-pqm/bzr/bzr.dev

0.14.26 by Aaron Bentley
Update copyright
1
# Copyright (C) 2008 Canonical Ltd
0.12.12 by Aaron Bentley
Implement shelf creator
2
#
0.12.80 by Aaron Bentley
Re-format GPL notifications
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.12.12 by Aaron Bentley
Implement shelf creator
16
0.12.17 by Aaron Bentley
Handle creating symlinks
17
import os
18
4297.1.1 by Vincent Ladeuil
Trivial cleanups.
19
from bzrlib import (
20
    errors,
21
    osutils,
22
    pack,
23
    shelf,
24
    tests,
25
    transform,
26
    workingtree,
27
    )
0.12.12 by Aaron Bentley
Implement shelf creator
28
29
0.14.34 by Aaron Bentley
Factor out the empty shelf
30
EMPTY_SHELF = ("Bazaar pack format 1 (introduced in 0.18)\n"
0.15.39 by Aaron Bentley
Update empty shelf serialization
31
               "B23\n"
32
               "metadata\n\n"
33
               "d11:revision_id5:null:e"
0.14.34 by Aaron Bentley
Factor out the empty shelf
34
               "B159\n"
35
               "attribs\n\n"
36
               "d10:_id_numberi0e18:_new_executabilityde7:_new_idde"
37
               "9:_new_namede11:_new_parentde16:_non_present_idsde"
38
               "17:_removed_contentsle11:_removed_idle14:_tree_path_idsdeeE")
39
40
0.12.12 by Aaron Bentley
Implement shelf creator
41
class TestPrepareShelf(tests.TestCaseWithTransport):
42
43
    def test_shelve_rename(self):
44
        tree = self.make_branch_and_tree('.')
45
        self.build_tree(['foo'])
46
        tree.add(['foo'], ['foo-id'])
47
        tree.commit('foo')
48
        tree.rename_one('foo', 'bar')
0.14.7 by Aaron Bentley
Misc test cleanup
49
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.12 by Aaron Bentley
Implement shelf creator
50
        self.addCleanup(creator.finalize)
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
51
        self.assertEqual([('rename', 'foo-id', 'foo', 'bar')],
52
                          list(creator.iter_shelvable()))
0.12.12 by Aaron Bentley
Implement shelf creator
53
        creator.shelve_rename('foo-id')
54
        work_trans_id = creator.work_transform.trans_id_file_id('foo-id')
55
        self.assertEqual('foo', creator.work_transform.final_name(
56
                         work_trans_id))
57
        shelf_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
58
        self.assertEqual('bar', creator.shelf_transform.final_name(
59
                         shelf_trans_id))
60
61
    def test_shelve_move(self):
62
        tree = self.make_branch_and_tree('.')
63
        self.build_tree(['foo/', 'bar/', 'foo/baz'])
64
        tree.add(['foo', 'bar', 'foo/baz'], ['foo-id', 'bar-id', 'baz-id'])
65
        tree.commit('foo')
66
        tree.rename_one('foo/baz', 'bar/baz')
0.14.7 by Aaron Bentley
Misc test cleanup
67
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.12 by Aaron Bentley
Implement shelf creator
68
        self.addCleanup(creator.finalize)
69
        self.assertEqual([('rename', 'baz-id', 'foo/baz', 'bar/baz')],
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
70
                         list(creator.iter_shelvable()))
0.12.12 by Aaron Bentley
Implement shelf creator
71
        creator.shelve_rename('baz-id')
72
        work_trans_id = creator.work_transform.trans_id_file_id('baz-id')
73
        work_foo = creator.work_transform.trans_id_file_id('foo-id')
74
        self.assertEqual(work_foo, creator.work_transform.final_parent(
75
                         work_trans_id))
76
        shelf_trans_id = creator.shelf_transform.trans_id_file_id('baz-id')
77
        shelf_bar = creator.shelf_transform.trans_id_file_id('bar-id')
78
        self.assertEqual(shelf_bar, creator.shelf_transform.final_parent(
79
                         shelf_trans_id))
0.12.13 by Aaron Bentley
Implement shelving content
80
        creator.transform()
81
        self.assertEqual('foo/baz', tree.id2path('baz-id'))
82
0.12.14 by Aaron Bentley
Add shelving of created files
83
    def assertShelvedFileEqual(self, expected_content, creator, file_id):
84
        s_trans_id = creator.shelf_transform.trans_id_file_id(file_id)
85
        shelf_file = creator.shelf_transform._limbo_name(s_trans_id)
86
        self.assertFileEqual(expected_content, shelf_file)
87
0.12.13 by Aaron Bentley
Implement shelving content
88
    def test_shelve_content_change(self):
89
        tree = self.make_branch_and_tree('.')
90
        tree.lock_write()
91
        self.addCleanup(tree.unlock)
92
        self.build_tree_contents([('foo', 'a\n')])
93
        tree.add('foo', 'foo-id')
94
        tree.commit('Committed foo')
95
        self.build_tree_contents([('foo', 'b\na\nc\n')])
0.14.7 by Aaron Bentley
Misc test cleanup
96
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.13 by Aaron Bentley
Implement shelving content
97
        self.addCleanup(creator.finalize)
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
98
        self.assertEqual([('modify text', 'foo-id')],
99
                         list(creator.iter_shelvable()))
0.14.14 by Aaron Bentley
Change shelf_text to shelve_lines
100
        creator.shelve_lines('foo-id', ['a\n', 'c\n'])
0.12.13 by Aaron Bentley
Implement shelving content
101
        creator.transform()
102
        self.assertFileEqual('a\nc\n', 'foo')
0.12.14 by Aaron Bentley
Add shelving of created files
103
        self.assertShelvedFileEqual('b\na\n', creator, 'foo-id')
104
105
    def test_shelve_creation(self):
106
        tree = self.make_branch_and_tree('.')
107
        tree.lock_write()
108
        self.addCleanup(tree.unlock)
109
        tree.commit('Empty tree')
0.12.16 by Aaron Bentley
Handle shelving directory creation
110
        self.build_tree_contents([('foo', 'a\n'), ('bar/',)])
111
        tree.add(['foo', 'bar'], ['foo-id', 'bar-id'])
0.14.7 by Aaron Bentley
Misc test cleanup
112
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.14 by Aaron Bentley
Add shelving of created files
113
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
114
        self.assertEqual([('add file', 'bar-id', 'directory', 'bar'),
115
                          ('add file', 'foo-id', 'file', 'foo')],
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
116
                          sorted(list(creator.iter_shelvable())))
0.14.2 by Aaron Bentley
Somewhat clean up shelving
117
        creator.shelve_creation('foo-id')
118
        creator.shelve_creation('bar-id')
0.12.14 by Aaron Bentley
Add shelving of created files
119
        creator.transform()
0.12.15 by Aaron Bentley
Handle file-id when shelving creation
120
        self.assertRaises(StopIteration,
121
                          tree.iter_entries_by_dir(['foo-id']).next)
122
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
123
        self.assertEqual('foo-id',
124
                         creator.shelf_transform.final_file_id(s_trans_id))
0.12.14 by Aaron Bentley
Add shelving of created files
125
        self.failIfExists('foo')
0.12.16 by Aaron Bentley
Handle shelving directory creation
126
        self.failIfExists('bar')
0.12.14 by Aaron Bentley
Add shelving of created files
127
        self.assertShelvedFileEqual('a\n', creator, 'foo-id')
0.12.16 by Aaron Bentley
Handle shelving directory creation
128
        s_bar_trans_id = creator.shelf_transform.trans_id_file_id('bar-id')
129
        self.assertEqual('directory',
130
            creator.shelf_transform.final_kind(s_bar_trans_id))
0.12.17 by Aaron Bentley
Handle creating symlinks
131
132
    def test_shelve_symlink_creation(self):
133
        self.requireFeature(tests.SymlinkFeature)
134
        tree = self.make_branch_and_tree('.')
135
        tree.lock_write()
136
        self.addCleanup(tree.unlock)
137
        tree.commit('Empty tree')
138
        os.symlink('bar', 'foo')
139
        tree.add('foo', 'foo-id')
0.14.7 by Aaron Bentley
Misc test cleanup
140
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.17 by Aaron Bentley
Handle creating symlinks
141
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
142
        self.assertEqual([('add file', 'foo-id', 'symlink', 'foo')],
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
143
                         list(creator.iter_shelvable()))
0.14.2 by Aaron Bentley
Somewhat clean up shelving
144
        creator.shelve_creation('foo-id')
0.12.17 by Aaron Bentley
Handle creating symlinks
145
        creator.transform()
146
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
147
        self.failIfExists('foo')
148
        limbo_name = creator.shelf_transform._limbo_name(s_trans_id)
149
        self.assertEqual('bar', os.readlink(limbo_name))
0.12.19 by Aaron Bentley
Add support for writing shelves
150
4119.5.1 by James Westby
Shelve can now shelve changes to a symlink's target.
151
    def test_shelve_symlink_target_change(self):
152
        self.requireFeature(tests.SymlinkFeature)
153
        tree = self.make_branch_and_tree('.')
154
        tree.lock_write()
155
        self.addCleanup(tree.unlock)
156
        os.symlink('bar', 'foo')
157
        tree.add('foo', 'foo-id')
158
        tree.commit("commit symlink")
159
        os.unlink("foo")
160
        os.symlink('baz', 'foo')
161
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
162
        self.addCleanup(creator.finalize)
163
        self.assertEqual([('modify target', 'foo-id', 'foo', 'bar', 'baz')],
164
                         list(creator.iter_shelvable()))
165
        creator.shelve_modify_target('foo-id')
166
        creator.transform()
167
        self.assertEqual('bar', os.readlink('foo'))
168
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
169
        limbo_name = creator.shelf_transform._limbo_name(s_trans_id)
170
        self.assertEqual('baz', os.readlink(limbo_name))
171
0.14.12 by Aaron Bentley
Handle new dangling ids
172
    def test_shelve_creation_no_contents(self):
173
        tree = self.make_branch_and_tree('.')
174
        tree.lock_write()
175
        self.addCleanup(tree.unlock)
176
        tree.commit('Empty tree')
177
        self.build_tree(['foo'])
178
        tree.add('foo', 'foo-id')
179
        os.unlink('foo')
180
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
181
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
182
        self.assertEqual([('add file', 'foo-id', None, 'foo')],
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
183
                         sorted(list(creator.iter_shelvable())))
0.14.12 by Aaron Bentley
Handle new dangling ids
184
        creator.shelve_creation('foo-id')
185
        creator.transform()
186
        self.assertRaises(StopIteration,
187
                          tree.iter_entries_by_dir(['foo-id']).next)
188
        self.assertShelvedFileEqual('', creator, 'foo-id')
189
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
190
        self.assertEqual('foo-id',
191
                         creator.shelf_transform.final_file_id(s_trans_id))
192
        self.failIfExists('foo')
193
0.14.4 by Aaron Bentley
Implement shelving deletion
194
    def test_shelve_deletion(self):
195
        tree = self.make_branch_and_tree('tree')
0.14.11 by Aaron Bentley
Fix re-versioning
196
        tree.lock_write()
197
        self.addCleanup(tree.unlock)
0.14.4 by Aaron Bentley
Implement shelving deletion
198
        self.build_tree_contents([('tree/foo/',), ('tree/foo/bar', 'baz')])
199
        tree.add(['foo', 'foo/bar'], ['foo-id', 'bar-id'])
200
        tree.commit('Added file and directory')
0.14.9 by Aaron Bentley
Shelve deleted files properly
201
        tree.unversion(['foo-id', 'bar-id'])
0.14.4 by Aaron Bentley
Implement shelving deletion
202
        os.unlink('tree/foo/bar')
203
        os.rmdir('tree/foo')
0.14.7 by Aaron Bentley
Misc test cleanup
204
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.14.4 by Aaron Bentley
Implement shelving deletion
205
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
206
        self.assertEqual([('delete file', 'bar-id', 'file', 'foo/bar'),
207
                          ('delete file', 'foo-id', 'directory', 'foo')],
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
208
                          sorted(list(creator.iter_shelvable())))
0.14.4 by Aaron Bentley
Implement shelving deletion
209
        creator.shelve_deletion('foo-id')
210
        creator.shelve_deletion('bar-id')
0.14.6 by Aaron Bentley
Fix deletion test
211
        creator.transform()
0.14.11 by Aaron Bentley
Fix re-versioning
212
        self.assertTrue('foo-id' in tree)
213
        self.assertTrue('bar-id' in tree)
0.14.4 by Aaron Bentley
Implement shelving deletion
214
        self.assertFileEqual('baz', 'tree/foo/bar')
215
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
216
    def test_shelve_delete_contents(self):
217
        tree = self.make_branch_and_tree('tree')
218
        self.build_tree(['tree/foo',])
219
        tree.add('foo', 'foo-id')
220
        tree.commit('Added file and directory')
221
        os.unlink('tree/foo')
222
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
223
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
224
        self.assertEqual([('delete file', 'foo-id', 'file', 'foo')],
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
225
                         sorted(list(creator.iter_shelvable())))
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
226
        creator.shelve_deletion('foo-id')
227
        creator.transform()
228
        self.failUnlessExists('tree/foo')
229
0.14.23 by Aaron Bentley
Allow shelving kind change
230
    def test_shelve_change_kind(self):
231
        tree = self.make_branch_and_tree('tree')
232
        self.build_tree_contents([('tree/foo', 'bar')])
233
        tree.add('foo', 'foo-id')
234
        tree.commit('Added file and directory')
235
        os.unlink('tree/foo')
236
        os.mkdir('tree/foo')
237
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
238
        self.addCleanup(creator.finalize)
239
        self.assertEqual([('change kind', 'foo-id', 'file', 'directory',
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
240
                           'foo')], sorted(list(creator.iter_shelvable())))
0.14.23 by Aaron Bentley
Allow shelving kind change
241
        creator.shelve_content_change('foo-id')
242
        creator.transform()
243
        self.assertFileEqual('bar', 'tree/foo')
244
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
245
        self.assertEqual('directory',
246
                         creator.shelf_transform._new_contents[s_trans_id])
247
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
248
    def test_shelve_unversion(self):
249
        tree = self.make_branch_and_tree('tree')
250
        self.build_tree(['tree/foo',])
251
        tree.add('foo', 'foo-id')
252
        tree.commit('Added file and directory')
253
        tree.unversion(['foo-id'])
254
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
255
        self.addCleanup(creator.finalize)
0.14.13 by Aaron Bentley
Provide path and kind when deletes/adds are detected.
256
        self.assertEqual([('delete file', 'foo-id', 'file', 'foo')],
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
257
                         sorted(list(creator.iter_shelvable())))
0.14.10 by Aaron Bentley
Fix behavior with deletions, unversioning, ...
258
        creator.shelve_deletion('foo-id')
259
        creator.transform()
260
        self.failUnlessExists('tree/foo')
261
0.14.33 by Aaron Bentley
Add explicit test of shelf on-disk format
262
    def test_shelve_serialization(self):
263
        tree = self.make_branch_and_tree('.')
264
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
265
        self.addCleanup(creator.finalize)
0.12.76 by Aaron Bentley
Convert failing tests
266
        shelf_file = open('shelf', 'wb')
267
        self.addCleanup(shelf_file.close)
268
        try:
269
            creator.write_shelf(shelf_file)
270
        finally:
271
            shelf_file.close()
272
        self.assertFileEqual(EMPTY_SHELF, 'shelf')
0.14.33 by Aaron Bentley
Add explicit test of shelf on-disk format
273
0.12.19 by Aaron Bentley
Add support for writing shelves
274
    def test_write_shelf(self):
275
        tree = self.make_branch_and_tree('tree')
276
        self.build_tree(['tree/foo'])
277
        tree.add('foo', 'foo-id')
0.14.7 by Aaron Bentley
Misc test cleanup
278
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
279
        self.addCleanup(creator.finalize)
0.14.32 by Aaron Bentley
Replace ShelfCreator.__iter__ with ShelfCreator.iter_shelvable
280
        list(creator.iter_shelvable())
0.14.2 by Aaron Bentley
Somewhat clean up shelving
281
        creator.shelve_creation('foo-id')
0.12.29 by Aaron Bentley
Update failing tests
282
        shelf_file = open('shelf', 'wb')
283
        try:
0.12.61 by Aaron Bentley
Stop assigning result of write_shelf
284
            creator.write_shelf(shelf_file)
0.12.29 by Aaron Bentley
Update failing tests
285
        finally:
286
            shelf_file.close()
0.12.19 by Aaron Bentley
Add support for writing shelves
287
        parser = pack.ContainerPushParser()
0.12.29 by Aaron Bentley
Update failing tests
288
        shelf_file = open('shelf', 'rb')
0.12.19 by Aaron Bentley
Add support for writing shelves
289
        try:
290
            parser.accept_bytes(shelf_file.read())
291
        finally:
292
            shelf_file.close()
293
        tt = transform.TransformPreview(tree)
0.14.7 by Aaron Bentley
Misc test cleanup
294
        self.addCleanup(tt.finalize)
0.12.29 by Aaron Bentley
Update failing tests
295
        records = iter(parser.read_pending_records())
296
        #skip revision-id
297
        records.next()
0.15.26 by Aaron Bentley
Merge with prepare-shelf
298
        tt.deserialize(records)
0.12.21 by Aaron Bentley
Add failing test of unshelver
299
3873.2.4 by Benoît Pierre
Add a test: test_shelve_unversioned; check if tree is in a clean state
300
    def test_shelve_unversioned(self):
301
        tree = self.make_branch_and_tree('tree')
302
        self.assertRaises(errors.PathsNotVersionedError,
303
                          shelf.ShelfCreator, tree, tree.basis_tree(), ['foo'])
304
        # We should be able to lock/unlock the tree if ShelfCreator cleaned
305
        # after itself.
306
        wt = workingtree.WorkingTree.open('tree')
307
        wt.lock_tree_write()
308
        wt.unlock()
309
        # And a second tentative should raise the same error (no
310
        # limbo/pending_deletion leftovers).
311
        self.assertRaises(errors.PathsNotVersionedError,
312
                          shelf.ShelfCreator, tree, tree.basis_tree(), ['foo'])
313
0.12.21 by Aaron Bentley
Add failing test of unshelver
314
315
class TestUnshelver(tests.TestCaseWithTransport):
316
0.15.31 by Aaron Bentley
Remove 'unshelve' method, test make_merger
317
    def test_make_merger(self):
0.12.21 by Aaron Bentley
Add failing test of unshelver
318
        tree = self.make_branch_and_tree('tree')
0.12.30 by Aaron Bentley
Fix test by using non NULL base tree
319
        tree.commit('first commit')
0.12.21 by Aaron Bentley
Add failing test of unshelver
320
        self.build_tree_contents([('tree/foo', 'bar')])
0.12.24 by Aaron Bentley
Get unshelve using merge codepath, not applying transform directly
321
        tree.lock_write()
322
        self.addCleanup(tree.unlock)
0.12.21 by Aaron Bentley
Add failing test of unshelver
323
        tree.add('foo', 'foo-id')
0.15.5 by Aaron Bentley
Rename to shelf
324
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
325
        self.addCleanup(creator.finalize)
0.12.73 by Aaron Bentley
Merge unshelve into shelf-manager
326
        list(creator.iter_shelvable())
0.12.23 by Aaron Bentley
Fix up unshelve some more
327
        creator.shelve_creation('foo-id')
0.12.29 by Aaron Bentley
Update failing tests
328
        shelf_file = open('shelf-file', 'w+b')
329
        try:
0.12.61 by Aaron Bentley
Stop assigning result of write_shelf
330
            creator.write_shelf(shelf_file)
0.12.29 by Aaron Bentley
Update failing tests
331
            creator.transform()
332
            shelf_file.seek(0)
0.12.34 by Aaron Bentley
merge with unshelve
333
            unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
0.12.66 by Aaron Bentley
Merge with unshelve
334
            unshelver.make_merger().do_merge()
0.12.29 by Aaron Bentley
Update failing tests
335
            self.assertFileEqual('bar', 'tree/foo')
336
        finally:
337
            shelf_file.close()
0.12.26 by Aaron Bentley
Use correct base for shelving
338
0.15.23 by Aaron Bentley
Use correct tree for desrializing transform
339
    def test_unshelve_changed(self):
340
        tree = self.make_branch_and_tree('tree')
341
        tree.lock_write()
342
        self.addCleanup(tree.unlock)
343
        self.build_tree_contents([('tree/foo', 'a\nb\nc\n')])
344
        tree.add('foo', 'foo-id')
345
        tree.commit('first commit')
346
        self.build_tree_contents([('tree/foo', 'a\nb\nd\n')])
347
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
348
        self.addCleanup(creator.finalize)
0.12.73 by Aaron Bentley
Merge unshelve into shelf-manager
349
        list(creator.iter_shelvable())
0.15.23 by Aaron Bentley
Use correct tree for desrializing transform
350
        creator.shelve_lines('foo-id', ['a\n', 'b\n', 'c\n'])
0.12.57 by Aaron Bentley
Update for new Shelf API
351
        shelf_file = open('shelf', 'w+b')
352
        self.addCleanup(shelf_file.close)
353
        creator.write_shelf(shelf_file)
0.15.23 by Aaron Bentley
Use correct tree for desrializing transform
354
        creator.transform()
355
        self.build_tree_contents([('tree/foo', 'z\na\nb\nc\n')])
0.12.57 by Aaron Bentley
Update for new Shelf API
356
        shelf_file.seek(0)
357
        unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
0.15.31 by Aaron Bentley
Remove 'unshelve' method, test make_merger
358
        unshelver.make_merger().do_merge()
0.15.23 by Aaron Bentley
Use correct tree for desrializing transform
359
        self.assertFileEqual('z\na\nb\nd\n', 'tree/foo')
360
3981.1.1 by Robert Collins
Fix bug 319790 - unshelve of deleted paths failing.
361
    def test_unshelve_deleted(self):
362
        tree = self.make_branch_and_tree('tree')
363
        tree.lock_write()
364
        self.addCleanup(tree.unlock)
365
        self.build_tree_contents([('tree/foo/',), ('tree/foo/bar', 'baz')])
366
        tree.add(['foo', 'foo/bar'], ['foo-id', 'bar-id'])
367
        tree.commit('Added file and directory')
368
        tree.unversion(['foo-id', 'bar-id'])
369
        os.unlink('tree/foo/bar')
370
        os.rmdir('tree/foo')
371
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
372
        list(creator.iter_shelvable())
373
        creator.shelve_deletion('foo-id')
374
        creator.shelve_deletion('bar-id')
375
        shelf_file = open('shelf', 'w+b')
376
        self.addCleanup(shelf_file.close)
377
        creator.write_shelf(shelf_file)
378
        creator.transform()
379
        creator.finalize()
380
        # validate the test setup
381
        self.assertTrue('foo-id' in tree)
382
        self.assertTrue('bar-id' in tree)
383
        self.assertFileEqual('baz', 'tree/foo/bar')
384
        shelf_file.seek(0)
385
        unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
386
        unshelver.make_merger().do_merge()
387
        self.assertFalse('foo-id' in tree)
388
        self.assertFalse('bar-id' in tree)
389
0.12.26 by Aaron Bentley
Use correct base for shelving
390
    def test_unshelve_base(self):
391
        tree = self.make_branch_and_tree('tree')
392
        tree.lock_write()
393
        self.addCleanup(tree.unlock)
394
        tree.commit('rev1', rev_id='rev1')
0.15.5 by Aaron Bentley
Rename to shelf
395
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
0.12.59 by Aaron Bentley
Fix locking bugs in tests
396
        self.addCleanup(creator.finalize)
0.12.42 by Aaron Bentley
Get shelf from tree
397
        manager = tree.get_shelf_manager()
0.12.29 by Aaron Bentley
Update failing tests
398
        shelf_id, shelf_file = manager.new_shelf()
399
        try:
0.12.61 by Aaron Bentley
Stop assigning result of write_shelf
400
            creator.write_shelf(shelf_file)
0.12.29 by Aaron Bentley
Update failing tests
401
        finally:
402
            shelf_file.close()
0.12.26 by Aaron Bentley
Use correct base for shelving
403
        tree.commit('rev2', rev_id='rev2')
0.12.29 by Aaron Bentley
Update failing tests
404
        shelf_file = manager.read_shelf(1)
0.12.59 by Aaron Bentley
Fix locking bugs in tests
405
        self.addCleanup(shelf_file.close)
406
        unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
407
        self.addCleanup(unshelver.finalize)
0.12.26 by Aaron Bentley
Use correct base for shelving
408
        self.assertEqual('rev1', unshelver.base_tree.get_revision_id())
0.12.27 by Aaron Bentley
Implement shelf manager
409
0.15.41 by Aaron Bentley
Replace assert with proper error handling
410
    def test_unshelve_serialization(self):
411
        tree = self.make_branch_and_tree('.')
412
        self.build_tree_contents([('shelf', EMPTY_SHELF)])
0.12.76 by Aaron Bentley
Convert failing tests
413
        shelf_file = open('shelf', 'rb')
414
        self.addCleanup(shelf_file.close)
415
        unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
0.15.41 by Aaron Bentley
Replace assert with proper error handling
416
417
    def test_corrupt_shelf(self):
418
        tree = self.make_branch_and_tree('.')
419
        self.build_tree_contents([('shelf', EMPTY_SHELF.replace('metadata',
420
                                                                'foo'))])
0.12.76 by Aaron Bentley
Convert failing tests
421
        shelf_file = open('shelf', 'rb')
422
        self.addCleanup(shelf_file.close)
0.15.41 by Aaron Bentley
Replace assert with proper error handling
423
        e = self.assertRaises(errors.ShelfCorrupt,
424
                              shelf.Unshelver.from_tree_and_shelf, tree,
0.12.76 by Aaron Bentley
Convert failing tests
425
                              shelf_file)
0.15.41 by Aaron Bentley
Replace assert with proper error handling
426
        self.assertEqual('Shelf corrupt.', str(e))
0.12.75 by Aaron Bentley
Merge unshelve into shelf-manager
427
0.12.27 by Aaron Bentley
Implement shelf manager
428
429
class TestShelfManager(tests.TestCaseWithTransport):
430
0.12.42 by Aaron Bentley
Get shelf from tree
431
    def test_get_shelf_manager(self):
0.12.27 by Aaron Bentley
Implement shelf manager
432
        tree = self.make_branch_and_tree('.')
0.12.42 by Aaron Bentley
Get shelf from tree
433
        manager = tree.get_shelf_manager()
0.12.41 by Aaron Bentley
Change shelf to use WT control dir for shelves
434
        self.assertEqual(tree._transport.base + 'shelf/',
0.12.27 by Aaron Bentley
Implement shelf manager
435
                         manager.transport.base)
436
437
    def get_manager(self):
0.12.42 by Aaron Bentley
Get shelf from tree
438
        return self.make_branch_and_tree('.').get_shelf_manager()
0.12.27 by Aaron Bentley
Implement shelf manager
439
0.12.77 by Aaron Bentley
Use names of the form shelf-5 for shelves
440
    def test_get_shelf_filename(self):
441
        tree = self.make_branch_and_tree('.')
442
        manager = tree.get_shelf_manager()
443
        self.assertEqual('shelf-1', manager.get_shelf_filename(1))
444
445
    def test_get_shelf_ids(self):
446
        tree = self.make_branch_and_tree('.')
447
        manager = tree.get_shelf_manager()
448
        self.assertEqual([1, 3], manager.get_shelf_ids(
449
                         ['shelf-1', 'shelf-02', 'shelf-3']))
450
0.12.27 by Aaron Bentley
Implement shelf manager
451
    def test_new_shelf(self):
452
        manager = self.get_manager()
453
        shelf_id, shelf_file = manager.new_shelf()
454
        shelf_file.close()
455
        self.assertEqual(1, shelf_id)
456
        shelf_id, shelf_file = manager.new_shelf()
457
        shelf_file.close()
458
        self.assertEqual(2, shelf_id)
459
        manager.delete_shelf(1)
460
        shelf_id, shelf_file = manager.new_shelf()
461
        shelf_file.close()
462
        self.assertEqual(3, shelf_id)
463
464
    def test_active_shelves(self):
465
        manager = self.get_manager()
466
        self.assertEqual([], manager.active_shelves())
467
        shelf_id, shelf_file = manager.new_shelf()
468
        shelf_file.close()
469
        self.assertEqual([1], manager.active_shelves())
470
471
    def test_delete_shelf(self):
472
        manager = self.get_manager()
473
        shelf_id, shelf_file = manager.new_shelf()
474
        shelf_file.close()
475
        self.assertEqual([1], manager.active_shelves())
476
        manager.delete_shelf(1)
477
        self.assertEqual([], manager.active_shelves())
478
479
    def test_last_shelf(self):
480
        manager = self.get_manager()
481
        self.assertIs(None, manager.last_shelf())
482
        shelf_id, shelf_file = manager.new_shelf()
483
        shelf_file.close()
484
        self.assertEqual(1, manager.last_shelf())
485
486
    def test_read_shelf(self):
487
        manager = self.get_manager()
488
        shelf_id, shelf_file = manager.new_shelf()
489
        try:
490
            shelf_file.write('foo')
491
        finally:
492
            shelf_file.close()
493
        shelf_id, shelf_file = manager.new_shelf()
494
        try:
495
            shelf_file.write('bar')
496
        finally:
497
            shelf_file.close()
498
        shelf_file = manager.read_shelf(1)
499
        try:
500
            self.assertEqual('foo', shelf_file.read())
501
        finally:
502
            shelf_file.close()
503
        shelf_file = manager.read_shelf(2)
504
        try:
505
            self.assertEqual('bar', shelf_file.read())
506
        finally:
507
            shelf_file.close()
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
508
0.12.50 by Aaron Bentley
Improve error handling for non-existant shelf-ids
509
    def test_read_non_existant(self):
510
        manager = self.get_manager()
0.12.68 by Aaron Bentley
Update docs, move items to proper files.
511
        e = self.assertRaises(errors.NoSuchShelfId, manager.read_shelf, 1)
0.12.50 by Aaron Bentley
Improve error handling for non-existant shelf-ids
512
        self.assertEqual('No changes are shelved with id "1".', str(e))
513
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
514
    def test_shelve_changes(self):
515
        tree = self.make_branch_and_tree('tree')
0.12.44 by Aaron Bentley
Give manager responsibility for applying transform
516
        tree.commit('no-change commit')
517
        tree.lock_write()
518
        self.addCleanup(tree.unlock)
519
        self.build_tree_contents([('tree/foo', 'bar')])
520
        self.assertFileEqual('bar', 'tree/foo')
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
521
        tree.add('foo', 'foo-id')
522
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
523
        self.addCleanup(creator.finalize)
0.12.74 by Aaron Bentley
Update to use iter_shelvable
524
        list(creator.iter_shelvable())
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
525
        creator.shelve_creation('foo-id')
526
        shelf_manager = tree.get_shelf_manager()
527
        shelf_id = shelf_manager.shelve_changes(creator)
0.12.44 by Aaron Bentley
Give manager responsibility for applying transform
528
        self.failIfExists('tree/foo')
0.12.43 by Aaron Bentley
Make ShelfManager consume ShelfCreator and produce Unshelver
529
        unshelver = shelf_manager.get_unshelver(shelf_id)
0.12.67 by Aaron Bentley
Update for new Unshelver API
530
        unshelver.make_merger().do_merge()
0.12.44 by Aaron Bentley
Give manager responsibility for applying transform
531
        self.assertFileEqual('bar', 'tree/foo')
0.16.112 by Aaron Bentley
Add tests
532
533
    def test_get_metadata(self):
534
        tree = self.make_branch_and_tree('.')
535
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
536
        shelf_manager = tree.get_shelf_manager()
537
        shelf_id = shelf_manager.shelve_changes(creator, 'foo')
538
        metadata = shelf_manager.get_metadata(shelf_id)
539
        self.assertEqual('foo', metadata['message'])
540
        self.assertEqual('null:', metadata['revision_id'])