1
# Copyright (C) 2005, 2006 by Canonical Ltd
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Test the uncommit command."""
21
from bzrlib import uncommit, workingtree
22
from bzrlib.bzrdir import BzrDirMetaFormat1
23
from bzrlib.errors import BzrError, BoundBranchOutOfDate
24
from bzrlib.tests import TestCaseWithTransport
27
class TestUncommit(TestCaseWithTransport):
28
def create_simple_tree(self):
29
wt = self.make_branch_and_tree('tree')
30
self.build_tree(['tree/a', 'tree/b', 'tree/c'])
31
wt.add(['a', 'b', 'c'])
32
wt.commit('initial commit', rev_id='a1')
34
open('tree/a', 'wb').write('new contents of a\n')
35
wt.commit('second commit', rev_id='a2')
39
def test_uncommit(self):
40
"""Test uncommit functionality."""
41
wt = self.create_simple_tree()
44
out, err = self.run_bzr('uncommit', '--dry-run', '--force')
45
self.assertContainsRe(out, 'Dry-run')
46
self.assertNotContainsRe(out, 'initial commit')
47
self.assertContainsRe(out, 'second commit')
50
self.assertEqual('a2', wt.last_revision())
52
# Uncommit, don't prompt
53
out, err = self.run_bzr('uncommit', '--force')
54
self.assertNotContainsRe(out, 'initial commit')
55
self.assertContainsRe(out, 'second commit')
57
# This should look like we are back in revno 1
58
self.assertEqual('a1', wt.last_revision())
59
out, err = self.run_bzr('status')
60
self.assertEquals(out, 'modified:\n a\n')
62
def test_uncommit_checkout(self):
63
wt = self.create_simple_tree()
65
checkout_tree = wt.bzrdir.sprout('checkout').open_workingtree()
66
checkout_tree.branch.bind(wt.branch)
68
self.assertEqual('a2', checkout_tree.last_revision())
71
out, err = self.run_bzr('uncommit', '--dry-run', '--force')
72
self.assertContainsRe(out, 'Dry-run')
73
self.assertNotContainsRe(out, 'initial commit')
74
self.assertContainsRe(out, 'second commit')
76
self.assertEqual('a2', checkout_tree.last_revision())
78
out, err = self.run_bzr('uncommit', '--force')
79
self.assertNotContainsRe(out, 'initial commit')
80
self.assertContainsRe(out, 'second commit')
82
# uncommit in a checkout should uncommit the parent branch
83
# (but doesn't effect the other working tree)
84
self.assertEquals('a1', checkout_tree.last_revision())
85
self.assertEquals('a1', wt.branch.last_revision())
86
self.assertEquals('a2', wt.last_revision())
88
def test_uncommit_bound(self):
90
a = BzrDirMetaFormat1().initialize('a')
93
t_a = a.create_workingtree()
94
t_a.commit('commit 1')
95
t_a.commit('commit 2')
96
t_a.commit('commit 3')
97
b = t_a.bzrdir.sprout('b').open_branch()
100
self.assertEqual(len(b.revision_history()), 2)
101
self.assertEqual(len(t_a.branch.revision_history()), 2)
102
# update A's tree to not have the uncomitted revision referenced.
104
t_a.commit('commit 3b')
105
self.assertRaises(BoundBranchOutOfDate, uncommit.uncommit, b)
109
def test_uncommit_revision(self):
110
wt = self.create_simple_tree()
113
out, err = self.run_bzr('uncommit', '-r1', '--force')
115
self.assertNotContainsRe(out, 'initial commit')
116
self.assertContainsRe(out, 'second commit')
117
self.assertEqual('a1', wt.last_revision())
118
self.assertEqual('a1', wt.branch.last_revision())
120
def test_uncommit_neg_1(self):
121
wt = self.create_simple_tree()
123
out, err = self.run_bzr('uncommit', '-r', '-1', retcode=1)
124
self.assertEqual('No revisions to uncommit.\n', out)
126
def test_uncommit_merges(self):
127
wt = self.create_simple_tree()
129
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
131
tree2.commit('unchanged', rev_id='b3')
132
tree2.commit('unchanged', rev_id='b4')
134
self.merge(tree2.branch, wt)
135
wt.commit('merge b4', rev_id='a3')
137
self.assertEqual(['a3'], wt.get_parent_ids())
140
out, err = self.run_bzr('uncommit', '--force')
142
self.assertEqual(['a2', 'b4'], wt.get_parent_ids())
144
def test_uncommit_multiple_merge(self):
145
wt = self.create_simple_tree()
147
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
149
tree2.commit('unchanged', rev_id='b3')
151
self.merge(tree2.branch, wt)
152
wt.commit('merge b3', rev_id='a3')
154
tree2.commit('unchanged', rev_id='b4')
156
self.merge(tree2.branch, wt)
157
wt.commit('merge b4', rev_id='a4')
159
self.assertEqual(['a4'], wt.get_parent_ids())
162
out, err = self.run_bzr('uncommit', '--force', '-r', '2')
164
self.assertEqual(['a2', 'b3', 'b4'], wt.get_parent_ids())
166
def test_uncommit_octopus_merge(self):
167
# Check that uncommit keeps the pending merges in the same order
168
wt = self.create_simple_tree()
170
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
171
tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
173
tree2.commit('unchanged', rev_id='b3')
174
tree3.commit('unchanged', rev_id='c3')
176
self.merge(tree2.branch, wt)
177
self.merge(tree3.branch, wt)
178
wt.commit('merge b3, c3', rev_id='a3')
180
tree2.commit('unchanged', rev_id='b4')
181
tree3.commit('unchanged', rev_id='c4')
183
self.merge(tree3.branch, wt)
184
self.merge(tree2.branch, wt)
185
wt.commit('merge b4, c4', rev_id='a4')
187
self.assertEqual(['a4'], wt.get_parent_ids())
190
out, err = self.run_bzr('uncommit', '--force', '-r', '2')
192
self.assertEqual(['a2', 'b3', 'c3', 'c4', 'b4'], wt.get_parent_ids())