1
# Copyright (C) 2005, 2006 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):
29
def create_simple_tree(self):
30
wt = self.make_branch_and_tree('tree')
31
self.build_tree(['tree/a', 'tree/b', 'tree/c'])
32
wt.add(['a', 'b', 'c'])
33
wt.commit('initial commit', rev_id='a1')
35
open('tree/a', 'wb').write('new contents of a\n')
36
wt.commit('second commit', rev_id='a2')
40
def test_uncommit(self):
41
"""Test uncommit functionality."""
42
wt = self.create_simple_tree()
45
out, err = self.run_bzr('uncommit --dry-run --force')
46
self.assertContainsRe(out, 'Dry-run')
47
self.assertNotContainsRe(out, 'initial commit')
48
self.assertContainsRe(out, 'second commit')
51
self.assertEqual(['a2'], wt.get_parent_ids())
53
# Uncommit, don't prompt
54
out, err = self.run_bzr('uncommit --force')
55
self.assertNotContainsRe(out, 'initial commit')
56
self.assertContainsRe(out, 'second commit')
58
# This should look like we are back in revno 1
59
self.assertEqual(['a1'], wt.get_parent_ids())
60
out, err = self.run_bzr('status')
61
self.assertEquals(out, 'modified:\n a\n')
63
def test_uncommit_no_history(self):
64
wt = self.make_branch_and_tree('tree')
65
out, err = self.run_bzr('uncommit --force', retcode=1)
66
self.assertEqual('', err)
67
self.assertEqual('No revisions to uncommit.\n', out)
69
def test_uncommit_checkout(self):
70
wt = self.create_simple_tree()
71
checkout_tree = wt.branch.create_checkout('checkout')
73
self.assertEqual(['a2'], checkout_tree.get_parent_ids())
76
out, err = self.run_bzr('uncommit --dry-run --force')
77
self.assertContainsRe(out, 'Dry-run')
78
self.assertNotContainsRe(out, 'initial commit')
79
self.assertContainsRe(out, 'second commit')
81
self.assertEqual(['a2'], checkout_tree.get_parent_ids())
83
out, err = self.run_bzr('uncommit --force')
84
self.assertNotContainsRe(out, 'initial commit')
85
self.assertContainsRe(out, 'second commit')
87
# uncommit in a checkout should uncommit the parent branch
88
# (but doesn't effect the other working tree)
89
self.assertEquals(['a1'], checkout_tree.get_parent_ids())
90
self.assertEquals('a1', wt.branch.last_revision())
91
self.assertEquals(['a2'], wt.get_parent_ids())
93
def test_uncommit_bound(self):
95
a = BzrDirMetaFormat1().initialize('a')
98
t_a = a.create_workingtree()
99
t_a.commit('commit 1')
100
t_a.commit('commit 2')
101
t_a.commit('commit 3')
102
b = t_a.branch.create_checkout('b').branch
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.
108
t_a.commit('commit 3b')
109
self.assertRaises(BoundBranchOutOfDate, uncommit.uncommit, b)
113
def test_uncommit_revision(self):
114
wt = self.create_simple_tree()
117
out, err = self.run_bzr('uncommit -r1 --force')
119
self.assertNotContainsRe(out, 'initial commit')
120
self.assertContainsRe(out, 'second commit')
121
self.assertEqual(['a1'], wt.get_parent_ids())
122
self.assertEqual('a1', wt.branch.last_revision())
124
def test_uncommit_neg_1(self):
125
wt = self.create_simple_tree()
127
out, err = self.run_bzr('uncommit -r -1', retcode=1)
128
self.assertEqual('No revisions to uncommit.\n', out)
130
def test_uncommit_merges(self):
131
wt = self.create_simple_tree()
133
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
135
tree2.commit('unchanged', rev_id='b3')
136
tree2.commit('unchanged', rev_id='b4')
138
wt.merge_from_branch(tree2.branch)
139
wt.commit('merge b4', rev_id='a3')
141
self.assertEqual(['a3'], wt.get_parent_ids())
144
out, err = self.run_bzr('uncommit --force')
146
self.assertEqual(['a2', 'b4'], wt.get_parent_ids())
148
def test_uncommit_pending_merge(self):
149
wt = self.create_simple_tree()
150
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
151
tree2.commit('unchanged', rev_id='b3')
153
wt.branch.fetch(tree2.branch)
154
wt.set_pending_merges(['b3'])
157
out, err = self.run_bzr('uncommit --force')
158
self.assertEqual(['a1', 'b3'], wt.get_parent_ids())
160
def test_uncommit_multiple_merge(self):
161
wt = self.create_simple_tree()
163
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
165
tree2.commit('unchanged', rev_id='b3')
167
wt.merge_from_branch(tree2.branch)
168
wt.commit('merge b3', rev_id='a3')
170
tree2.commit('unchanged', rev_id='b4')
172
wt.merge_from_branch(tree2.branch)
173
wt.commit('merge b4', rev_id='a4')
175
self.assertEqual(['a4'], wt.get_parent_ids())
178
out, err = self.run_bzr('uncommit --force -r 2')
180
self.assertEqual(['a2', 'b3', 'b4'], wt.get_parent_ids())
182
def test_uncommit_merge_plus_pending(self):
183
wt = self.create_simple_tree()
185
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
187
tree2.commit('unchanged', rev_id='b3')
188
wt.branch.fetch(tree2.branch)
189
wt.set_pending_merges(['b3'])
190
wt.commit('merge b3', rev_id='a3')
192
tree2.commit('unchanged', rev_id='b4')
193
wt.branch.fetch(tree2.branch)
194
wt.set_pending_merges(['b4'])
196
self.assertEqual(['a3', 'b4'], wt.get_parent_ids())
199
out, err = self.run_bzr('uncommit --force -r 2')
201
self.assertEqual(['a2', 'b3', 'b4'], wt.get_parent_ids())
203
def test_uncommit_octopus_merge(self):
204
# Check that uncommit keeps the pending merges in the same order
205
wt = self.create_simple_tree()
207
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
208
tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
210
tree2.commit('unchanged', rev_id='b3')
211
tree3.commit('unchanged', rev_id='c3')
213
wt.merge_from_branch(tree2.branch)
214
wt.merge_from_branch(tree3.branch)
215
wt.commit('merge b3, c3', rev_id='a3')
217
tree2.commit('unchanged', rev_id='b4')
218
tree3.commit('unchanged', rev_id='c4')
220
wt.merge_from_branch(tree3.branch)
221
wt.merge_from_branch(tree2.branch)
222
wt.commit('merge b4, c4', rev_id='a4')
224
self.assertEqual(['a4'], wt.get_parent_ids())
227
out, err = self.run_bzr('uncommit --force -r 2')
229
self.assertEqual(['a2', 'b3', 'c3', 'c4', 'b4'], wt.get_parent_ids())