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_checkout(self):
 
 
64
        wt = self.create_simple_tree()
 
 
65
        checkout_tree = wt.branch.create_checkout('checkout')
 
 
67
        self.assertEqual(['a2'], checkout_tree.get_parent_ids())
 
 
70
        out, err = self.run_bzr('uncommit', '--dry-run', '--force')
 
 
71
        self.assertContainsRe(out, 'Dry-run')
 
 
72
        self.assertNotContainsRe(out, 'initial commit')
 
 
73
        self.assertContainsRe(out, 'second commit')
 
 
75
        self.assertEqual(['a2'], checkout_tree.get_parent_ids())
 
 
77
        out, err = self.run_bzr('uncommit', '--force')
 
 
78
        self.assertNotContainsRe(out, 'initial commit')
 
 
79
        self.assertContainsRe(out, 'second commit')
 
 
81
        # uncommit in a checkout should uncommit the parent branch
 
 
82
        # (but doesn't effect the other working tree)
 
 
83
        self.assertEquals(['a1'], checkout_tree.get_parent_ids())
 
 
84
        self.assertEquals('a1', wt.branch.last_revision())
 
 
85
        self.assertEquals(['a2'], wt.get_parent_ids())
 
 
87
    def test_uncommit_bound(self):
 
 
89
        a = BzrDirMetaFormat1().initialize('a')
 
 
92
        t_a = a.create_workingtree()
 
 
93
        t_a.commit('commit 1')
 
 
94
        t_a.commit('commit 2')
 
 
95
        t_a.commit('commit 3')
 
 
96
        b = t_a.branch.create_checkout('b').branch
 
 
98
        self.assertEqual(len(b.revision_history()), 2)
 
 
99
        self.assertEqual(len(t_a.branch.revision_history()), 2)
 
 
100
        # update A's tree to not have the uncomitted revision referenced.
 
 
102
        t_a.commit('commit 3b')
 
 
103
        self.assertRaises(BoundBranchOutOfDate, uncommit.uncommit, b)
 
 
107
    def test_uncommit_revision(self):
 
 
108
        wt = self.create_simple_tree()
 
 
111
        out, err = self.run_bzr('uncommit', '-r1', '--force')
 
 
113
        self.assertNotContainsRe(out, 'initial commit')
 
 
114
        self.assertContainsRe(out, 'second commit')
 
 
115
        self.assertEqual(['a1'], wt.get_parent_ids())
 
 
116
        self.assertEqual('a1', wt.branch.last_revision())
 
 
118
    def test_uncommit_neg_1(self):
 
 
119
        wt = self.create_simple_tree()
 
 
121
        out, err = self.run_bzr('uncommit', '-r', '-1', retcode=1)
 
 
122
        self.assertEqual('No revisions to uncommit.\n', out)
 
 
124
    def test_uncommit_merges(self):
 
 
125
        wt = self.create_simple_tree()
 
 
127
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
 
 
129
        tree2.commit('unchanged', rev_id='b3')
 
 
130
        tree2.commit('unchanged', rev_id='b4')
 
 
132
        wt.merge_from_branch(tree2.branch)
 
 
133
        wt.commit('merge b4', rev_id='a3')
 
 
135
        self.assertEqual(['a3'], wt.get_parent_ids())
 
 
138
        out, err = self.run_bzr('uncommit', '--force')
 
 
140
        self.assertEqual(['a2', 'b4'], wt.get_parent_ids())
 
 
142
    def test_uncommit_pending_merge(self):
 
 
143
        wt = self.create_simple_tree()
 
 
144
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
 
 
145
        tree2.commit('unchanged', rev_id='b3')
 
 
147
        wt.branch.fetch(tree2.branch)
 
 
148
        wt.set_pending_merges(['b3'])
 
 
151
        out, err = self.run_bzr('uncommit', '--force')
 
 
152
        self.assertEqual(['a1', 'b3'], wt.get_parent_ids())
 
 
154
    def test_uncommit_multiple_merge(self):
 
 
155
        wt = self.create_simple_tree()
 
 
157
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
 
 
159
        tree2.commit('unchanged', rev_id='b3')
 
 
161
        wt.merge_from_branch(tree2.branch)
 
 
162
        wt.commit('merge b3', rev_id='a3')
 
 
164
        tree2.commit('unchanged', rev_id='b4')
 
 
166
        wt.merge_from_branch(tree2.branch)
 
 
167
        wt.commit('merge b4', rev_id='a4')
 
 
169
        self.assertEqual(['a4'], wt.get_parent_ids())
 
 
172
        out, err = self.run_bzr('uncommit', '--force', '-r', '2')
 
 
174
        self.assertEqual(['a2', 'b3', 'b4'], wt.get_parent_ids())
 
 
176
    def test_uncommit_merge_plus_pending(self):
 
 
177
        wt = self.create_simple_tree()
 
 
179
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
 
 
181
        tree2.commit('unchanged', rev_id='b3')
 
 
182
        wt.branch.fetch(tree2.branch)
 
 
183
        wt.set_pending_merges(['b3'])
 
 
184
        wt.commit('merge b3', rev_id='a3')
 
 
186
        tree2.commit('unchanged', rev_id='b4')
 
 
187
        wt.branch.fetch(tree2.branch)
 
 
188
        wt.set_pending_merges(['b4'])
 
 
190
        self.assertEqual(['a3', 'b4'], wt.get_parent_ids())
 
 
193
        out, err = self.run_bzr('uncommit', '--force', '-r', '2')
 
 
195
        self.assertEqual(['a2', 'b3', 'b4'], wt.get_parent_ids())
 
 
197
    def test_uncommit_octopus_merge(self):
 
 
198
        # Check that uncommit keeps the pending merges in the same order
 
 
199
        wt = self.create_simple_tree()
 
 
201
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
 
 
202
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
 
 
204
        tree2.commit('unchanged', rev_id='b3')
 
 
205
        tree3.commit('unchanged', rev_id='c3')
 
 
207
        wt.merge_from_branch(tree2.branch)
 
 
208
        wt.merge_from_branch(tree3.branch)
 
 
209
        wt.commit('merge b3, c3', rev_id='a3')
 
 
211
        tree2.commit('unchanged', rev_id='b4')
 
 
212
        tree3.commit('unchanged', rev_id='c4')
 
 
214
        wt.merge_from_branch(tree3.branch)
 
 
215
        wt.merge_from_branch(tree2.branch)
 
 
216
        wt.commit('merge b4, c4', rev_id='a4')
 
 
218
        self.assertEqual(['a4'], wt.get_parent_ids())
 
 
221
        out, err = self.run_bzr('uncommit', '--force', '-r', '2')
 
 
223
        self.assertEqual(['a2', 'b3', 'c3', 'c4', 'b4'], wt.get_parent_ids())