1
# Copyright (C) 2008, 2009, 2010 Canonical Ltd
1
# Copyright (C) 2008-2011, 2016 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
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
from cStringIO import StringIO
21
20
from textwrap import dedent
29
from bzrlib.tests import script
28
from ..sixish import (
32
37
class ExpectShelver(shelf_ui.Shelver):
39
44
auto, auto_apply, file_list, message,
40
45
destroy, reporter=reporter)
42
self.diff_writer = StringIO()
44
def expect(self, prompt, response):
45
self.expected.append((prompt, response))
47
def prompt(self, message):
47
self.diff_writer = BytesIO()
49
def expect(self, message, response):
50
self.expected.append((message, response))
52
def prompt(self, message, choices, default):
49
prompt, response = self.expected.pop(0)
54
expected_message, response = self.expected.pop(0)
51
56
raise AssertionError('Unexpected prompt: %s' % message)
57
if message != expected_message:
53
58
raise AssertionError('Wrong prompt: %s' % message)
59
if choices != '&yes\n&No\n&finish\n&quit':
60
raise AssertionError('Wrong choices: %s' % choices)
63
70
LINES_AY = 'a\nb\nc\nd\ne\nf\ng\nh\ni\ny\n'
66
class TestShelver(tests.TestCaseWithTransport):
73
class ShelfTestCase(tests.TestCaseWithTransport):
68
75
def create_shelvable_tree(self):
69
76
tree = self.make_branch_and_tree('tree')
73
80
self.build_tree_contents([('tree/foo', LINES_ZY)])
84
class TestShelver(ShelfTestCase):
76
86
def test_unexpected_prompt_failure(self):
77
87
tree = self.create_shelvable_tree()
78
88
tree.lock_tree_write()
80
90
shelver = ExpectShelver(tree, tree.basis_tree())
81
91
self.addCleanup(shelver.finalize)
82
92
e = self.assertRaises(AssertionError, shelver.run)
83
self.assertEqual('Unexpected prompt: Shelve? [yNfq?]', str(e))
93
self.assertEqual('Unexpected prompt: Shelve?', str(e))
85
95
def test_wrong_prompt_failure(self):
86
96
tree = self.create_shelvable_tree()
88
98
self.addCleanup(tree.unlock)
89
99
shelver = ExpectShelver(tree, tree.basis_tree())
90
100
self.addCleanup(shelver.finalize)
91
shelver.expect('foo', 'y')
101
shelver.expect('foo', 0)
92
102
e = self.assertRaises(AssertionError, shelver.run)
93
self.assertEqual('Wrong prompt: Shelve? [yNfq?]', str(e))
103
self.assertEqual('Wrong prompt: Shelve?', str(e))
95
105
def test_shelve_not_diff(self):
96
106
tree = self.create_shelvable_tree()
98
108
self.addCleanup(tree.unlock)
99
109
shelver = ExpectShelver(tree, tree.basis_tree())
100
110
self.addCleanup(shelver.finalize)
101
shelver.expect('Shelve? [yNfq?]', 'n')
102
shelver.expect('Shelve? [yNfq?]', 'n')
111
shelver.expect('Shelve?', 1)
112
shelver.expect('Shelve?', 1)
103
113
# No final shelving prompt because no changes were selected
105
115
self.assertFileEqual(LINES_ZY, 'tree/foo')
110
120
self.addCleanup(tree.unlock)
111
121
shelver = ExpectShelver(tree, tree.basis_tree())
112
122
self.addCleanup(shelver.finalize)
113
shelver.expect('Shelve? [yNfq?]', 'y')
114
shelver.expect('Shelve? [yNfq?]', 'y')
115
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'n')
123
shelver.expect('Shelve?', 0)
124
shelver.expect('Shelve?', 0)
125
shelver.expect('Shelve 2 change(s)?', 1)
117
127
self.assertFileEqual(LINES_ZY, 'tree/foo')
122
132
self.addCleanup(tree.unlock)
123
133
shelver = ExpectShelver(tree, tree.basis_tree())
124
134
self.addCleanup(shelver.finalize)
125
shelver.expect('Shelve? [yNfq?]', 'y')
126
shelver.expect('Shelve? [yNfq?]', 'y')
127
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
135
shelver.expect('Shelve?', 0)
136
shelver.expect('Shelve?', 0)
137
shelver.expect('Shelve 2 change(s)?', 0)
129
139
self.assertFileEqual(LINES_AJ, 'tree/foo')
134
144
self.addCleanup(tree.unlock)
135
145
shelver = ExpectShelver(tree, tree.basis_tree())
136
146
self.addCleanup(shelver.finalize)
137
shelver.expect('Shelve? [yNfq?]', 'y')
138
shelver.expect('Shelve? [yNfq?]', 'n')
139
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
147
shelver.expect('Shelve?', 0)
148
shelver.expect('Shelve?', 1)
149
shelver.expect('Shelve 1 change(s)?', 0)
141
151
self.assertFileEqual(LINES_AY, 'tree/foo')
147
157
self.addCleanup(tree.unlock)
148
158
shelver = ExpectShelver(tree, tree.basis_tree())
149
159
self.addCleanup(shelver.finalize)
150
shelver.expect('Shelve binary changes? [yNfq?]', 'y')
151
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
160
shelver.expect('Shelve binary changes?', 0)
161
shelver.expect('Shelve 1 change(s)?', 0)
153
163
self.assertFileEqual(LINES_AJ, 'tree/foo')
159
169
self.addCleanup(tree.unlock)
160
170
shelver = ExpectShelver(tree, tree.basis_tree())
161
171
self.addCleanup(shelver.finalize)
162
shelver.expect('Shelve renaming "foo" => "bar"? [yNfq?]', 'y')
163
shelver.expect('Shelve? [yNfq?]', 'y')
164
shelver.expect('Shelve? [yNfq?]', 'y')
165
shelver.expect('Shelve 3 change(s)? [yNfq?]', 'y')
172
shelver.expect('Shelve renaming "foo" => "bar"?', 0)
173
shelver.expect('Shelve?', 0)
174
shelver.expect('Shelve?', 0)
175
shelver.expect('Shelve 3 change(s)?', 0)
167
177
self.assertFileEqual(LINES_AJ, 'tree/foo')
173
183
self.addCleanup(tree.unlock)
174
184
shelver = ExpectShelver(tree, tree.basis_tree())
175
185
self.addCleanup(shelver.finalize)
176
shelver.expect('Shelve removing file "foo"? [yNfq?]', 'y')
177
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
186
shelver.expect('Shelve removing file "foo"?', 0)
187
shelver.expect('Shelve 1 change(s)?', 0)
179
189
self.assertFileEqual(LINES_AJ, 'tree/foo')
187
197
self.addCleanup(tree.unlock)
188
198
shelver = ExpectShelver(tree, tree.basis_tree())
189
199
self.addCleanup(shelver.finalize)
190
shelver.expect('Shelve adding file "foo"? [yNfq?]', 'y')
191
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
200
shelver.expect('Shelve adding file "foo"?', 0)
201
shelver.expect('Shelve 1 change(s)?', 0)
193
self.failIfExists('tree/foo')
203
self.assertPathDoesNotExist('tree/foo')
195
205
def test_shelve_kind_change(self):
196
206
tree = self.create_shelvable_tree()
200
210
self.addCleanup(tree.unlock)
201
211
shelver = ExpectShelver(tree, tree.basis_tree())
202
212
self.addCleanup(shelver.finalize)
203
shelver.expect('Shelve changing "foo" from file to directory? [yNfq?]',
205
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
213
shelver.expect('Shelve changing "foo" from file to directory?',
215
shelver.expect('Shelve 1 change(s)?', 0)
207
217
def test_shelve_modify_target(self):
208
self.requireFeature(tests.SymlinkFeature)
218
self.requireFeature(features.SymlinkFeature)
209
219
tree = self.create_shelvable_tree()
210
220
os.symlink('bar', 'tree/baz')
211
221
tree.add('baz', 'baz-id')
217
227
shelver = ExpectShelver(tree, tree.basis_tree())
218
228
self.addCleanup(shelver.finalize)
219
229
shelver.expect('Shelve changing target of "baz" from "bar" to '
220
'"vax"? [yNfq?]', 'y')
221
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
231
shelver.expect('Shelve 1 change(s)?', 0)
223
233
self.assertEqual('bar', os.readlink('tree/baz'))
228
238
self.addCleanup(tree.unlock)
229
239
shelver = ExpectShelver(tree, tree.basis_tree())
230
240
self.addCleanup(shelver.finalize)
231
shelver.expect('Shelve? [yNfq?]', 'f')
232
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
241
shelver.expect('Shelve?', 2)
242
shelver.expect('Shelve 2 change(s)?', 0)
234
244
self.assertFileEqual(LINES_AJ, 'tree/foo')
239
249
self.addCleanup(tree.unlock)
240
250
shelver = ExpectShelver(tree, tree.basis_tree())
241
251
self.addCleanup(shelver.finalize)
242
shelver.expect('Shelve? [yNfq?]', 'q')
252
shelver.expect('Shelve?', 3)
243
253
self.assertRaises(errors.UserAbort, shelver.run)
244
254
self.assertFileEqual(LINES_ZY, 'tree/foo')
261
271
self.addCleanup(tree.unlock)
262
272
shelver = ExpectShelver(tree, tree.basis_tree(), file_list=['bar'])
263
273
self.addCleanup(shelver.finalize)
264
shelver.expect('Shelve adding file "bar"? [yNfq?]', 'y')
265
shelver.expect('Shelve 1 change(s)? [yNfq?]', 'y')
268
def test_shelve_help(self):
269
tree = self.create_shelvable_tree()
270
tree.lock_tree_write()
271
self.addCleanup(tree.unlock)
272
shelver = ExpectShelver(tree, tree.basis_tree())
273
self.addCleanup(shelver.finalize)
274
shelver.expect('Shelve? [yNfq?]', '?')
275
shelver.expect('Shelve? [(y)es, (N)o, (f)inish, or (q)uit]', 'f')
276
shelver.expect('Shelve 2 change(s)? [yNfq?]', 'y')
274
shelver.expect('Shelve adding file "bar"?', 0)
275
shelver.expect('Shelve 1 change(s)?', 0)
279
278
def test_shelve_destroy(self):
302
def test_shelve_old_root_deleted(self):
301
def test_shelve_old_root_preserved(self):
303
302
tree1 = self.make_branch_and_tree('tree1')
304
303
tree1.commit('add root')
304
tree1_root_id = tree1.get_root_id()
305
305
tree2 = self.make_branch_and_tree('tree2')
306
306
rev2 = tree2.commit('add root')
307
self.assertNotEqual(tree1_root_id, tree2.get_root_id())
307
308
tree1.merge_from_branch(tree2.branch,
308
309
from_revision=revision.NULL_REVISION)
309
tree1.commit('Replaced root entry')
310
tree1.commit('merging in tree2')
311
self.assertEqual(tree1_root_id, tree1.get_root_id())
310
312
# This is essentially assertNotRaises(InconsistentDelta)
311
self.expectFailure('Cannot shelve replacing a root entry',
312
self.assertRaises, AssertionError,
313
self.assertRaises, errors.InconsistentDelta,
314
self.shelve_all, tree1, rev2)
313
# With testtools 0.9.9, it can be rewritten as:
314
# with ExpectedException(AssertionError,
315
# 'InconsistentDelta not raised'):
316
# with ExpectedException(errors.InconsistentDelta, ''):
317
# self.shelve_all(tree1, rev2)
318
e = self.assertRaises(AssertionError, self.assertRaises,
319
errors.InconsistentDelta, self.shelve_all, tree1,
321
self.assertContainsRe('InconsistentDelta not raised', str(e))
316
323
def test_shelve_split(self):
317
324
outer_tree = self.make_branch_and_tree('outer')
336
343
shelver = ExpectShelver(tree, tree.basis_tree(),
337
344
reporter=shelf_ui.ApplyReporter())
338
345
self.addCleanup(shelver.finalize)
339
shelver.expect('Apply change? [yNfq?]', 'n')
340
shelver.expect('Apply change? [yNfq?]', 'n')
346
shelver.expect('Apply change?', 1)
347
shelver.expect('Apply change?', 1)
341
348
# No final shelving prompt because no changes were selected
343
350
self.assertFileEqual(LINES_ZY, 'tree/foo')
349
356
shelver = ExpectShelver(tree, tree.basis_tree(),
350
357
reporter=shelf_ui.ApplyReporter())
351
358
self.addCleanup(shelver.finalize)
352
shelver.expect('Apply change? [yNfq?]', 'y')
353
shelver.expect('Apply change? [yNfq?]', 'y')
354
shelver.expect('Apply 2 change(s)? [yNfq?]', 'n')
359
shelver.expect('Apply change?', 0)
360
shelver.expect('Apply change?', 0)
361
shelver.expect('Apply 2 change(s)?', 1)
356
363
self.assertFileEqual(LINES_ZY, 'tree/foo')
362
369
shelver = ExpectShelver(tree, tree.basis_tree(),
363
370
reporter=shelf_ui.ApplyReporter())
364
371
self.addCleanup(shelver.finalize)
365
shelver.expect('Apply change? [yNfq?]', 'y')
366
shelver.expect('Apply change? [yNfq?]', 'y')
367
shelver.expect('Apply 2 change(s)? [yNfq?]', 'y')
372
shelver.expect('Apply change?', 0)
373
shelver.expect('Apply change?', 0)
374
shelver.expect('Apply 2 change(s)?', 0)
369
376
self.assertFileEqual(LINES_AJ, 'tree/foo')
376
383
shelver = ExpectShelver(tree, tree.basis_tree(),
377
384
reporter=shelf_ui.ApplyReporter())
378
385
self.addCleanup(shelver.finalize)
379
shelver.expect('Apply binary changes? [yNfq?]', 'y')
380
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
386
shelver.expect('Apply binary changes?', 0)
387
shelver.expect('Apply 1 change(s)?', 0)
382
389
self.assertFileEqual(LINES_AJ, 'tree/foo')
389
396
shelver = ExpectShelver(tree, tree.basis_tree(),
390
397
reporter=shelf_ui.ApplyReporter())
391
398
self.addCleanup(shelver.finalize)
392
shelver.expect('Rename "bar" => "foo"? [yNfq?]', 'y')
393
shelver.expect('Apply change? [yNfq?]', 'y')
394
shelver.expect('Apply change? [yNfq?]', 'y')
395
shelver.expect('Apply 3 change(s)? [yNfq?]', 'y')
399
shelver.expect('Rename "bar" => "foo"?', 0)
400
shelver.expect('Apply change?', 0)
401
shelver.expect('Apply change?', 0)
402
shelver.expect('Apply 3 change(s)?', 0)
397
404
self.assertFileEqual(LINES_AJ, 'tree/foo')
404
411
shelver = ExpectShelver(tree, tree.basis_tree(),
405
412
reporter=shelf_ui.ApplyReporter())
406
413
self.addCleanup(shelver.finalize)
407
shelver.expect('Add file "foo"? [yNfq?]', 'y')
408
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
414
shelver.expect('Add file "foo"?', 0)
415
shelver.expect('Apply 1 change(s)?', 0)
410
417
self.assertFileEqual(LINES_AJ, 'tree/foo')
419
426
shelver = ExpectShelver(tree, tree.basis_tree(),
420
427
reporter=shelf_ui.ApplyReporter())
421
428
self.addCleanup(shelver.finalize)
422
shelver.expect('Delete file "foo"? [yNfq?]', 'y')
423
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
429
shelver.expect('Delete file "foo"?', 0)
430
shelver.expect('Apply 1 change(s)?', 0)
425
self.failIfExists('tree/foo')
432
self.assertPathDoesNotExist('tree/foo')
427
434
def test_shelve_kind_change(self):
428
435
tree = self.create_shelvable_tree()
433
440
shelver = ExpectShelver(tree, tree.basis_tree(),
434
441
reporter=shelf_ui.ApplyReporter())
435
442
self.addCleanup(shelver.finalize)
436
shelver.expect('Change "foo" from directory to a file? [yNfq?]', 'y')
437
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
443
shelver.expect('Change "foo" from directory to a file?', 0)
444
shelver.expect('Apply 1 change(s)?', 0)
439
446
def test_shelve_modify_target(self):
440
self.requireFeature(tests.SymlinkFeature)
447
self.requireFeature(features.SymlinkFeature)
441
448
tree = self.create_shelvable_tree()
442
449
os.symlink('bar', 'tree/baz')
443
450
tree.add('baz', 'baz-id')
449
456
shelver = ExpectShelver(tree, tree.basis_tree(),
450
457
reporter=shelf_ui.ApplyReporter())
451
458
self.addCleanup(shelver.finalize)
452
shelver.expect('Change target of "baz" from "vax" to "bar"? [yNfq?]',
454
shelver.expect('Apply 1 change(s)? [yNfq?]', 'y')
459
shelver.expect('Change target of "baz" from "vax" to "bar"?',
461
shelver.expect('Apply 1 change(s)?', 0)
456
463
self.assertEqual('bar', os.readlink('tree/baz'))
508
515
def test_unshelve_args_preview(self):
509
516
tree = self.create_tree_with_shelf()
510
write_diff_to = StringIO()
517
write_diff_to = BytesIO()
511
518
unshelver = shelf_ui.Unshelver.from_args(
512
519
directory='tree', action='preview', write_diff_to=write_diff_to)