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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
"""Black-box tests for bzr push."""
23
22
from bzrlib import (
27
from bzrlib.branch import Branch
28
from bzrlib.bzrdir import BzrDirMetaFormat1
29
from bzrlib.osutils import abspath
30
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
31
from bzrlib.tests.blackbox import ExternalBase
32
from bzrlib.tests.http_server import HttpServer
33
from bzrlib.transport import register_transport, unregister_transport
34
from bzrlib.transport.memory import MemoryServer, MemoryTransport
35
from bzrlib.uncommit import uncommit
36
from bzrlib.urlutils import local_path_from_url
37
from bzrlib.workingtree import WorkingTree
40
class TestPush(ExternalBase):
34
from bzrlib.repofmt import knitrepo
35
from bzrlib.tests import (
41
from bzrlib.tests.matchers import ContainsNoVfsCalls
42
from bzrlib.transport import memory
45
load_tests = scenarios.load_tests_apply_scenarios
48
class TestPush(tests.TestCaseWithTransport):
50
def test_push_error_on_vfs_http(self):
51
""" pushing a branch to a HTTP server fails cleanly. """
52
# the trunk is published on a web server
53
self.transport_readonly_server = http_server.HttpServer
54
self.make_branch('source')
55
public_url = self.get_readonly_url('target')
56
self.run_bzr_error(['http does not support mkdir'],
60
def test_push_suggests_parent_alias(self):
61
"""Push suggests using :parent if there is a known parent branch."""
62
tree_a = self.make_branch_and_tree('a')
63
tree_a.commit('this is a commit')
64
tree_b = self.make_branch_and_tree('b')
66
# If there is no parent location set, :parent isn't mentioned.
67
out = self.run_bzr('push', working_dir='a', retcode=3)
68
self.assertEquals(out,
69
('','bzr: ERROR: No push location known or specified.\n'))
71
# If there is a parent location set, the error suggests :parent.
72
tree_a.branch.set_parent(tree_b.branch.base)
73
out = self.run_bzr('push', working_dir='a', retcode=3)
74
self.assertEquals(out,
75
('','bzr: ERROR: No push location known or specified. '
76
'To push to the parent branch '
77
'(at %s), use \'bzr push :parent\'.\n' %
78
urlutils.unescape_for_display(tree_b.branch.base, 'utf-8')))
42
80
def test_push_remember(self):
43
81
"""Push changes from one branch to another and test push location."""
61
99
self.assertEqual(None, branch_b.get_push_location())
63
101
# test push for failure without push location set
65
out = self.run_bzr('push', retcode=3)
102
out = self.run_bzr('push', working_dir='branch_a', retcode=3)
66
103
self.assertEquals(out,
67
104
('','bzr: ERROR: No push location known or specified.\n'))
69
106
# test not remembered if cannot actually push
70
self.run_bzr('push ../path/which/doesnt/exist', retcode=3)
71
out = self.run_bzr('push', retcode=3)
107
self.run_bzr('push path/which/doesnt/exist',
108
working_dir='branch_a', retcode=3)
109
out = self.run_bzr('push', working_dir='branch_a', retcode=3)
72
110
self.assertEquals(
73
111
('', 'bzr: ERROR: No push location known or specified.\n'),
76
114
# test implicit --remember when no push location set, push fails
77
out = self.run_bzr('push ../branch_b', retcode=3)
115
out = self.run_bzr('push ../branch_b',
116
working_dir='branch_a', retcode=3)
78
117
self.assertEquals(out,
79
118
('','bzr: ERROR: These branches have diverged. '
80
'Try using "merge" and then "push".\n'))
81
self.assertEquals(abspath(branch_a.get_push_location()),
82
abspath(branch_b.bzrdir.root_transport.base))
119
'See "bzr help diverged-branches" for more information.\n'))
120
# Refresh the branch as 'push' modified it
121
branch_a = branch_a.bzrdir.open_branch()
122
self.assertEquals(osutils.abspath(branch_a.get_push_location()),
123
osutils.abspath(branch_b.bzrdir.root_transport.base))
84
125
# test implicit --remember after resolving previous failure
85
uncommit(branch=branch_b, tree=tree_b)
126
uncommit.uncommit(branch=branch_b, tree=tree_b)
86
127
transport.delete('branch_b/c')
87
out, err = self.run_bzr('push')
128
out, err = self.run_bzr('push', working_dir='branch_a')
129
# Refresh the branch as 'push' modified it
130
branch_a = branch_a.bzrdir.open_branch()
88
131
path = branch_a.get_push_location()
89
self.assertEquals(out,
90
'Using saved push location: %s\n'
91
'Pushed up to revision 2.\n'
92
% local_path_from_url(path))
93
132
self.assertEqual(err,
94
'All changes applied successfully.\n')
133
'Using saved push location: %s\n'
134
'All changes applied successfully.\n'
135
'Pushed up to revision 2.\n'
136
% urlutils.local_path_from_url(path))
95
137
self.assertEqual(path,
96
138
branch_b.bzrdir.root_transport.base)
97
139
# test explicit --remember
98
self.run_bzr('push ../branch_c --remember')
140
self.run_bzr('push ../branch_c --remember', working_dir='branch_a')
141
# Refresh the branch as 'push' modified it
142
branch_a = branch_a.bzrdir.open_branch()
99
143
self.assertEquals(branch_a.get_push_location(),
100
144
branch_c.bzrdir.root_transport.base)
102
146
def test_push_without_tree(self):
103
147
# bzr push from a branch that does not have a checkout should work.
104
148
b = self.make_branch('.')
105
149
out, err = self.run_bzr('push pushed-location')
106
150
self.assertEqual('', out)
107
151
self.assertEqual('Created new branch.\n', err)
108
b2 = Branch.open('pushed-location')
152
b2 = branch.Branch.open('pushed-location')
109
153
self.assertEndsWith(b2.base, 'pushed-location/')
155
def test_push_no_tree(self):
156
# bzr push --no-tree of a branch with working trees
157
b = self.make_branch_and_tree('push-from')
158
self.build_tree(['push-from/file'])
161
out, err = self.run_bzr('push --no-tree -d push-from push-to')
162
self.assertEqual('', out)
163
self.assertEqual('Created new branch.\n', err)
164
self.assertPathDoesNotExist('push-to/file')
111
166
def test_push_new_branch_revision_count(self):
112
# bzr push of a branch with revisions to a new location
113
# should print the number of revisions equal to the length of the
167
# bzr push of a branch with revisions to a new location
168
# should print the number of revisions equal to the length of the
115
170
t = self.make_branch_and_tree('tree')
116
171
self.build_tree(['tree/file'])
118
173
t.commit('commit 1')
120
out, err = self.run_bzr('push pushed-to')
174
out, err = self.run_bzr('push -d tree pushed-to')
122
175
self.assertEqual('', out)
123
176
self.assertEqual('Created new branch.\n', err)
178
def test_push_quiet(self):
179
# test that using -q makes output quiet
180
t = self.make_branch_and_tree('tree')
181
self.build_tree(['tree/file'])
184
self.run_bzr('push -d tree pushed-to')
185
# Refresh the branch as 'push' modified it and get the push location
186
push_loc = t.branch.bzrdir.open_branch().get_push_location()
187
out, err = self.run_bzr('push', working_dir="tree")
188
self.assertEqual('Using saved push location: %s\n'
189
'No new revisions or tags to push.\n' %
190
urlutils.local_path_from_url(push_loc), err)
191
out, err = self.run_bzr('push -q', working_dir="tree")
192
self.assertEqual('', out)
193
self.assertEqual('', err)
125
195
def test_push_only_pushes_history(self):
126
196
# Knit branches should only push the history for the current revision.
127
format = BzrDirMetaFormat1()
128
format.repository_format = RepositoryFormatKnit1()
197
format = bzrdir.BzrDirMetaFormat1()
198
format.repository_format = knitrepo.RepositoryFormatKnit1()
129
199
shared_repo = self.make_repository('repo', format=format, shared=True)
130
200
shared_repo.set_make_working_trees(True)
132
202
def make_shared_tree(path):
133
203
shared_repo.bzrdir.root_transport.mkdir(path)
134
shared_repo.bzrdir.create_branch_convenience('repo/' + path)
135
return WorkingTree.open('repo/' + path)
204
controldir.ControlDir.create_branch_convenience('repo/' + path)
205
return workingtree.WorkingTree.open('repo/' + path)
136
206
tree_a = make_shared_tree('a')
137
207
self.build_tree(['repo/a/file'])
138
208
tree_a.add('file')
164
233
def test_push_funky_id(self):
165
234
t = self.make_branch_and_tree('tree')
167
self.build_tree(['filename'])
235
self.build_tree(['tree/filename'])
168
236
t.add('filename', 'funky-chars<>%&;"\'')
169
237
t.commit('commit filename')
170
self.run_bzr('push ../new-tree')
238
self.run_bzr('push -d tree new-tree')
172
240
def test_push_dash_d(self):
173
241
t = self.make_branch_and_tree('from')
174
242
t.commit(allow_pointless=True,
175
243
message='first commit')
176
244
self.run_bzr('push -d from to-one')
177
self.failUnlessExists('to-one')
178
self.run_bzr('push -d %s %s'
245
self.assertPathExists('to-one')
246
self.run_bzr('push -d %s %s'
179
247
% tuple(map(urlutils.local_path_to_url, ['from', 'to-two'])))
180
self.failUnlessExists('to-two')
248
self.assertPathExists('to-two')
250
def test_push_repository_no_branch_doesnt_fetch_all_revs(self):
251
# See https://bugs.launchpad.net/bzr/+bug/465517
252
target_repo = self.make_repository('target')
253
source = self.make_branch_builder('source')
254
source.start_series()
255
source.build_snapshot('A', None, [
256
('add', ('', 'root-id', 'directory', None))])
257
source.build_snapshot('B', ['A'], [])
258
source.build_snapshot('C', ['A'], [])
259
source.finish_series()
260
self.run_bzr('push target -d source')
261
self.addCleanup(target_repo.lock_read().unlock)
262
# We should have pushed 'C', but not 'B', since it isn't in the
264
self.assertEqual([('A',), ('C',)], sorted(target_repo.revisions.keys()))
266
def test_push_smart_non_stacked_streaming_acceptance(self):
267
self.setup_smart_server_with_call_log()
268
t = self.make_branch_and_tree('from')
269
t.commit(allow_pointless=True, message='first commit')
270
self.reset_smart_call_log()
271
self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
272
# This figure represent the amount of work to perform this use case. It
273
# is entirely ok to reduce this number if a test fails due to rpc_count
274
# being too low. If rpc_count increases, more network roundtrips have
275
# become necessary for this use case. Please do not adjust this number
276
# upwards without agreement from bzr's network support maintainers.
277
self.assertLength(9, self.hpss_calls)
278
self.assertLength(1, self.hpss_connections)
279
self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
281
def test_push_smart_stacked_streaming_acceptance(self):
282
self.setup_smart_server_with_call_log()
283
parent = self.make_branch_and_tree('parent', format='1.9')
284
parent.commit(message='first commit')
285
local = parent.bzrdir.sprout('local').open_workingtree()
286
local.commit(message='local commit')
287
self.reset_smart_call_log()
288
self.run_bzr(['push', '--stacked', '--stacked-on', '../parent',
289
self.get_url('public')], working_dir='local')
290
# This figure represent the amount of work to perform this use case. It
291
# is entirely ok to reduce this number if a test fails due to rpc_count
292
# being too low. If rpc_count increases, more network roundtrips have
293
# become necessary for this use case. Please do not adjust this number
294
# upwards without agreement from bzr's network support maintainers.
295
self.assertLength(15, self.hpss_calls)
296
self.assertLength(1, self.hpss_connections)
297
self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
298
remote = branch.Branch.open('public')
299
self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
301
def test_push_smart_tags_streaming_acceptance(self):
302
self.setup_smart_server_with_call_log()
303
t = self.make_branch_and_tree('from')
304
rev_id = t.commit(allow_pointless=True, message='first commit')
305
t.branch.tags.set_tag('new-tag', rev_id)
306
self.reset_smart_call_log()
307
self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
308
# This figure represent the amount of work to perform this use case. It
309
# is entirely ok to reduce this number if a test fails due to rpc_count
310
# being too low. If rpc_count increases, more network roundtrips have
311
# become necessary for this use case. Please do not adjust this number
312
# upwards without agreement from bzr's network support maintainers.
313
self.assertLength(11, self.hpss_calls)
314
self.assertLength(1, self.hpss_connections)
315
self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
317
def test_push_smart_incremental_acceptance(self):
318
self.setup_smart_server_with_call_log()
319
t = self.make_branch_and_tree('from')
320
rev_id1 = t.commit(allow_pointless=True, message='first commit')
321
rev_id2 = t.commit(allow_pointless=True, message='second commit')
323
['push', self.get_url('to-one'), '-r1'], working_dir='from')
324
self.reset_smart_call_log()
325
self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
326
# This figure represent the amount of work to perform this use case. It
327
# is entirely ok to reduce this number if a test fails due to rpc_count
328
# being too low. If rpc_count increases, more network roundtrips have
329
# become necessary for this use case. Please do not adjust this number
330
# upwards without agreement from bzr's network support maintainers.
331
self.assertLength(11, self.hpss_calls)
332
self.assertLength(1, self.hpss_connections)
333
self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
335
def test_push_smart_with_default_stacking_url_path_segment(self):
336
# If the default stacked-on location is a path element then branches
337
# we push there over the smart server are stacked and their
338
# stacked_on_url is that exact path segment. Added to nail bug 385132.
339
self.setup_smart_server_with_call_log()
340
self.make_branch('stack-on', format='1.9')
341
self.make_bzrdir('.').get_config().set_default_stack_on(
343
self.make_branch('from', format='1.9')
344
out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
345
b = branch.Branch.open(self.get_url('to'))
346
self.assertEqual('/extra/stack-on', b.get_stacked_on_url())
348
def test_push_smart_with_default_stacking_relative_path(self):
349
# If the default stacked-on location is a relative path then branches
350
# we push there over the smart server are stacked and their
351
# stacked_on_url is a relative path. Added to nail bug 385132.
352
self.setup_smart_server_with_call_log()
353
self.make_branch('stack-on', format='1.9')
354
self.make_bzrdir('.').get_config().set_default_stack_on('stack-on')
355
self.make_branch('from', format='1.9')
356
out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
357
b = branch.Branch.open(self.get_url('to'))
358
self.assertEqual('../stack-on', b.get_stacked_on_url())
182
360
def create_simple_tree(self):
183
361
tree = self.make_branch_and_tree('tree')
343
538
self.assertFalse(self.get_transport('published').has('.'))
345
540
def test_push_notifies_default_stacking(self):
346
self.make_branch('stack_on', format='development1')
541
self.make_branch('stack_on', format='1.6')
347
542
self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
348
self.make_branch('from', format='development1')
543
self.make_branch('from', format='1.6')
349
544
out, err = self.run_bzr('push -d from to')
350
545
self.assertContainsRe(err,
351
546
'Using default stacking branch stack_on at .*')
354
class RedirectingMemoryTransport(MemoryTransport):
356
def mkdir(self, path, mode=None):
357
path = self.abspath(path)[len(self._scheme):]
358
if path == '/source':
359
raise errors.RedirectRequested(
360
path, self._scheme + '/target', is_permanent=True)
361
elif path == '/infinite-loop':
362
raise errors.RedirectRequested(
363
path, self._scheme + '/infinite-loop', is_permanent=True)
548
def test_push_stacks_with_default_stacking_if_target_is_stackable(self):
549
self.make_branch('stack_on', format='1.6')
550
self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
551
self.make_branch('from', format='pack-0.92')
552
out, err = self.run_bzr('push -d from to')
553
b = branch.Branch.open('to')
554
self.assertEqual('../stack_on', b.get_stacked_on_url())
556
def test_push_does_not_change_format_with_default_if_target_cannot(self):
557
self.make_branch('stack_on', format='pack-0.92')
558
self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
559
self.make_branch('from', format='pack-0.92')
560
out, err = self.run_bzr('push -d from to')
561
b = branch.Branch.open('to')
562
self.assertRaises(errors.UnstackableBranchFormat, b.get_stacked_on_url)
564
def test_push_doesnt_create_broken_branch(self):
565
"""Pushing a new standalone branch works even when there's a default
566
stacking policy at the destination.
568
The new branch will preserve the repo format (even if it isn't the
569
default for the branch), and will be stacked when the repo format
570
allows (which means that the branch format isn't necessarly preserved).
572
self.make_repository('repo', shared=True, format='1.6')
573
builder = self.make_branch_builder('repo/local', format='pack-0.92')
574
builder.start_series()
575
builder.build_snapshot('rev-1', None, [
576
('add', ('', 'root-id', 'directory', '')),
577
('add', ('filename', 'f-id', 'file', 'content\n'))])
578
builder.build_snapshot('rev-2', ['rev-1'], [])
579
builder.build_snapshot('rev-3', ['rev-2'],
580
[('modify', ('f-id', 'new-content\n'))])
581
builder.finish_series()
582
branch = builder.get_branch()
583
# Push rev-1 to "trunk", so that we can stack on it.
584
self.run_bzr('push -d repo/local trunk -r 1')
585
# Set a default stacking policy so that new branches will automatically
587
self.make_bzrdir('.').get_config().set_default_stack_on('trunk')
588
# Push rev-2 to a new branch "remote". It will be stacked on "trunk".
589
out, err = self.run_bzr('push -d repo/local remote -r 2')
590
self.assertContainsRe(
591
err, 'Using default stacking branch trunk at .*')
592
# Push rev-3 onto "remote". If "remote" not stacked and is missing the
593
# fulltext record for f-id @ rev-1, then this will fail.
594
out, err = self.run_bzr('push -d repo/local remote -r 3')
596
def test_push_verbose_shows_log(self):
597
tree = self.make_branch_and_tree('source')
599
out, err = self.run_bzr('push -v -d source target')
600
# initial push contains log
601
self.assertContainsRe(out, 'rev1')
603
out, err = self.run_bzr('push -v -d source target')
604
# subsequent push contains log
605
self.assertContainsRe(out, 'rev2')
606
# subsequent log is accurate
607
self.assertNotContainsRe(out, 'rev1')
609
def test_push_from_subdir(self):
610
t = self.make_branch_and_tree('tree')
611
self.build_tree(['tree/dir/', 'tree/dir/file'])
612
t.add('dir', 'dir/file')
614
out, err = self.run_bzr('push ../../pushloc', working_dir='tree/dir')
615
self.assertEqual('', out)
616
self.assertEqual('Created new branch.\n', err)
618
def test_overwrite_tags(self):
619
"""--overwrite-tags only overwrites tags, not revisions."""
620
from_tree = self.make_branch_and_tree('from')
621
from_tree.branch.tags.set_tag("mytag", "somerevid")
622
to_tree = self.make_branch_and_tree('to')
623
to_tree.branch.tags.set_tag("mytag", "anotherrevid")
624
revid1 = to_tree.commit('my commit')
625
out = self.run_bzr(['push', '-d', 'from', 'to'])
626
self.assertEquals(out,
627
('Conflicting tags:\n mytag\n', 'No new revisions to push.\n'))
628
out = self.run_bzr(['push', '-d', 'from', '--overwrite-tags', 'to'])
629
self.assertEquals(out, ('', '1 tag updated.\n'))
630
self.assertEquals(to_tree.branch.tags.lookup_tag('mytag'),
632
self.assertEquals(to_tree.branch.last_revision(), revid1)
635
class RedirectingMemoryTransport(memory.MemoryTransport):
637
def mkdir(self, relpath, mode=None):
638
if self._cwd == '/source/':
639
raise errors.RedirectRequested(self.abspath(relpath),
640
self.abspath('../target'),
642
elif self._cwd == '/infinite-loop/':
643
raise errors.RedirectRequested(self.abspath(relpath),
644
self.abspath('../infinite-loop'),
365
647
return super(RedirectingMemoryTransport, self).mkdir(
369
class RedirectingMemoryServer(MemoryServer):
650
def get(self, relpath):
651
if self.clone(relpath)._cwd == '/infinite-loop/':
652
raise errors.RedirectRequested(self.abspath(relpath),
653
self.abspath('../infinite-loop'),
656
return super(RedirectingMemoryTransport, self).get(relpath)
658
def _redirected_to(self, source, target):
659
# We do accept redirections
660
return transport.get_transport(target)
663
class RedirectingMemoryServer(memory.MemoryServer):
665
def start_server(self):
372
666
self._dirs = {'/': None}
375
669
self._scheme = 'redirecting-memory+%s:///' % id(self)
376
register_transport(self._scheme, self._memory_factory)
670
transport.register_transport(self._scheme, self._memory_factory)
378
672
def _memory_factory(self, url):
379
673
result = RedirectingMemoryTransport(url)
420
710
"""Push fails gracefully if the mkdir generates a large number of
424
713
destination_url = self.memory_server.get_url() + 'infinite-loop'
425
714
out, err = self.run_bzr_error(
426
715
['Too many redirections trying to make %s\\.\n'
427
716
% re.escape(destination_url)],
428
'push %s' % destination_url, retcode=3)
717
['push', '-d', 'tree', destination_url], retcode=3)
430
718
self.assertEqual('', out)
721
class TestPushStrictMixin(object):
723
def make_local_branch_and_tree(self):
724
self.tree = self.make_branch_and_tree('local')
725
self.build_tree_contents([('local/file', 'initial')])
726
self.tree.add('file')
727
self.tree.commit('adding file', rev_id='added')
728
self.build_tree_contents([('local/file', 'modified')])
729
self.tree.commit('modify file', rev_id='modified')
731
def set_config_push_strict(self, value):
732
br = branch.Branch.open('local')
733
br.get_config_stack().set('push_strict', value)
735
_default_command = ['push', '../to']
736
_default_wd = 'local'
737
_default_errors = ['Working tree ".*/local/" has uncommitted '
738
'changes \(See bzr status\)\.',]
739
_default_additional_error = 'Use --no-strict to force the push.\n'
740
_default_additional_warning = 'Uncommitted changes will not be pushed.'
743
def assertPushFails(self, args):
744
out, err = self.run_bzr_error(self._default_errors,
745
self._default_command + args,
746
working_dir=self._default_wd, retcode=3)
747
self.assertContainsRe(err, self._default_additional_error)
749
def assertPushSucceeds(self, args, with_warning=False, revid_to_push=None):
751
error_regexes = self._default_errors
754
out, err = self.run_bzr(self._default_command + args,
755
working_dir=self._default_wd,
756
error_regexes=error_regexes)
758
self.assertContainsRe(err, self._default_additional_warning)
760
self.assertNotContainsRe(err, self._default_additional_warning)
761
branch_from = branch.Branch.open(self._default_wd)
762
if revid_to_push is None:
763
revid_to_push = branch_from.last_revision()
764
branch_to = branch.Branch.open('to')
765
repo_to = branch_to.repository
766
self.assertTrue(repo_to.has_revision(revid_to_push))
767
self.assertEqual(revid_to_push, branch_to.last_revision())
771
class TestPushStrictWithoutChanges(tests.TestCaseWithTransport,
772
TestPushStrictMixin):
775
super(TestPushStrictWithoutChanges, self).setUp()
776
self.make_local_branch_and_tree()
778
def test_push_default(self):
779
self.assertPushSucceeds([])
781
def test_push_strict(self):
782
self.assertPushSucceeds(['--strict'])
784
def test_push_no_strict(self):
785
self.assertPushSucceeds(['--no-strict'])
787
def test_push_config_var_strict(self):
788
self.set_config_push_strict('true')
789
self.assertPushSucceeds([])
791
def test_push_config_var_no_strict(self):
792
self.set_config_push_strict('false')
793
self.assertPushSucceeds([])
796
strict_push_change_scenarios = [
798
dict(_changes_type= '_uncommitted_changes')),
800
dict(_changes_type= '_pending_merges')),
801
('out-of-sync-trees',
802
dict(_changes_type= '_out_of_sync_trees')),
806
class TestPushStrictWithChanges(tests.TestCaseWithTransport,
807
TestPushStrictMixin):
809
scenarios = strict_push_change_scenarios
810
_changes_type = None # Set by load_tests
813
super(TestPushStrictWithChanges, self).setUp()
814
# Apply the changes defined in load_tests: one of _uncommitted_changes,
815
# _pending_merges or _out_of_sync_trees
816
getattr(self, self._changes_type)()
818
def _uncommitted_changes(self):
819
self.make_local_branch_and_tree()
820
# Make a change without committing it
821
self.build_tree_contents([('local/file', 'in progress')])
823
def _pending_merges(self):
824
self.make_local_branch_and_tree()
825
# Create 'other' branch containing a new file
826
other_bzrdir = self.tree.bzrdir.sprout('other')
827
other_tree = other_bzrdir.open_workingtree()
828
self.build_tree_contents([('other/other-file', 'other')])
829
other_tree.add('other-file')
830
other_tree.commit('other commit', rev_id='other')
831
# Merge and revert, leaving a pending merge
832
self.tree.merge_from_branch(other_tree.branch)
833
self.tree.revert(filenames=['other-file'], backups=False)
835
def _out_of_sync_trees(self):
836
self.make_local_branch_and_tree()
837
self.run_bzr(['checkout', '--lightweight', 'local', 'checkout'])
838
# Make a change and commit it
839
self.build_tree_contents([('local/file', 'modified in local')])
840
self.tree.commit('modify file', rev_id='modified-in-local')
841
# Exercise commands from the checkout directory
842
self._default_wd = 'checkout'
843
self._default_errors = ["Working tree is out of date, please run"
846
def test_push_default(self):
847
self.assertPushSucceeds([], with_warning=True)
849
def test_push_with_revision(self):
850
self.assertPushSucceeds(['-r', 'revid:added'], revid_to_push='added')
852
def test_push_no_strict(self):
853
self.assertPushSucceeds(['--no-strict'])
855
def test_push_strict_with_changes(self):
856
self.assertPushFails(['--strict'])
858
def test_push_respect_config_var_strict(self):
859
self.set_config_push_strict('true')
860
self.assertPushFails([])
862
def test_push_bogus_config_var_ignored(self):
863
self.set_config_push_strict("I don't want you to be strict")
864
self.assertPushSucceeds([], with_warning=True)
866
def test_push_no_strict_command_line_override_config(self):
867
self.set_config_push_strict('yES')
868
self.assertPushFails([])
869
self.assertPushSucceeds(['--no-strict'])
871
def test_push_strict_command_line_override_config(self):
872
self.set_config_push_strict('oFF')
873
self.assertPushFails(['--strict'])
874
self.assertPushSucceeds([])
877
class TestPushForeign(tests.TestCaseWithTransport):
880
super(TestPushForeign, self).setUp()
881
test_foreign.register_dummy_foreign_for_test(self)
883
def make_dummy_builder(self, relpath):
884
builder = self.make_branch_builder(
885
relpath, format=test_foreign.DummyForeignVcsDirFormat())
886
builder.build_snapshot('revid', None,
887
[('add', ('', 'TREE_ROOT', 'directory', None)),
888
('add', ('foo', 'fooid', 'file', 'bar'))])
891
def test_no_roundtripping(self):
892
target_branch = self.make_dummy_builder('dp').get_branch()
893
source_tree = self.make_branch_and_tree("dc")
894
output, error = self.run_bzr("push -d dc dp", retcode=3)
895
self.assertEquals("", output)
896
self.assertEquals(error, "bzr: ERROR: It is not possible to losslessly"
897
" push to dummy. You may want to use dpush instead.\n")
900
class TestPushOutput(script.TestCaseWithTransportAndScript):
902
def test_push_log_format(self):
905
Created a standalone tree (format: 2a)
910
$ bzr commit -m 'we need some foo'
911
2>Committing to:...trunk/
913
2>Committed revision 1.
914
$ bzr init ../feature
915
Created a standalone tree (format: 2a)
916
$ bzr push -v ../feature -Olog_format=line
918
1: jrandom@example.com ...we need some foo
919
2>All changes applied successfully.
920
2>Pushed up to revision 1.
923
def test_push_with_revspec(self):
926
Shared repository with trees (format: 2a)
930
Created a repository tree (format: 2a)
931
Using shared repository...
933
$ bzr commit -m 'first rev' --unchanged
934
2>Committing to:...trunk/
935
2>Committed revision 1.
939
$ bzr commit -m 'we need some foo'
940
2>Committing to:...trunk/
942
2>Committed revision 2.
943
$ bzr push -r 1 ../other
944
2>Created new branch.
945
$ bzr st ../other # checking that file is not created (#484516)