1
# Copyright (C) 2008-2011, 2016 Canonical Ltd
1
# Copyright (C) 2008 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
45
40
self.diff_writer = StringIO()
47
def expect(self, message, response):
48
self.expected.append((message, response))
42
def expect(self, prompt, response):
43
self.expected.append((prompt, response))
50
def prompt(self, message, choices, default):
45
def prompt(self, message):
52
expected_message, response = self.expected.pop(0)
47
prompt, response = self.expected.pop(0)
54
49
raise AssertionError('Unexpected prompt: %s' % message)
55
if message != expected_message:
56
51
raise AssertionError('Wrong prompt: %s' % message)
57
if choices != '&yes\n&No\n&finish\n&quit':
58
raise AssertionError('Wrong choices: %s' % choices)
68
61
LINES_AY = 'a\nb\nc\nd\ne\nf\ng\nh\ni\ny\n'
71
class ShelfTestCase(tests.TestCaseWithTransport):
64
class TestShelver(tests.TestCaseWithTransport):
73
66
def create_shelvable_tree(self):
74
67
tree = self.make_branch_and_tree('tree')
78
71
self.build_tree_contents([('tree/foo', LINES_ZY)])
82
class TestShelver(ShelfTestCase):
84
74
def test_unexpected_prompt_failure(self):
85
75
tree = self.create_shelvable_tree()
86
76
tree.lock_tree_write()
87
77
self.addCleanup(tree.unlock)
88
78
shelver = ExpectShelver(tree, tree.basis_tree())
89
self.addCleanup(shelver.finalize)
90
79
e = self.assertRaises(AssertionError, shelver.run)
91
self.assertEqual('Unexpected prompt: Shelve?', str(e))
80
self.assertEqual('Unexpected prompt: Shelve? [yNfq?]', str(e))
93
82
def test_wrong_prompt_failure(self):
94
83
tree = self.create_shelvable_tree()
95
84
tree.lock_tree_write()
96
85
self.addCleanup(tree.unlock)
97
86
shelver = ExpectShelver(tree, tree.basis_tree())
98
self.addCleanup(shelver.finalize)
99
shelver.expect('foo', 0)
87
shelver.expect('foo', 'y')
100
88
e = self.assertRaises(AssertionError, shelver.run)
101
self.assertEqual('Wrong prompt: Shelve?', str(e))
89
self.assertEqual('Wrong prompt: Shelve? [yNfq?]', str(e))
103
91
def test_shelve_not_diff(self):
104
92
tree = self.create_shelvable_tree()
105
93
tree.lock_tree_write()
106
94
self.addCleanup(tree.unlock)
107
95
shelver = ExpectShelver(tree, tree.basis_tree())
108
self.addCleanup(shelver.finalize)
109
shelver.expect('Shelve?', 1)
110
shelver.expect('Shelve?', 1)
96
shelver.expect('Shelve? [yNfq?]', 'n')
97
shelver.expect('Shelve? [yNfq?]', 'n')
111
98
# No final shelving prompt because no changes were selected
113
100
self.assertFileEqual(LINES_ZY, 'tree/foo')
117
104
tree.lock_tree_write()
118
105
self.addCleanup(tree.unlock)
119
106
shelver = ExpectShelver(tree, tree.basis_tree())
120
self.addCleanup(shelver.finalize)
121
shelver.expect('Shelve?', 0)
122
shelver.expect('Shelve?', 0)
123
shelver.expect('Shelve 2 change(s)?', 1)
107
shelver.expect('Shelve? [yNfq?]', 'y')
108
shelver.expect('Shelve? [yNfq?]', 'y')
109
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'n')
125
111
self.assertFileEqual(LINES_ZY, 'tree/foo')
129
115
tree.lock_tree_write()
130
116
self.addCleanup(tree.unlock)
131
117
shelver = ExpectShelver(tree, tree.basis_tree())
132
self.addCleanup(shelver.finalize)
133
shelver.expect('Shelve?', 0)
134
shelver.expect('Shelve?', 0)
135
shelver.expect('Shelve 2 change(s)?', 0)
118
shelver.expect('Shelve? [yNfq?]', 'y')
119
shelver.expect('Shelve? [yNfq?]', 'y')
120
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
137
122
self.assertFileEqual(LINES_AJ, 'tree/foo')
141
126
tree.lock_tree_write()
142
127
self.addCleanup(tree.unlock)
143
128
shelver = ExpectShelver(tree, tree.basis_tree())
144
self.addCleanup(shelver.finalize)
145
shelver.expect('Shelve?', 0)
146
shelver.expect('Shelve?', 1)
147
shelver.expect('Shelve 1 change(s)?', 0)
129
shelver.expect('Shelve? [yNfq?]', 'y')
130
shelver.expect('Shelve? [yNfq?]', 'n')
131
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
149
133
self.assertFileEqual(LINES_AY, 'tree/foo')
154
138
tree.lock_tree_write()
155
139
self.addCleanup(tree.unlock)
156
140
shelver = ExpectShelver(tree, tree.basis_tree())
157
self.addCleanup(shelver.finalize)
158
shelver.expect('Shelve binary changes?', 0)
159
shelver.expect('Shelve 1 change(s)?', 0)
141
shelver.expect('Shelve binary changes? [yNfq?]', 'y')
142
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
161
144
self.assertFileEqual(LINES_AJ, 'tree/foo')
166
149
tree.lock_tree_write()
167
150
self.addCleanup(tree.unlock)
168
151
shelver = ExpectShelver(tree, tree.basis_tree())
169
self.addCleanup(shelver.finalize)
170
shelver.expect('Shelve renaming "foo" => "bar"?', 0)
171
shelver.expect('Shelve?', 0)
172
shelver.expect('Shelve?', 0)
173
shelver.expect('Shelve 3 change(s)?', 0)
152
shelver.expect('Shelve renaming "foo" => "bar"? [yNfq?]', 'y')
153
shelver.expect('Shelve? [yNfq?]', 'y')
154
shelver.expect('Shelve? [yNfq?]', 'y')
155
shelver.expect('Shelve 3 change(s)? [yNfq?]', 'y')
175
157
self.assertFileEqual(LINES_AJ, 'tree/foo')
180
162
tree.lock_tree_write()
181
163
self.addCleanup(tree.unlock)
182
164
shelver = ExpectShelver(tree, tree.basis_tree())
183
self.addCleanup(shelver.finalize)
184
shelver.expect('Shelve removing file "foo"?', 0)
185
shelver.expect('Shelve 1 change(s)?', 0)
165
shelver.expect('Shelve removing file "foo"? [yNfq?]', 'y')
166
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
187
168
self.assertFileEqual(LINES_AJ, 'tree/foo')
194
175
tree.lock_tree_write()
195
176
self.addCleanup(tree.unlock)
196
177
shelver = ExpectShelver(tree, tree.basis_tree())
197
self.addCleanup(shelver.finalize)
198
shelver.expect('Shelve adding file "foo"?', 0)
199
shelver.expect('Shelve 1 change(s)?', 0)
178
shelver.expect('Shelve adding file "foo"? [yNfq?]', 'y')
179
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
201
self.assertPathDoesNotExist('tree/foo')
181
self.failIfExists('tree/foo')
203
183
def test_shelve_kind_change(self):
204
184
tree = self.create_shelvable_tree()
207
187
tree.lock_tree_write()
208
188
self.addCleanup(tree.unlock)
209
189
shelver = ExpectShelver(tree, tree.basis_tree())
210
self.addCleanup(shelver.finalize)
211
shelver.expect('Shelve changing "foo" from file to directory?',
213
shelver.expect('Shelve 1 change(s)?', 0)
190
shelver.expect('Shelve changing "foo" from file to directory? [yNfq?]',
192
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
215
194
def test_shelve_modify_target(self):
216
self.requireFeature(features.SymlinkFeature)
195
self.requireFeature(tests.SymlinkFeature)
217
196
tree = self.create_shelvable_tree()
218
197
os.symlink('bar', 'tree/baz')
219
198
tree.add('baz', 'baz-id')
223
202
tree.lock_tree_write()
224
203
self.addCleanup(tree.unlock)
225
204
shelver = ExpectShelver(tree, tree.basis_tree())
226
self.addCleanup(shelver.finalize)
227
205
shelver.expect('Shelve changing target of "baz" from "bar" to '
229
shelver.expect('Shelve 1 change(s)?', 0)
206
'"vax"? [yNfq?]', 'y')
207
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
231
209
self.assertEqual('bar', os.readlink('tree/baz'))
235
213
tree.lock_tree_write()
236
214
self.addCleanup(tree.unlock)
237
215
shelver = ExpectShelver(tree, tree.basis_tree())
238
self.addCleanup(shelver.finalize)
239
shelver.expect('Shelve?', 2)
240
shelver.expect('Shelve 2 change(s)?', 0)
216
shelver.expect('Shelve? [yNfq?]', 'f')
217
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
242
219
self.assertFileEqual(LINES_AJ, 'tree/foo')
246
223
tree.lock_tree_write()
247
224
self.addCleanup(tree.unlock)
248
225
shelver = ExpectShelver(tree, tree.basis_tree())
249
self.addCleanup(shelver.finalize)
250
shelver.expect('Shelve?', 3)
226
shelver.expect('Shelve? [yNfq?]', 'q')
251
227
self.assertRaises(errors.UserAbort, shelver.run)
252
228
self.assertFileEqual(LINES_ZY, 'tree/foo')
268
244
tree.lock_tree_write()
269
245
self.addCleanup(tree.unlock)
270
246
shelver = ExpectShelver(tree, tree.basis_tree(), file_list=['bar'])
271
self.addCleanup(shelver.finalize)
272
shelver.expect('Shelve adding file "bar"?', 0)
273
shelver.expect('Shelve 1 change(s)?', 0)
276
def test_shelve_destroy(self):
247
shelver.expect('Shelve adding file "bar"? [yNfq?]', 'y')
248
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
251
def test_shelve_help(self):
252
tree = self.create_shelvable_tree()
253
tree.lock_tree_write()
254
self.addCleanup(tree.unlock)
255
shelver = ExpectShelver(tree, tree.basis_tree())
256
shelver.expect('Shelve? [yNfq?]', '?')
257
shelver.expect('Shelve? [(y)es, (N)o, (f)inish, or (q)uit]', 'f')
258
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
261
def test_shelve_distroy(self):
277
262
tree = self.create_shelvable_tree()
278
263
shelver = shelf_ui.Shelver.from_args(sys.stdout, all=True,
279
264
directory='tree', destroy=True)
280
self.addCleanup(shelver.finalize)
268
shelver.work_tree.unlock()
282
269
self.assertIs(None, tree.get_shelf_manager().last_shelf())
283
270
self.assertFileEqual(LINES_AJ, 'tree/foo')
289
276
target = tree.branch.repository.revision_tree(target_revision_id)
290
277
shelver = shelf_ui.Shelver(tree, target, auto=True,
299
def test_shelve_old_root_preserved(self):
283
def test_shelve_old_root_deleted(self):
300
284
tree1 = self.make_branch_and_tree('tree1')
301
285
tree1.commit('add root')
302
tree1_root_id = tree1.get_root_id()
303
286
tree2 = self.make_branch_and_tree('tree2')
304
287
rev2 = tree2.commit('add root')
305
self.assertNotEqual(tree1_root_id, tree2.get_root_id())
306
288
tree1.merge_from_branch(tree2.branch,
307
289
from_revision=revision.NULL_REVISION)
308
tree1.commit('merging in tree2')
309
self.assertEqual(tree1_root_id, tree1.get_root_id())
290
tree1.commit('Replaced root entry')
310
291
# This is essentially assertNotRaises(InconsistentDelta)
311
# With testtools 0.9.9, it can be rewritten as:
312
# with ExpectedException(AssertionError,
313
# 'InconsistentDelta not raised'):
314
# with ExpectedException(errors.InconsistentDelta, ''):
315
# self.shelve_all(tree1, rev2)
316
e = self.assertRaises(AssertionError, self.assertRaises,
317
errors.InconsistentDelta, self.shelve_all, tree1,
319
self.assertContainsRe('InconsistentDelta not raised', str(e))
292
self.expectFailure('Cannot shelve replacing a root entry',
293
self.assertRaises, AssertionError,
294
self.assertRaises, errors.InconsistentDelta,
295
self.shelve_all, tree1, rev2)
321
297
def test_shelve_split(self):
322
298
outer_tree = self.make_branch_and_tree('outer')
340
316
self.addCleanup(tree.unlock)
341
317
shelver = ExpectShelver(tree, tree.basis_tree(),
342
318
reporter=shelf_ui.ApplyReporter())
343
self.addCleanup(shelver.finalize)
344
shelver.expect('Apply change?', 1)
345
shelver.expect('Apply change?', 1)
319
shelver.expect('Apply change? [yNfq?]', 'n')
320
shelver.expect('Apply change? [yNfq?]', 'n')
346
321
# No final shelving prompt because no changes were selected
348
323
self.assertFileEqual(LINES_ZY, 'tree/foo')
353
328
self.addCleanup(tree.unlock)
354
329
shelver = ExpectShelver(tree, tree.basis_tree(),
355
330
reporter=shelf_ui.ApplyReporter())
356
self.addCleanup(shelver.finalize)
357
shelver.expect('Apply change?', 0)
358
shelver.expect('Apply change?', 0)
359
shelver.expect('Apply 2 change(s)?', 1)
331
shelver.expect('Apply change? [yNfq?]', 'y')
332
shelver.expect('Apply change? [yNfq?]', 'y')
333
shelver.expect('Apply 2 change(s)? [yNfq?]', 'n')
361
335
self.assertFileEqual(LINES_ZY, 'tree/foo')
366
340
self.addCleanup(tree.unlock)
367
341
shelver = ExpectShelver(tree, tree.basis_tree(),
368
342
reporter=shelf_ui.ApplyReporter())
369
self.addCleanup(shelver.finalize)
370
shelver.expect('Apply change?', 0)
371
shelver.expect('Apply change?', 0)
372
shelver.expect('Apply 2 change(s)?', 0)
343
shelver.expect('Apply change? [yNfq?]', 'y')
344
shelver.expect('Apply change? [yNfq?]', 'y')
345
shelver.expect('Apply 2 change(s)? [yNfq?]', 'y')
374
347
self.assertFileEqual(LINES_AJ, 'tree/foo')
380
353
self.addCleanup(tree.unlock)
381
354
shelver = ExpectShelver(tree, tree.basis_tree(),
382
355
reporter=shelf_ui.ApplyReporter())
383
self.addCleanup(shelver.finalize)
384
shelver.expect('Apply binary changes?', 0)
385
shelver.expect('Apply 1 change(s)?', 0)
356
shelver.expect('Apply binary changes? [yNfq?]', 'y')
357
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
387
359
self.assertFileEqual(LINES_AJ, 'tree/foo')
393
365
self.addCleanup(tree.unlock)
394
366
shelver = ExpectShelver(tree, tree.basis_tree(),
395
367
reporter=shelf_ui.ApplyReporter())
396
self.addCleanup(shelver.finalize)
397
shelver.expect('Rename "bar" => "foo"?', 0)
398
shelver.expect('Apply change?', 0)
399
shelver.expect('Apply change?', 0)
400
shelver.expect('Apply 3 change(s)?', 0)
368
shelver.expect('Rename "bar" => "foo"? [yNfq?]', 'y')
369
shelver.expect('Apply change? [yNfq?]', 'y')
370
shelver.expect('Apply change? [yNfq?]', 'y')
371
shelver.expect('Apply 3 change(s)? [yNfq?]', 'y')
402
373
self.assertFileEqual(LINES_AJ, 'tree/foo')
408
379
self.addCleanup(tree.unlock)
409
380
shelver = ExpectShelver(tree, tree.basis_tree(),
410
381
reporter=shelf_ui.ApplyReporter())
411
self.addCleanup(shelver.finalize)
412
shelver.expect('Add file "foo"?', 0)
413
shelver.expect('Apply 1 change(s)?', 0)
382
shelver.expect('Add file "foo"? [yNfq?]', 'y')
383
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
415
385
self.assertFileEqual(LINES_AJ, 'tree/foo')
423
393
self.addCleanup(tree.unlock)
424
394
shelver = ExpectShelver(tree, tree.basis_tree(),
425
395
reporter=shelf_ui.ApplyReporter())
426
self.addCleanup(shelver.finalize)
427
shelver.expect('Delete file "foo"?', 0)
428
shelver.expect('Apply 1 change(s)?', 0)
396
shelver.expect('Delete file "foo"? [yNfq?]', 'y')
397
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
430
self.assertPathDoesNotExist('tree/foo')
399
self.failIfExists('tree/foo')
432
401
def test_shelve_kind_change(self):
433
402
tree = self.create_shelvable_tree()
437
406
self.addCleanup(tree.unlock)
438
407
shelver = ExpectShelver(tree, tree.basis_tree(),
439
408
reporter=shelf_ui.ApplyReporter())
440
self.addCleanup(shelver.finalize)
441
shelver.expect('Change "foo" from directory to a file?', 0)
442
shelver.expect('Apply 1 change(s)?', 0)
409
shelver.expect('Change "foo" from directory to a file? [yNfq?]', 'y')
410
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
444
412
def test_shelve_modify_target(self):
445
self.requireFeature(features.SymlinkFeature)
413
self.requireFeature(tests.SymlinkFeature)
446
414
tree = self.create_shelvable_tree()
447
415
os.symlink('bar', 'tree/baz')
448
416
tree.add('baz', 'baz-id')
453
421
self.addCleanup(tree.unlock)
454
422
shelver = ExpectShelver(tree, tree.basis_tree(),
455
423
reporter=shelf_ui.ApplyReporter())
456
self.addCleanup(shelver.finalize)
457
shelver.expect('Change target of "baz" from "vax" to "bar"?',
459
shelver.expect('Apply 1 change(s)?', 0)
424
shelver.expect('Change target of "baz" from "vax" to "bar"? [yNfq?]',
426
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
461
428
self.assertEqual('bar', os.readlink('tree/baz'))
471
438
tree.add('foo', 'foo-id')
472
439
tree.commit('added foo')
473
440
self.build_tree_contents([('tree/foo', LINES_ZY)])
474
shelver = shelf_ui.Shelver(tree, tree.basis_tree(),
475
auto_apply=True, auto=True)
441
shelf_ui.Shelver(tree, tree.basis_tree(), auto_apply=True,
510
473
self.assertFileEqual(LINES_AJ, 'tree/foo')
511
474
self.assertEqual(1, tree.get_shelf_manager().last_shelf())
513
def test_unshelve_args_preview(self):
514
tree = self.create_tree_with_shelf()
515
write_diff_to = StringIO()
516
unshelver = shelf_ui.Unshelver.from_args(
517
directory='tree', action='preview', write_diff_to=write_diff_to)
521
unshelver.tree.unlock()
522
# The changes were not unshelved.
523
self.assertFileEqual(LINES_AJ, 'tree/foo')
524
self.assertEqual(1, tree.get_shelf_manager().last_shelf())
526
# But the diff was written to write_diff_to.
527
diff = write_diff_to.getvalue()
528
expected = dedent("""\
543
self.assertEqualDiff(expected, diff[-len(expected):])
545
476
def test_unshelve_args_delete_only(self):
546
477
tree = self.make_branch_and_tree('tree')
547
478
manager = tree.get_shelf_manager()
569
500
self.assertRaises(errors.InvalidShelfId,
570
501
shelf_ui.Unshelver.from_args, directory='tree',
571
502
action='delete-only', shelf_id='foo')
574
class TestUnshelveScripts(TestUnshelver,
575
script.TestCaseWithTransportAndScript):
577
def test_unshelve_messages_keep(self):
578
self.create_tree_with_shelf()
581
$ bzr unshelve --keep
582
2>Using changes with id "1".
584
2>All changes applied successfully.
587
def test_unshelve_messages_delete(self):
588
self.create_tree_with_shelf()
591
$ bzr unshelve --delete-only
592
2>Deleted changes with id "1".
595
def test_unshelve_messages_apply(self):
596
self.create_tree_with_shelf()
599
$ bzr unshelve --apply
600
2>Using changes with id "1".
602
2>All changes applied successfully.
603
2>Deleted changes with id "1".
606
def test_unshelve_messages_dry_run(self):
607
self.create_tree_with_shelf()
610
$ bzr unshelve --dry-run
611
2>Using changes with id "1".