/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_shelf.py

  • Committer: Martin Pool
  • Date: 2007-10-03 08:06:44 UTC
  • mto: This revision was merged to the branch mainline in revision 2901.
  • Revision ID: mbp@sourcefrog.net-20071003080644-oivy0gkg98sex0ed
Avoid internal error tracebacks on failure to lock on readonly transport (#129701).

Add new LockFailed, which doesn't imply that we failed to get it because of
contention.  Raise this if we fail to create the pending or lock directories
because of Transport errors.

UnlockableTransport is not an internal error.

ReadOnlyLockError has a message which didn't match its name or usage; it's now
deprecated and callers are updated to use LockFailed which is more appropriate.

Add zero_ninetytwo deprecation symbol.

Unify assertMatchesRe with TestCase.assertContainsRe.

When the constructor is deprecated, just say that the class is deprecated, not
the __init__ method - this works better with applyDeprecated in tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2008, 2009, 2010 Canonical Ltd
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
import os
18
 
 
19
 
from bzrlib import (
20
 
    errors,
21
 
    osutils,
22
 
    pack,
23
 
    shelf,
24
 
    tests,
25
 
    transform,
26
 
    workingtree,
27
 
    )
28
 
 
29
 
 
30
 
EMPTY_SHELF = ("Bazaar pack format 1 (introduced in 0.18)\n"
31
 
               "B23\n"
32
 
               "metadata\n\n"
33
 
               "d11:revision_id5:null:e"
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
 
 
41
 
class TestPrepareShelf(tests.TestCaseWithTransport):
42
 
 
43
 
    def prepare_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')
49
 
        tree.lock_tree_write()
50
 
        self.addCleanup(tree.unlock)
51
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
52
 
        self.addCleanup(creator.finalize)
53
 
        self.assertEqual([('rename', 'foo-id', 'foo', 'bar')],
54
 
                          list(creator.iter_shelvable()))
55
 
        return creator
56
 
 
57
 
    def check_shelve_rename(self, creator):
58
 
        work_trans_id = creator.work_transform.trans_id_file_id('foo-id')
59
 
        self.assertEqual('foo', creator.work_transform.final_name(
60
 
                         work_trans_id))
61
 
        shelf_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
62
 
        self.assertEqual('bar', creator.shelf_transform.final_name(
63
 
                         shelf_trans_id))
64
 
 
65
 
    def test_shelve_rename(self):
66
 
        creator = self.prepare_shelve_rename()
67
 
        creator.shelve_rename('foo-id')
68
 
        self.check_shelve_rename(creator)
69
 
 
70
 
    def test_shelve_change_handles_rename(self):
71
 
        creator = self.prepare_shelve_rename()
72
 
        creator.shelve_change(('rename', 'foo-id', 'foo', 'bar'))
73
 
        self.check_shelve_rename(creator)
74
 
 
75
 
    def prepare_shelve_move(self):
76
 
        tree = self.make_branch_and_tree('.')
77
 
        self.build_tree(['foo/', 'bar/', 'foo/baz'])
78
 
        tree.add(['foo', 'bar', 'foo/baz'], ['foo-id', 'bar-id', 'baz-id'])
79
 
        tree.commit('foo')
80
 
        tree.rename_one('foo/baz', 'bar/baz')
81
 
        tree.lock_tree_write()
82
 
        self.addCleanup(tree.unlock)
83
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
84
 
        self.addCleanup(creator.finalize)
85
 
        self.assertEqual([('rename', 'baz-id', 'foo/baz', 'bar/baz')],
86
 
                         list(creator.iter_shelvable()))
87
 
        return creator, tree
88
 
 
89
 
    def check_shelve_move(self, creator, tree):
90
 
        work_trans_id = creator.work_transform.trans_id_file_id('baz-id')
91
 
        work_foo = creator.work_transform.trans_id_file_id('foo-id')
92
 
        self.assertEqual(work_foo, creator.work_transform.final_parent(
93
 
                         work_trans_id))
94
 
        shelf_trans_id = creator.shelf_transform.trans_id_file_id('baz-id')
95
 
        shelf_bar = creator.shelf_transform.trans_id_file_id('bar-id')
96
 
        self.assertEqual(shelf_bar, creator.shelf_transform.final_parent(
97
 
                         shelf_trans_id))
98
 
        creator.transform()
99
 
        self.assertEqual('foo/baz', tree.id2path('baz-id'))
100
 
 
101
 
    def test_shelve_move(self):
102
 
        creator, tree = self.prepare_shelve_move()
103
 
        creator.shelve_rename('baz-id')
104
 
        self.check_shelve_move(creator, tree)
105
 
 
106
 
    def test_shelve_change_handles_move(self):
107
 
        creator, tree = self.prepare_shelve_move()
108
 
        creator.shelve_change(('rename', 'baz-id', 'foo/baz', 'bar/baz'))
109
 
        self.check_shelve_move(creator, tree)
110
 
 
111
 
    def test_shelve_changed_root_id(self):
112
 
        tree = self.make_branch_and_tree('.')
113
 
        self.build_tree(['foo'])
114
 
        tree.set_root_id('first-root-id')
115
 
        tree.add(['foo'], ['foo-id'])
116
 
        tree.commit('foo')
117
 
        tree.set_root_id('second-root-id')
118
 
        tree.lock_tree_write()
119
 
        self.addCleanup(tree.unlock)
120
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
121
 
        self.addCleanup(creator.finalize)
122
 
        self.expectFailure('shelf doesn\'t support shelving root changes yet',
123
 
            self.assertEqual, [
124
 
                ('delete file', 'first-root-id', 'directory', ''),
125
 
                ('add file', 'second-root-id', 'directory', ''),
126
 
                ('rename', 'foo-id', u'foo', u'foo'),
127
 
                ], list(creator.iter_shelvable()))
128
 
 
129
 
        self.assertEqual([('delete file', 'first-root-id', 'directory', ''),
130
 
                          ('add file', 'second-root-id', 'directory', ''),
131
 
                          ('rename', 'foo-id', u'foo', u'foo'),
132
 
                         ], list(creator.iter_shelvable()))
133
 
 
134
 
    def assertShelvedFileEqual(self, expected_content, creator, file_id):
135
 
        s_trans_id = creator.shelf_transform.trans_id_file_id(file_id)
136
 
        shelf_file = creator.shelf_transform._limbo_name(s_trans_id)
137
 
        self.assertFileEqual(expected_content, shelf_file)
138
 
 
139
 
    def prepare_content_change(self):
140
 
        tree = self.make_branch_and_tree('.')
141
 
        tree.lock_write()
142
 
        self.addCleanup(tree.unlock)
143
 
        self.build_tree_contents([('foo', 'a\n')])
144
 
        tree.add('foo', 'foo-id')
145
 
        tree.commit('Committed foo')
146
 
        self.build_tree_contents([('foo', 'b\na\nc\n')])
147
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
148
 
        self.addCleanup(creator.finalize)
149
 
        return creator
150
 
 
151
 
    def test_shelve_content_change(self):
152
 
        creator = self.prepare_content_change()
153
 
        self.assertEqual([('modify text', 'foo-id')],
154
 
                         list(creator.iter_shelvable()))
155
 
        creator.shelve_lines('foo-id', ['a\n', 'c\n'])
156
 
        creator.transform()
157
 
        self.assertFileEqual('a\nc\n', 'foo')
158
 
        self.assertShelvedFileEqual('b\na\n', creator, 'foo-id')
159
 
 
160
 
    def test_shelve_change_handles_modify_text(self):
161
 
        creator = self.prepare_content_change()
162
 
        creator.shelve_change(('modify text', 'foo-id'))
163
 
        creator.transform()
164
 
        self.assertFileEqual('a\n', 'foo')
165
 
        self.assertShelvedFileEqual('b\na\nc\n', creator, 'foo-id')
166
 
 
167
 
    def test_shelve_all(self):
168
 
        creator = self.prepare_content_change()
169
 
        creator.shelve_all()
170
 
        creator.transform()
171
 
        self.assertFileEqual('a\n', 'foo')
172
 
        self.assertShelvedFileEqual('b\na\nc\n', creator, 'foo-id')
173
 
 
174
 
    def prepare_shelve_creation(self):
175
 
        tree = self.make_branch_and_tree('.')
176
 
        tree.lock_write()
177
 
        self.addCleanup(tree.unlock)
178
 
        tree.commit('Empty tree')
179
 
        self.build_tree_contents([('foo', 'a\n'), ('bar/',)])
180
 
        tree.add(['foo', 'bar'], ['foo-id', 'bar-id'])
181
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
182
 
        self.addCleanup(creator.finalize)
183
 
        self.assertEqual([('add file', 'bar-id', 'directory', 'bar'),
184
 
                          ('add file', 'foo-id', 'file', 'foo')],
185
 
                          sorted(list(creator.iter_shelvable())))
186
 
        return creator, tree
187
 
 
188
 
    def check_shelve_creation(self, creator, tree):
189
 
        self.assertRaises(StopIteration,
190
 
                          tree.iter_entries_by_dir(['foo-id']).next)
191
 
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
192
 
        self.assertEqual('foo-id',
193
 
                         creator.shelf_transform.final_file_id(s_trans_id))
194
 
        self.failIfExists('foo')
195
 
        self.failIfExists('bar')
196
 
        self.assertShelvedFileEqual('a\n', creator, 'foo-id')
197
 
        s_bar_trans_id = creator.shelf_transform.trans_id_file_id('bar-id')
198
 
        self.assertEqual('directory',
199
 
            creator.shelf_transform.final_kind(s_bar_trans_id))
200
 
 
201
 
    def test_shelve_creation(self):
202
 
        creator, tree = self.prepare_shelve_creation()
203
 
        creator.shelve_creation('foo-id')
204
 
        creator.shelve_creation('bar-id')
205
 
        creator.transform()
206
 
        self.check_shelve_creation(creator, tree)
207
 
 
208
 
    def test_shelve_change_handles_creation(self):
209
 
        creator, tree = self.prepare_shelve_creation()
210
 
        creator.shelve_change(('add file', 'foo-id', 'file', 'foo'))
211
 
        creator.shelve_change(('add file', 'bar-id', 'directory', 'bar'))
212
 
        creator.transform()
213
 
        self.check_shelve_creation(creator, tree)
214
 
 
215
 
    def _test_shelve_symlink_creation(self, link_name, link_target,
216
 
                                      shelve_change=False):
217
 
        self.requireFeature(tests.SymlinkFeature)
218
 
        tree = self.make_branch_and_tree('.')
219
 
        tree.lock_write()
220
 
        self.addCleanup(tree.unlock)
221
 
        tree.commit('Empty tree')
222
 
        os.symlink(link_target, link_name)
223
 
        tree.add(link_name, 'foo-id')
224
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
225
 
        self.addCleanup(creator.finalize)
226
 
        self.assertEqual([('add file', 'foo-id', 'symlink', link_name)],
227
 
                         list(creator.iter_shelvable()))
228
 
        if shelve_change:
229
 
            creator.shelve_change(('add file', 'foo-id', 'symlink', link_name))
230
 
        else:
231
 
            creator.shelve_creation('foo-id')
232
 
        creator.transform()
233
 
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
234
 
        self.failIfExists(link_name)
235
 
        limbo_name = creator.shelf_transform._limbo_name(s_trans_id)
236
 
        self.assertEqual(link_target, osutils.readlink(limbo_name))
237
 
        ptree = creator.shelf_transform.get_preview_tree()
238
 
        self.assertEqual(link_target, ptree.get_symlink_target('foo-id'))
239
 
 
240
 
    def test_shelve_symlink_creation(self):
241
 
        self._test_shelve_symlink_creation('foo', 'bar')
242
 
 
243
 
    def test_shelve_unicode_symlink_creation(self):
244
 
        self.requireFeature(tests.UnicodeFilenameFeature)
245
 
        self._test_shelve_symlink_creation(u'fo\N{Euro Sign}o',
246
 
                                           u'b\N{Euro Sign}ar')
247
 
 
248
 
    def test_shelve_change_handles_symlink_creation(self):
249
 
        self._test_shelve_symlink_creation('foo', 'bar', shelve_change=True)
250
 
 
251
 
    def _test_shelve_symlink_target_change(self, link_name,
252
 
                                           old_target, new_target,
253
 
                                           shelve_change=False):
254
 
        self.requireFeature(tests.SymlinkFeature)
255
 
        tree = self.make_branch_and_tree('.')
256
 
        tree.lock_write()
257
 
        self.addCleanup(tree.unlock)
258
 
        os.symlink(old_target, link_name)
259
 
        tree.add(link_name, 'foo-id')
260
 
        tree.commit("commit symlink")
261
 
        os.unlink(link_name)
262
 
        os.symlink(new_target, link_name)
263
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
264
 
        self.addCleanup(creator.finalize)
265
 
        self.assertEqual([('modify target', 'foo-id', link_name,
266
 
                           old_target, new_target)],
267
 
                         list(creator.iter_shelvable()))
268
 
        if shelve_change:
269
 
            creator.shelve_change(('modify target', 'foo-id', link_name,
270
 
                                   old_target, new_target))
271
 
        else:
272
 
            creator.shelve_modify_target('foo-id')
273
 
        creator.transform()
274
 
        self.assertEqual(old_target, osutils.readlink(link_name))
275
 
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
276
 
        limbo_name = creator.shelf_transform._limbo_name(s_trans_id)
277
 
        self.assertEqual(new_target, osutils.readlink(limbo_name))
278
 
        ptree = creator.shelf_transform.get_preview_tree()
279
 
        self.assertEqual(new_target, ptree.get_symlink_target('foo-id'))
280
 
 
281
 
    def test_shelve_symlink_target_change(self):
282
 
        self._test_shelve_symlink_target_change('foo', 'bar', 'baz')
283
 
 
284
 
    def test_shelve_unicode_symlink_target_change(self):
285
 
        self.requireFeature(tests.UnicodeFilenameFeature)
286
 
        self._test_shelve_symlink_target_change(
287
 
            u'fo\N{Euro Sign}o', u'b\N{Euro Sign}ar', u'b\N{Euro Sign}az')
288
 
 
289
 
    def test_shelve_change_handles_symlink_target_change(self):
290
 
        self._test_shelve_symlink_target_change('foo', 'bar', 'baz',
291
 
                                                shelve_change=True)
292
 
 
293
 
    def test_shelve_creation_no_contents(self):
294
 
        tree = self.make_branch_and_tree('.')
295
 
        tree.lock_write()
296
 
        self.addCleanup(tree.unlock)
297
 
        tree.commit('Empty tree')
298
 
        self.build_tree(['foo'])
299
 
        tree.add('foo', 'foo-id')
300
 
        os.unlink('foo')
301
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
302
 
        self.addCleanup(creator.finalize)
303
 
        self.assertEqual([('add file', 'foo-id', None, 'foo')],
304
 
                         sorted(list(creator.iter_shelvable())))
305
 
        creator.shelve_creation('foo-id')
306
 
        creator.transform()
307
 
        self.assertRaises(StopIteration,
308
 
                          tree.iter_entries_by_dir(['foo-id']).next)
309
 
        self.assertShelvedFileEqual('', creator, 'foo-id')
310
 
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
311
 
        self.assertEqual('foo-id',
312
 
                         creator.shelf_transform.final_file_id(s_trans_id))
313
 
        self.failIfExists('foo')
314
 
 
315
 
    def prepare_shelve_deletion(self):
316
 
        tree = self.make_branch_and_tree('tree')
317
 
        tree.lock_write()
318
 
        self.addCleanup(tree.unlock)
319
 
        self.build_tree_contents([('tree/foo/',), ('tree/foo/bar', 'baz')])
320
 
        tree.add(['foo', 'foo/bar'], ['foo-id', 'bar-id'])
321
 
        tree.commit('Added file and directory')
322
 
        tree.unversion(['foo-id', 'bar-id'])
323
 
        os.unlink('tree/foo/bar')
324
 
        os.rmdir('tree/foo')
325
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
326
 
        self.addCleanup(creator.finalize)
327
 
        self.assertEqual([('delete file', 'bar-id', 'file', 'foo/bar'),
328
 
                          ('delete file', 'foo-id', 'directory', 'foo')],
329
 
                          sorted(list(creator.iter_shelvable())))
330
 
        return creator, tree
331
 
 
332
 
    def check_shelve_deletion(self, tree):
333
 
        self.assertTrue('foo-id' in tree)
334
 
        self.assertTrue('bar-id' in tree)
335
 
        self.assertFileEqual('baz', 'tree/foo/bar')
336
 
 
337
 
    def test_shelve_deletion(self):
338
 
        creator, tree = self.prepare_shelve_deletion()
339
 
        creator.shelve_deletion('foo-id')
340
 
        creator.shelve_deletion('bar-id')
341
 
        creator.transform()
342
 
        self.check_shelve_deletion(tree)
343
 
 
344
 
    def test_shelve_change_handles_deletion(self):
345
 
        creator, tree = self.prepare_shelve_deletion()
346
 
        creator.shelve_change(('delete file', 'foo-id', 'directory', 'foo'))
347
 
        creator.shelve_change(('delete file', 'bar-id', 'file', 'foo/bar'))
348
 
        creator.transform()
349
 
        self.check_shelve_deletion(tree)
350
 
 
351
 
    def test_shelve_delete_contents(self):
352
 
        tree = self.make_branch_and_tree('tree')
353
 
        self.build_tree(['tree/foo',])
354
 
        tree.add('foo', 'foo-id')
355
 
        tree.commit('Added file and directory')
356
 
        os.unlink('tree/foo')
357
 
        tree.lock_tree_write()
358
 
        self.addCleanup(tree.unlock)
359
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
360
 
        self.addCleanup(creator.finalize)
361
 
        self.assertEqual([('delete file', 'foo-id', 'file', 'foo')],
362
 
                         sorted(list(creator.iter_shelvable())))
363
 
        creator.shelve_deletion('foo-id')
364
 
        creator.transform()
365
 
        self.failUnlessExists('tree/foo')
366
 
 
367
 
    def prepare_shelve_change_kind(self):
368
 
        tree = self.make_branch_and_tree('tree')
369
 
        self.build_tree_contents([('tree/foo', 'bar')])
370
 
        tree.add('foo', 'foo-id')
371
 
        tree.commit('Added file and directory')
372
 
        os.unlink('tree/foo')
373
 
        os.mkdir('tree/foo')
374
 
        tree.lock_tree_write()
375
 
        self.addCleanup(tree.unlock)
376
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
377
 
        self.addCleanup(creator.finalize)
378
 
        self.assertEqual([('change kind', 'foo-id', 'file', 'directory',
379
 
                           'foo')], sorted(list(creator.iter_shelvable())))
380
 
        return creator
381
 
 
382
 
    def check_shelve_change_kind(self, creator):
383
 
        self.assertFileEqual('bar', 'tree/foo')
384
 
        s_trans_id = creator.shelf_transform.trans_id_file_id('foo-id')
385
 
        self.assertEqual('directory',
386
 
                         creator.shelf_transform._new_contents[s_trans_id])
387
 
 
388
 
    def test_shelve_change_kind(self):
389
 
        creator = self.prepare_shelve_change_kind()
390
 
        creator.shelve_content_change('foo-id')
391
 
        creator.transform()
392
 
        self.check_shelve_change_kind(creator)
393
 
 
394
 
    def test_shelve_change_handles_change_kind(self):
395
 
        creator = self.prepare_shelve_change_kind()
396
 
        creator.shelve_change(('change kind', 'foo-id', 'file', 'directory',
397
 
                               'foo'))
398
 
        creator.transform()
399
 
        self.check_shelve_change_kind(creator)
400
 
 
401
 
    def test_shelve_change_unknown_change(self):
402
 
        tree = self.make_branch_and_tree('tree')
403
 
        tree.lock_tree_write()
404
 
        self.addCleanup(tree.unlock)
405
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
406
 
        self.addCleanup(creator.finalize)
407
 
        e = self.assertRaises(ValueError, creator.shelve_change, ('unknown',))
408
 
        self.assertEqual('Unknown change kind: "unknown"', str(e))
409
 
 
410
 
    def test_shelve_unversion(self):
411
 
        tree = self.make_branch_and_tree('tree')
412
 
        self.build_tree(['tree/foo',])
413
 
        tree.add('foo', 'foo-id')
414
 
        tree.commit('Added file and directory')
415
 
        tree.unversion(['foo-id'])
416
 
        tree.lock_tree_write()
417
 
        self.addCleanup(tree.unlock)
418
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
419
 
        self.addCleanup(creator.finalize)
420
 
        self.assertEqual([('delete file', 'foo-id', 'file', 'foo')],
421
 
                         sorted(list(creator.iter_shelvable())))
422
 
        creator.shelve_deletion('foo-id')
423
 
        creator.transform()
424
 
        self.failUnlessExists('tree/foo')
425
 
 
426
 
    def test_shelve_serialization(self):
427
 
        tree = self.make_branch_and_tree('.')
428
 
        tree.lock_tree_write()
429
 
        self.addCleanup(tree.unlock)
430
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
431
 
        self.addCleanup(creator.finalize)
432
 
        shelf_file = open('shelf', 'wb')
433
 
        self.addCleanup(shelf_file.close)
434
 
        try:
435
 
            creator.write_shelf(shelf_file)
436
 
        finally:
437
 
            shelf_file.close()
438
 
        self.assertFileEqual(EMPTY_SHELF, 'shelf')
439
 
 
440
 
    def test_write_shelf(self):
441
 
        tree = self.make_branch_and_tree('tree')
442
 
        self.build_tree(['tree/foo'])
443
 
        tree.add('foo', 'foo-id')
444
 
        tree.lock_tree_write()
445
 
        self.addCleanup(tree.unlock)
446
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
447
 
        self.addCleanup(creator.finalize)
448
 
        list(creator.iter_shelvable())
449
 
        creator.shelve_creation('foo-id')
450
 
        shelf_file = open('shelf', 'wb')
451
 
        try:
452
 
            creator.write_shelf(shelf_file)
453
 
        finally:
454
 
            shelf_file.close()
455
 
        parser = pack.ContainerPushParser()
456
 
        shelf_file = open('shelf', 'rb')
457
 
        try:
458
 
            parser.accept_bytes(shelf_file.read())
459
 
        finally:
460
 
            shelf_file.close()
461
 
        tt = transform.TransformPreview(tree)
462
 
        self.addCleanup(tt.finalize)
463
 
        records = iter(parser.read_pending_records())
464
 
        #skip revision-id
465
 
        records.next()
466
 
        tt.deserialize(records)
467
 
 
468
 
    def test_shelve_unversioned(self):
469
 
        tree = self.make_branch_and_tree('tree')
470
 
        tree.lock_tree_write()
471
 
        try:
472
 
            self.assertRaises(errors.PathsNotVersionedError,
473
 
                              shelf.ShelfCreator, tree, tree.basis_tree(), ['foo'])
474
 
        finally:
475
 
            tree.unlock()
476
 
        # We should be able to lock/unlock the tree if ShelfCreator cleaned
477
 
        # after itself.
478
 
        wt = workingtree.WorkingTree.open('tree')
479
 
        wt.lock_tree_write()
480
 
        wt.unlock()
481
 
        # And a second tentative should raise the same error (no
482
 
        # limbo/pending_deletion leftovers).
483
 
        tree.lock_tree_write()
484
 
        try:
485
 
            self.assertRaises(errors.PathsNotVersionedError,
486
 
                              shelf.ShelfCreator, tree, tree.basis_tree(), ['foo'])
487
 
        finally:
488
 
            tree.unlock()
489
 
 
490
 
    def test_shelve_skips_added_root(self):
491
 
        """Skip adds of the root when iterating through shelvable changes."""
492
 
        tree = self.make_branch_and_tree('tree')
493
 
        tree.lock_tree_write()
494
 
        self.addCleanup(tree.unlock)
495
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
496
 
        self.addCleanup(creator.finalize)
497
 
        self.assertEqual([], list(creator.iter_shelvable()))
498
 
 
499
 
    def test_shelve_skips_added_root(self):
500
 
        """Skip adds of the root when iterating through shelvable changes."""
501
 
        tree = self.make_branch_and_tree('tree')
502
 
        tree.lock_tree_write()
503
 
        self.addCleanup(tree.unlock)
504
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
505
 
        self.addCleanup(creator.finalize)
506
 
        self.assertEqual([], list(creator.iter_shelvable()))
507
 
 
508
 
 
509
 
class TestUnshelver(tests.TestCaseWithTransport):
510
 
 
511
 
    def test_make_merger(self):
512
 
        tree = self.make_branch_and_tree('tree')
513
 
        tree.commit('first commit')
514
 
        self.build_tree_contents([('tree/foo', 'bar')])
515
 
        tree.lock_write()
516
 
        self.addCleanup(tree.unlock)
517
 
        tree.add('foo', 'foo-id')
518
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
519
 
        self.addCleanup(creator.finalize)
520
 
        list(creator.iter_shelvable())
521
 
        creator.shelve_creation('foo-id')
522
 
        shelf_file = open('shelf-file', 'w+b')
523
 
        try:
524
 
            creator.write_shelf(shelf_file)
525
 
            creator.transform()
526
 
            shelf_file.seek(0)
527
 
            unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
528
 
            unshelver.make_merger().do_merge()
529
 
            self.addCleanup(unshelver.finalize)
530
 
            self.assertFileEqual('bar', 'tree/foo')
531
 
        finally:
532
 
            shelf_file.close()
533
 
 
534
 
    def test_unshelve_changed(self):
535
 
        tree = self.make_branch_and_tree('tree')
536
 
        tree.lock_write()
537
 
        self.addCleanup(tree.unlock)
538
 
        self.build_tree_contents([('tree/foo', 'a\nb\nc\n')])
539
 
        tree.add('foo', 'foo-id')
540
 
        tree.commit('first commit')
541
 
        self.build_tree_contents([('tree/foo', 'a\nb\nd\n')])
542
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
543
 
        self.addCleanup(creator.finalize)
544
 
        list(creator.iter_shelvable())
545
 
        creator.shelve_lines('foo-id', ['a\n', 'b\n', 'c\n'])
546
 
        shelf_file = open('shelf', 'w+b')
547
 
        self.addCleanup(shelf_file.close)
548
 
        creator.write_shelf(shelf_file)
549
 
        creator.transform()
550
 
        self.build_tree_contents([('tree/foo', 'z\na\nb\nc\n')])
551
 
        shelf_file.seek(0)
552
 
        unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
553
 
        self.addCleanup(unshelver.finalize)
554
 
        unshelver.make_merger().do_merge()
555
 
        self.assertFileEqual('z\na\nb\nd\n', 'tree/foo')
556
 
 
557
 
    def test_unshelve_deleted(self):
558
 
        tree = self.make_branch_and_tree('tree')
559
 
        tree.lock_write()
560
 
        self.addCleanup(tree.unlock)
561
 
        self.build_tree_contents([('tree/foo/',), ('tree/foo/bar', 'baz')])
562
 
        tree.add(['foo', 'foo/bar'], ['foo-id', 'bar-id'])
563
 
        tree.commit('Added file and directory')
564
 
        tree.unversion(['foo-id', 'bar-id'])
565
 
        os.unlink('tree/foo/bar')
566
 
        os.rmdir('tree/foo')
567
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
568
 
        list(creator.iter_shelvable())
569
 
        creator.shelve_deletion('foo-id')
570
 
        creator.shelve_deletion('bar-id')
571
 
        shelf_file = open('shelf', 'w+b')
572
 
        self.addCleanup(shelf_file.close)
573
 
        creator.write_shelf(shelf_file)
574
 
        creator.transform()
575
 
        creator.finalize()
576
 
        # validate the test setup
577
 
        self.assertTrue('foo-id' in tree)
578
 
        self.assertTrue('bar-id' in tree)
579
 
        self.assertFileEqual('baz', 'tree/foo/bar')
580
 
        shelf_file.seek(0)
581
 
        unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
582
 
        self.addCleanup(unshelver.finalize)
583
 
        unshelver.make_merger().do_merge()
584
 
        self.assertFalse('foo-id' in tree)
585
 
        self.assertFalse('bar-id' in tree)
586
 
 
587
 
    def test_unshelve_base(self):
588
 
        tree = self.make_branch_and_tree('tree')
589
 
        tree.lock_write()
590
 
        self.addCleanup(tree.unlock)
591
 
        tree.commit('rev1', rev_id='rev1')
592
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
593
 
        self.addCleanup(creator.finalize)
594
 
        manager = tree.get_shelf_manager()
595
 
        shelf_id, shelf_file = manager.new_shelf()
596
 
        try:
597
 
            creator.write_shelf(shelf_file)
598
 
        finally:
599
 
            shelf_file.close()
600
 
        tree.commit('rev2', rev_id='rev2')
601
 
        shelf_file = manager.read_shelf(1)
602
 
        self.addCleanup(shelf_file.close)
603
 
        unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
604
 
        self.addCleanup(unshelver.finalize)
605
 
        self.assertEqual('rev1', unshelver.base_tree.get_revision_id())
606
 
 
607
 
    def test_unshelve_serialization(self):
608
 
        tree = self.make_branch_and_tree('.')
609
 
        self.build_tree_contents([('shelf', EMPTY_SHELF)])
610
 
        shelf_file = open('shelf', 'rb')
611
 
        self.addCleanup(shelf_file.close)
612
 
        unshelver = shelf.Unshelver.from_tree_and_shelf(tree, shelf_file)
613
 
        unshelver.finalize()
614
 
 
615
 
    def test_corrupt_shelf(self):
616
 
        tree = self.make_branch_and_tree('.')
617
 
        self.build_tree_contents([('shelf', EMPTY_SHELF.replace('metadata',
618
 
                                                                'foo'))])
619
 
        shelf_file = open('shelf', 'rb')
620
 
        self.addCleanup(shelf_file.close)
621
 
        e = self.assertRaises(errors.ShelfCorrupt,
622
 
                              shelf.Unshelver.from_tree_and_shelf, tree,
623
 
                              shelf_file)
624
 
        self.assertEqual('Shelf corrupt.', str(e))
625
 
 
626
 
 
627
 
class TestShelfManager(tests.TestCaseWithTransport):
628
 
 
629
 
    def test_get_shelf_manager(self):
630
 
        tree = self.make_branch_and_tree('.')
631
 
        manager = tree.get_shelf_manager()
632
 
        self.assertEqual(tree._transport.base + 'shelf/',
633
 
                         manager.transport.base)
634
 
 
635
 
    def get_manager(self):
636
 
        return self.make_branch_and_tree('.').get_shelf_manager()
637
 
 
638
 
    def test_get_shelf_filename(self):
639
 
        tree = self.make_branch_and_tree('.')
640
 
        manager = tree.get_shelf_manager()
641
 
        self.assertEqual('shelf-1', manager.get_shelf_filename(1))
642
 
 
643
 
    def test_get_shelf_ids(self):
644
 
        tree = self.make_branch_and_tree('.')
645
 
        manager = tree.get_shelf_manager()
646
 
        self.assertEqual([1, 3], manager.get_shelf_ids(
647
 
                         ['shelf-1', 'shelf-02', 'shelf-3']))
648
 
 
649
 
    def test_new_shelf(self):
650
 
        manager = self.get_manager()
651
 
        shelf_id, shelf_file = manager.new_shelf()
652
 
        shelf_file.close()
653
 
        self.assertEqual(1, shelf_id)
654
 
        shelf_id, shelf_file = manager.new_shelf()
655
 
        shelf_file.close()
656
 
        self.assertEqual(2, shelf_id)
657
 
        manager.delete_shelf(1)
658
 
        shelf_id, shelf_file = manager.new_shelf()
659
 
        shelf_file.close()
660
 
        self.assertEqual(3, shelf_id)
661
 
 
662
 
    def test_active_shelves(self):
663
 
        manager = self.get_manager()
664
 
        self.assertEqual([], manager.active_shelves())
665
 
        shelf_id, shelf_file = manager.new_shelf()
666
 
        shelf_file.close()
667
 
        self.assertEqual([1], manager.active_shelves())
668
 
 
669
 
    def test_delete_shelf(self):
670
 
        manager = self.get_manager()
671
 
        shelf_id, shelf_file = manager.new_shelf()
672
 
        shelf_file.close()
673
 
        self.assertEqual([1], manager.active_shelves())
674
 
        manager.delete_shelf(1)
675
 
        self.assertEqual([], manager.active_shelves())
676
 
 
677
 
    def test_last_shelf(self):
678
 
        manager = self.get_manager()
679
 
        self.assertIs(None, manager.last_shelf())
680
 
        shelf_id, shelf_file = manager.new_shelf()
681
 
        shelf_file.close()
682
 
        self.assertEqual(1, manager.last_shelf())
683
 
 
684
 
    def test_read_shelf(self):
685
 
        manager = self.get_manager()
686
 
        shelf_id, shelf_file = manager.new_shelf()
687
 
        try:
688
 
            shelf_file.write('foo')
689
 
        finally:
690
 
            shelf_file.close()
691
 
        shelf_id, shelf_file = manager.new_shelf()
692
 
        try:
693
 
            shelf_file.write('bar')
694
 
        finally:
695
 
            shelf_file.close()
696
 
        shelf_file = manager.read_shelf(1)
697
 
        try:
698
 
            self.assertEqual('foo', shelf_file.read())
699
 
        finally:
700
 
            shelf_file.close()
701
 
        shelf_file = manager.read_shelf(2)
702
 
        try:
703
 
            self.assertEqual('bar', shelf_file.read())
704
 
        finally:
705
 
            shelf_file.close()
706
 
 
707
 
    def test_read_non_existant(self):
708
 
        manager = self.get_manager()
709
 
        e = self.assertRaises(errors.NoSuchShelfId, manager.read_shelf, 1)
710
 
        self.assertEqual('No changes are shelved with id "1".', str(e))
711
 
 
712
 
    def test_shelve_changes(self):
713
 
        tree = self.make_branch_and_tree('tree')
714
 
        tree.commit('no-change commit')
715
 
        tree.lock_write()
716
 
        self.addCleanup(tree.unlock)
717
 
        self.build_tree_contents([('tree/foo', 'bar')])
718
 
        self.assertFileEqual('bar', 'tree/foo')
719
 
        tree.add('foo', 'foo-id')
720
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
721
 
        self.addCleanup(creator.finalize)
722
 
        list(creator.iter_shelvable())
723
 
        creator.shelve_creation('foo-id')
724
 
        shelf_manager = tree.get_shelf_manager()
725
 
        shelf_id = shelf_manager.shelve_changes(creator)
726
 
        self.failIfExists('tree/foo')
727
 
        unshelver = shelf_manager.get_unshelver(shelf_id)
728
 
        self.addCleanup(unshelver.finalize)
729
 
        unshelver.make_merger().do_merge()
730
 
        self.assertFileEqual('bar', 'tree/foo')
731
 
 
732
 
    def test_get_metadata(self):
733
 
        tree = self.make_branch_and_tree('.')
734
 
        tree.lock_tree_write()
735
 
        self.addCleanup(tree.unlock)
736
 
        creator = shelf.ShelfCreator(tree, tree.basis_tree())
737
 
        self.addCleanup(creator.finalize)
738
 
        shelf_manager = tree.get_shelf_manager()
739
 
        shelf_id = shelf_manager.shelve_changes(creator, 'foo')
740
 
        metadata = shelf_manager.get_metadata(shelf_id)
741
 
        self.assertEqual('foo', metadata['message'])
742
 
        self.assertEqual('null:', metadata['revision_id'])