~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_push.py

[merge] bzr.dev 2294

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2007 Canonical Ltd
 
2
#
 
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.
 
7
#
 
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.
 
12
#
 
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
 
16
 
 
17
 
 
18
"""Black-box tests for bzr push."""
 
19
 
 
20
import os
 
21
 
 
22
from bzrlib import (
 
23
    errors,
 
24
    urlutils,
 
25
    )
 
26
from bzrlib.branch import Branch
 
27
from bzrlib.bzrdir import BzrDirMetaFormat1
 
28
from bzrlib.osutils import abspath
 
29
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
 
30
from bzrlib.tests.blackbox import ExternalBase
 
31
from bzrlib.uncommit import uncommit
 
32
from bzrlib.urlutils import local_path_from_url
 
33
from bzrlib.workingtree import WorkingTree
 
34
 
 
35
 
 
36
class TestPush(ExternalBase):
 
37
 
 
38
    def test_push_remember(self):
 
39
        """Push changes from one branch to another and test push location."""
 
40
        transport = self.get_transport()
 
41
        tree_a = self.make_branch_and_tree('branch_a')
 
42
        branch_a = tree_a.branch
 
43
        self.build_tree(['branch_a/a'])
 
44
        tree_a.add('a')
 
45
        tree_a.commit('commit a')
 
46
        tree_b = branch_a.bzrdir.sprout('branch_b').open_workingtree()
 
47
        branch_b = tree_b.branch
 
48
        tree_c = branch_a.bzrdir.sprout('branch_c').open_workingtree()
 
49
        branch_c = tree_c.branch
 
50
        self.build_tree(['branch_a/b'])
 
51
        tree_a.add('b')
 
52
        tree_a.commit('commit b')
 
53
        self.build_tree(['branch_b/c'])
 
54
        tree_b.add('c')
 
55
        tree_b.commit('commit c')
 
56
        # initial push location must be empty
 
57
        self.assertEqual(None, branch_b.get_push_location())
 
58
 
 
59
        # test push for failure without push location set
 
60
        os.chdir('branch_a')
 
61
        out = self.runbzr('push', retcode=3)
 
62
        self.assertEquals(out,
 
63
                ('','bzr: ERROR: No push location known or specified.\n'))
 
64
 
 
65
        # test not remembered if cannot actually push
 
66
        self.run_bzr('push', '../path/which/doesnt/exist', retcode=3)
 
67
        out = self.run_bzr('push', retcode=3)
 
68
        self.assertEquals(
 
69
                ('', 'bzr: ERROR: No push location known or specified.\n'),
 
70
                out)
 
71
 
 
72
        # test implicit --remember when no push location set, push fails
 
73
        out = self.run_bzr('push', '../branch_b', retcode=3)
 
74
        self.assertEquals(out,
 
75
                ('','bzr: ERROR: These branches have diverged.  '
 
76
                    'Try using "merge" and then "push".\n'))
 
77
        self.assertEquals(abspath(branch_a.get_push_location()),
 
78
                          abspath(branch_b.bzrdir.root_transport.base))
 
79
 
 
80
        # test implicit --remember after resolving previous failure
 
81
        uncommit(branch=branch_b, tree=tree_b)
 
82
        transport.delete('branch_b/c')
 
83
        out = self.run_bzr('push')
 
84
        path = branch_a.get_push_location()
 
85
        self.assertEquals(('Using saved location: %s\n' 
 
86
                           % (local_path_from_url(path),)
 
87
                          , 'All changes applied successfully.\n'
 
88
                            '1 revision(s) pushed.\n'), out)
 
89
        self.assertEqual(path,
 
90
                         branch_b.bzrdir.root_transport.base)
 
91
        # test explicit --remember
 
92
        self.run_bzr('push', '../branch_c', '--remember')
 
93
        self.assertEquals(branch_a.get_push_location(),
 
94
                          branch_c.bzrdir.root_transport.base)
 
95
    
 
96
    def test_push_without_tree(self):
 
97
        # bzr push from a branch that does not have a checkout should work.
 
98
        b = self.make_branch('.')
 
99
        out, err = self.run_bzr('push', 'pushed-location')
 
100
        self.assertEqual('', out)
 
101
        self.assertEqual('0 revision(s) pushed.\n', err)
 
102
        b2 = Branch.open('pushed-location')
 
103
        self.assertEndsWith(b2.base, 'pushed-location/')
 
104
 
 
105
    def test_push_new_branch_revision_count(self):
 
106
        # bzr push of a branch with revisions to a new location 
 
107
        # should print the number of revisions equal to the length of the 
 
108
        # local branch.
 
109
        t = self.make_branch_and_tree('tree')
 
110
        self.build_tree(['tree/file'])
 
111
        t.add('file')
 
112
        t.commit('commit 1')
 
113
        os.chdir('tree')
 
114
        out, err = self.run_bzr('push', 'pushed-to')
 
115
        os.chdir('..')
 
116
        self.assertEqual('', out)
 
117
        self.assertEqual('1 revision(s) pushed.\n', err)
 
118
 
 
119
    def test_push_only_pushes_history(self):
 
120
        # Knit branches should only push the history for the current revision.
 
121
        format = BzrDirMetaFormat1()
 
122
        format.repository_format = RepositoryFormatKnit1()
 
123
        shared_repo = self.make_repository('repo', format=format, shared=True)
 
124
        shared_repo.set_make_working_trees(True)
 
125
 
 
126
        def make_shared_tree(path):
 
127
            shared_repo.bzrdir.root_transport.mkdir(path)
 
128
            shared_repo.bzrdir.create_branch_convenience('repo/' + path)
 
129
            return WorkingTree.open('repo/' + path)
 
