/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: Canonical.com Patch Queue Manager
  • Date: 2009-07-20 08:56:45 UTC
  • mfrom: (4526.9.23 apply-inventory-delta)
  • Revision ID: pqm@pqm.ubuntu.com-20090720085645-54mtgybxua0yx6hw
(robertc) Add checks for inventory deltas which try to ensure that
        deltas that are not an exact fit are not applied. (Robert
        Collins, bug 397705, bug 367633)

Show diffs side-by-side

added added

removed removed

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