13
13
# You should have received a copy of the GNU General Public License
14
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""Test the uncommit command."""
21
from bzrlib import uncommit
21
from bzrlib import uncommit, workingtree
22
22
from bzrlib.bzrdir import BzrDirMetaFormat1
23
from bzrlib.errors import BoundBranchOutOfDate
23
from bzrlib.errors import BzrError, BoundBranchOutOfDate
24
24
from bzrlib.tests import TestCaseWithTransport
25
from bzrlib.tests.matchers import ContainsNoVfsCalls
26
from bzrlib.tests.script import (
32
27
class TestUncommit(TestCaseWithTransport):
65
60
out, err = self.run_bzr('status')
66
61
self.assertEquals(out, 'modified:\n a\n')
68
def test_uncommit_interactive(self):
69
"""Uncommit seeks confirmation, and doesn't proceed without it."""
70
wt = self.create_simple_tree()
75
The above revision(s) will be removed.
76
2>Uncommit these revisions? ([y]es, [n]o): no
80
self.assertEqual(['a2'], wt.get_parent_ids())
82
63
def test_uncommit_no_history(self):
83
64
wt = self.make_branch_and_tree('tree')
84
65
out, err = self.run_bzr('uncommit --force', retcode=1)
120
101
t_a.commit('commit 3')
121
102
b = t_a.branch.create_checkout('b').branch
122
103
uncommit.uncommit(b)
123
self.assertEqual(b.last_revision_info()[0], 2)
124
self.assertEqual(t_a.branch.last_revision_info()[0], 2)
125
# update A's tree to not have the uncommitted revision referenced.
104
self.assertEqual(len(b.revision_history()), 2)
105
self.assertEqual(len(t_a.branch.revision_history()), 2)
106
# update A's tree to not have the uncomitted revision referenced.
127
108
t_a.commit('commit 3b')
128
109
self.assertRaises(BoundBranchOutOfDate, uncommit.uncommit, b)
192
173
wt = self.create_simple_tree()
194
175
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
195
177
tree2.commit('unchanged', rev_id='b3')
197
tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
198
tree3.commit('unchanged', rev_id='c3')
200
179
wt.merge_from_branch(tree2.branch)
201
180
wt.commit('merge b3', rev_id='a3')
203
wt.merge_from_branch(tree3.branch)
204
wt.commit('merge c3', rev_id='a4')
182
tree2.commit('unchanged', rev_id='b4')
184
wt.merge_from_branch(tree2.branch)
185
wt.commit('merge b4', rev_id='a4')
206
187
self.assertEqual(['a4'], wt.get_parent_ids())
209
190
out, err = self.run_bzr('uncommit --force -r 2')
211
self.assertEqual(['a2', 'b3', 'c3'], wt.get_parent_ids())
192
self.assertEqual(['a2', 'b3', 'b4'], wt.get_parent_ids())
213
194
def test_uncommit_merge_plus_pending(self):
214
195
wt = self.create_simple_tree()
216
197
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
217
199
tree2.commit('unchanged', rev_id='b3')
218
tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
219
tree3.commit('unchanged', rev_id='c3')
221
200
wt.branch.fetch(tree2.branch)
222
201
wt.set_pending_merges(['b3'])
223
202
wt.commit('merge b3', rev_id='a3')
226
wt.merge_from_branch(tree3.branch)
228
self.assertEqual(['a3', 'c3'], wt.get_parent_ids())
204
tree2.commit('unchanged', rev_id='b4')
205
wt.branch.fetch(tree2.branch)
206
wt.set_pending_merges(['b4'])
208
self.assertEqual(['a3', 'b4'], wt.get_parent_ids())
231
211
out, err = self.run_bzr('uncommit --force -r 2')
233
self.assertEqual(['a2', 'b3', 'c3'], wt.get_parent_ids())
235
def test_uncommit_shows_log_with_revision_id(self):
236
wt = self.create_simple_tree()
238
script = ScriptRunner()
239
script.run_script(self, """
241
$ bzr uncommit --force
245
The above revision(s) will be removed.
246
You can restore the old tip by running:
247
bzr pull . -r revid:a2
213
self.assertEqual(['a2', 'b3', 'b4'], wt.get_parent_ids())
250
215
def test_uncommit_octopus_merge(self):
251
216
# Check that uncommit keeps the pending merges in the same order
252
# though it will also filter out ones in the ancestry
253
217
wt = self.create_simple_tree()
255
219
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
258
222
tree2.commit('unchanged', rev_id='b3')
259
223
tree3.commit('unchanged', rev_id='c3')
261
225
wt.merge_from_branch(tree2.branch)
262
wt.merge_from_branch(tree3.branch, force=True)
226
wt.merge_from_branch(tree3.branch)
263
227
wt.commit('merge b3, c3', rev_id='a3')
265
229
tree2.commit('unchanged', rev_id='b4')
266
230
tree3.commit('unchanged', rev_id='c4')
268
232
wt.merge_from_branch(tree3.branch)
269
wt.merge_from_branch(tree2.branch, force=True)
233
wt.merge_from_branch(tree2.branch)
270
234
wt.commit('merge b4, c4', rev_id='a4')
272
236
self.assertEqual(['a4'], wt.get_parent_ids())
275
239
out, err = self.run_bzr('uncommit --force -r 2')
277
self.assertEqual(['a2', 'c4', 'b4'], wt.get_parent_ids())
241
self.assertEqual(['a2', 'b3', 'c3', 'c4', 'b4'], wt.get_parent_ids())
279
243
def test_uncommit_nonascii(self):
280
244
tree = self.make_branch_and_tree('tree')
281
245
tree.commit(u'\u1234 message')
282
246
out, err = self.run_bzr('uncommit --force tree', encoding='ascii')
283
247
self.assertContainsRe(out, r'\? message')
285
def test_uncommit_removes_tags(self):
286
tree = self.make_branch_and_tree('tree')
287
revid = tree.commit('message')
288
tree.branch.tags.set_tag("atag", revid)
289
out, err = self.run_bzr('uncommit --force tree')
290
self.assertEquals({}, tree.branch.tags.get_tag_dict())
292
def test_uncommit_keep_tags(self):
293
tree = self.make_branch_and_tree('tree')
294
revid = tree.commit('message')
295
tree.branch.tags.set_tag("atag", revid)
296
out, err = self.run_bzr('uncommit --keep-tags --force tree')
297
self.assertEquals({"atag": revid}, tree.branch.tags.get_tag_dict())
300
class TestSmartServerUncommit(TestCaseWithTransport):
302
def test_uncommit(self):
303
self.setup_smart_server_with_call_log()
304
t = self.make_branch_and_tree('from')
305
for count in range(2):
306
t.commit(message='commit %d' % count)
307
self.reset_smart_call_log()
308
out, err = self.run_bzr(['uncommit', '--force', self.get_url('from')])
309
# This figure represent the amount of work to perform this use case. It
310
# is entirely ok to reduce this number if a test fails due to rpc_count
311
# being too low. If rpc_count increases, more network roundtrips have
312
# become necessary for this use case. Please do not adjust this number
313
# upwards without agreement from bzr's network support maintainers.
314
self.assertLength(14, self.hpss_calls)
315
self.assertLength(1, self.hpss_connections)
316
self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
319
class TestInconsistentDelta(TestCaseWithTransport):
320
# See https://bugs.launchpad.net/bzr/+bug/855155
321
# See https://bugs.launchpad.net/bzr/+bug/1100385
322
# bzr uncommit may result in error
323
# 'An inconsistent delta was supplied involving'
325
def test_inconsistent_delta(self):
326
# Script taken from https://bugs.launchpad.net/bzr/+bug/855155/comments/26
327
wt = self.make_branch_and_tree('test')
328
self.build_tree(['test/a/', 'test/a/b', 'test/a/c'])
329
wt.add(['a', 'a/b', 'a/c'])
330
wt.commit('initial commit', rev_id='a1')
331
wt.remove(['a/b', 'a/c'])
332
wt.commit('remove b and c', rev_id='a2')
333
self.run_bzr("uncommit --force test")