130
        tree_a = make_shared_tree('a')
 
131
        self.build_tree(['repo/a/file'])
 
132
        tree_a.add('file')
 
133
        tree_a.commit('commit a-1', rev_id='a-1')
 
134
        f = open('repo/a/file', 'ab')
 
135
        f.write('more stuff\n')
 
136
        f.close()
 
137
        tree_a.commit('commit a-2', rev_id='a-2')
 
138
 
 
139
        tree_b = make_shared_tree('b')
 
140
        self.build_tree(['repo/b/file'])
 
141
        tree_b.add('file')
 
142
        tree_b.commit('commit b-1', rev_id='b-1')
 
143
 
 
144
        self.assertTrue(shared_repo.has_revision('a-1'))
 
145
        self.assertTrue(shared_repo.has_revision('a-2'))
 
146
        self.assertTrue(shared_repo.has_revision('b-1'))
 
147
 
 
148
        # Now that we have a repository with shared files, make sure
 
149
        # that things aren't copied out by a 'push'
 
150
        os.chdir('repo/b')
 
151
        self.run_bzr('push', '../../push-b')
 
152
        pushed_tree = WorkingTree.open('../../push-b')
 
153
        pushed_repo = pushed_tree.branch.repository
 
154
        self.assertFalse(pushed_repo.has_revision('a-1'))
 
155
        self.assertFalse(pushed_repo.has_revision('a-2'))
 
156
        self.assertTrue(pushed_repo.has_revision('b-1'))
 
157
 
 
158
    def test_push_funky_id(self):
 
159
        t = self.make_branch_and_tree('tree')
 
160
        os.chdir('tree')
 
161
        self.build_tree(['filename'])
 
162
        t.add('filename', 'funky-chars<>%&;"\'')
 
163
        t.commit('commit filename')
 
164
        self.run_bzr('push', '../new-tree')
 
165
 
 
166
    def test_push_dash_d(self):
 
167
        t = self.make_branch_and_tree('from')
 
168
        t.commit(allow_pointless=True,
 
169
                message='first commit')
 
170
        self.runbzr('push -d from to-one')
 
171
        self.failUnlessExists('to-one')
 
172
        self.runbzr('push -d %s %s' 
 
173
            % tuple(map(urlutils.local_path_to_url, ['from', 'to-two'])))
 
174
        self.failUnlessExists('to-two')
 
175
 
 
176
    def create_simple_tree(self):
 
177
        tree = self.make_branch_and_tree('tree')
 
178
        self.build_tree(['tree/a'])
 
179
        tree.add(['a'], ['a-id'])
 
180
        tree.commit('one', rev_id='r1')
 
181
        return tree
 
182
 
 
183
    def test_push_create_prefix(self):
 
184
        """'bzr push --create-prefix' will create leading directories."""
 
185
        tree = self.create_simple_tree()
 
186
 
 
187
        self.run_bzr_error(['Parent directory of ../new/tree does not exist'],
 
188
                           'push', '../new/tree',
 
189
                           working_dir='tree')
 
190
        self.run_bzr('push', '../new/tree', '--create-prefix',
 
191
                     working_dir='tree')
 
192
        new_tree = WorkingTree.open('new/tree')
 
193
        self.assertEqual(tree.last_revision(), new_tree.last_revision())
 
194
        self.failUnlessExists('new/tree/a')
 
195
 
 
196
    def test_push_use_existing(self):
 
197
        """'bzr push --use-existing-dir' can push into an existing dir.
 
198
 
 
199
        By default, 'bzr push' will not use an existing, non-versioned dir.
 
200
        """
 
201
        tree = self.create_simple_tree()
 
202
        self.build_tree(['target/'])
 
203
 
 
204
        self.run_bzr_error(['Target directory ../target already exists',
 
205
                            'Supply --use-existing-dir',
 
206
                           ], 'push', '../target',
 
207
                           working_dir='tree')
 
208
 
 
209
        self.run_bzr('push', '--use-existing-dir', '../target',
 
210
                     working_dir='tree')
 
211
 
 
212
        new_tree = WorkingTree.open('target')
 
213
        self.assertEqual(tree.last_revision(), new_tree.last_revision())
 
214
        # The push should have created target/a
 
215
        self.failUnlessExists('target/a')
 
216
 
 
217
    def test_push_onto_repo(self):
 
218
        """We should be able to 'bzr push' into an existing bzrdir."""
 
219
        tree = self.create_simple_tree()
 
220
        repo = self.make_repository('repo', shared=True)
 
221
 
 
222
        self.run_bzr('push', '../repo',
 
223
                     working_dir='tree')
 
224
 
 
225
        # Pushing onto an existing bzrdir will create a repository and
 
226
        # branch as needed, but will only create a working tree if there was
 
227
        # no BzrDir before.
 
228
        self.assertRaises(errors.NoWorkingTree, WorkingTree.open, 'repo')
 
229
        new_branch = Branch.open('repo')
 
230
        self.assertEqual(tree.last_revision(), new_branch.last_revision())
 
231
 
 
232
    def test_push_onto_just_bzrdir(self):
 
233
        """We don't handle when the target is just a bzrdir.
 
234
 
 
235
        Because you shouldn't be able to create *just* a bzrdir in the wild.
 
236
        """
 
237
        # TODO: jam 20070109 Maybe it would be better to create the repository
 
238
        #       if at this point
 
239
        tree = self.create_simple_tree()
 
240
        a_bzrdir = self.make_bzrdir('dir')
 
241
 
 
242
        self.run_bzr_error(['At ../dir you have a valid .bzr control'],
 
243
                'push', '../dir',
 
244
                working_dir='tree')