55
98
self.assertEqual(None, branch_b.get_push_location())
57
100
# test push for failure without push location set
59
out = self.runbzr('push', retcode=3)
101
out = self.run_bzr('push', working_dir='branch_a', retcode=3)
60
102
self.assertEquals(out,
61
103
('','bzr: ERROR: No push location known or specified.\n'))
63
105
# test not remembered if cannot actually push
64
self.run_bzr('push', '../path/which/doesnt/exist', retcode=3)
65
out = self.run_bzr('push', retcode=3)
106
self.run_bzr('push path/which/doesnt/exist',
107
working_dir='branch_a', retcode=3)
108
out = self.run_bzr('push', working_dir='branch_a', retcode=3)
66
109
self.assertEquals(
67
110
('', 'bzr: ERROR: No push location known or specified.\n'),
70
113
# test implicit --remember when no push location set, push fails
71
out = self.run_bzr('push', '../branch_b', retcode=3)
114
out = self.run_bzr('push ../branch_b',
115
working_dir='branch_a', retcode=3)
72
116
self.assertEquals(out,
73
117
('','bzr: ERROR: These branches have diverged. '
74
'Try a merge then push with overwrite.\n'))
75
self.assertEquals(abspath(branch_a.get_push_location()),
76
abspath(branch_b.bzrdir.root_transport.base))
118
'See "bzr help diverged-branches" for more information.\n'))
119
self.assertEquals(osutils.abspath(branch_a.get_push_location()),
120
osutils.abspath(branch_b.bzrdir.root_transport.base))
78
122
# test implicit --remember after resolving previous failure
79
uncommit(branch=branch_b, tree=tree_b)
123
uncommit.uncommit(branch=branch_b, tree=tree_b)
80
124
transport.delete('branch_b/c')
81
out = self.run_bzr('push')
125
out, err = self.run_bzr('push', working_dir='branch_a')
82
126
path = branch_a.get_push_location()
83
self.assertEquals(('Using saved location: %s\n'
84
% (local_path_from_url(path),)
85
, 'All changes applied successfully.\n'
86
'1 revision(s) pushed.\n'), out)
127
self.assertEquals(out,
128
'Using saved push location: %s\n'
129
% urlutils.local_path_from_url(path))
130
self.assertEqual(err,
131
'All changes applied successfully.\n'
132
'Pushed up to revision 2.\n')
87
133
self.assertEqual(path,
88
134
branch_b.bzrdir.root_transport.base)
89
135
# test explicit --remember
90
self.run_bzr('push', '../branch_c', '--remember')
136
self.run_bzr('push ../branch_c --remember', working_dir='branch_a')
91
137
self.assertEquals(branch_a.get_push_location(),
92
138
branch_c.bzrdir.root_transport.base)
94
140
def test_push_without_tree(self):
95
141
# bzr push from a branch that does not have a checkout should work.
96
142
b = self.make_branch('.')
97
out, err = self.run_bzr('push', 'pushed-location')
143
out, err = self.run_bzr('push pushed-location')
98
144
self.assertEqual('', out)
99
self.assertEqual('0 revision(s) pushed.\n', err)
100
b2 = bzrlib.branch.Branch.open('pushed-location')
145
self.assertEqual('Created new branch.\n', err)
146
b2 = branch.Branch.open('pushed-location')
101
147
self.assertEndsWith(b2.base, 'pushed-location/')
149
def test_push_no_tree(self):
150
# bzr push --no-tree of a branch with working trees
151
b = self.make_branch_and_tree('push-from')
152
self.build_tree(['push-from/file'])
155
out, err = self.run_bzr('push --no-tree -d push-from push-to')
156
self.assertEqual('', out)
157
self.assertEqual('Created new branch.\n', err)
158
self.failIfExists('push-to/file')
103
160
def test_push_new_branch_revision_count(self):
104
# bzr push of a branch with revisions to a new location
105
# should print the number of revisions equal to the length of the
161
# bzr push of a branch with revisions to a new location
162
# should print the number of revisions equal to the length of the
107
164
t = self.make_branch_and_tree('tree')
108
165
self.build_tree(['tree/file'])
110
167
t.commit('commit 1')
112
out, err = self.run_bzr('push', 'pushed-to')
168
out, err = self.run_bzr('push -d tree pushed-to')
114
169
self.assertEqual('', out)
115
self.assertEqual('1 revision(s) pushed.\n', err)
170
self.assertEqual('Created new branch.\n', err)
117
172
def test_push_only_pushes_history(self):
118
173
# Knit branches should only push the history for the current revision.
119
format = BzrDirMetaFormat1()
120
format.repository_format = RepositoryFormatKnit1()
174
format = bzrdir.BzrDirMetaFormat1()
175
format.repository_format = knitrepo.RepositoryFormatKnit1()
121
176
shared_repo = self.make_repository('repo', format=format, shared=True)
122
177
shared_repo.set_make_working_trees(True)
124
179
def make_shared_tree(path):
125
180
shared_repo.bzrdir.root_transport.mkdir(path)
126
181
shared_repo.bzrdir.create_branch_convenience('repo/' + path)
127
return WorkingTree.open('repo/' + path)
182
return workingtree.WorkingTree.open('repo/' + path)
128
183
tree_a = make_shared_tree('a')
129
184
self.build_tree(['repo/a/file'])
130
185
tree_a.add('file')
156
210
def test_push_funky_id(self):
157
211
t = self.make_branch_and_tree('tree')
159
self.build_tree(['filename'])
212
self.build_tree(['tree/filename'])
160
213
t.add('filename', 'funky-chars<>%&;"\'')
161
214
t.commit('commit filename')
162
self.run_bzr('push', '../new-tree')
215
self.run_bzr('push -d tree new-tree')
217
def test_push_dash_d(self):
218
t = self.make_branch_and_tree('from')
219
t.commit(allow_pointless=True,
220
message='first commit')
221
self.run_bzr('push -d from to-one')
222
self.failUnlessExists('to-one')
223
self.run_bzr('push -d %s %s'
224
% tuple(map(urlutils.local_path_to_url, ['from', 'to-two'])))
225
self.failUnlessExists('to-two')
227
def test_push_smart_non_stacked_streaming_acceptance(self):
228
self.setup_smart_server_with_call_log()
229
t = self.make_branch_and_tree('from')
230
t.commit(allow_pointless=True, message='first commit')
231
self.reset_smart_call_log()
232
self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
233
# This figure represent the amount of work to perform this use case. It
234
# is entirely ok to reduce this number if a test fails due to rpc_count
235
# being too low. If rpc_count increases, more network roundtrips have
236
# become necessary for this use case. Please do not adjust this number
237
# upwards without agreement from bzr's network support maintainers.
238
self.assertLength(9, self.hpss_calls)
240
def test_push_smart_stacked_streaming_acceptance(self):
241
self.setup_smart_server_with_call_log()
242
parent = self.make_branch_and_tree('parent', format='1.9')
243
parent.commit(message='first commit')
244
local = parent.bzrdir.sprout('local').open_workingtree()
245
local.commit(message='local commit')
246
self.reset_smart_call_log()
247
self.run_bzr(['push', '--stacked', '--stacked-on', '../parent',
248
self.get_url('public')], working_dir='local')
249
# This figure represent the amount of work to perform this use case. It
250
# is entirely ok to reduce this number if a test fails due to rpc_count
251
# being too low. If rpc_count increases, more network roundtrips have
252
# become necessary for this use case. Please do not adjust this number
253
# upwards without agreement from bzr's network support maintainers.
254
self.assertLength(14, self.hpss_calls)
255
remote = branch.Branch.open('public')
256
self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
258
def test_push_smart_tags_streaming_acceptance(self):
259
self.setup_smart_server_with_call_log()
260
t = self.make_branch_and_tree('from')
261
rev_id = t.commit(allow_pointless=True, message='first commit')
262
t.branch.tags.set_tag('new-tag', rev_id)
263
self.reset_smart_call_log()
264
self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
265
# This figure represent the amount of work to perform this use case. It
266
# is entirely ok to reduce this number if a test fails due to rpc_count
267
# being too low. If rpc_count increases, more network roundtrips have
268
# become necessary for this use case. Please do not adjust this number
269
# upwards without agreement from bzr's network support maintainers.
270
self.assertLength(11, self.hpss_calls)
272
def test_push_smart_incremental_acceptance(self):
273
self.setup_smart_server_with_call_log()
274
t = self.make_branch_and_tree('from')
275
rev_id1 = t.commit(allow_pointless=True, message='first commit')
276
rev_id2 = t.commit(allow_pointless=True, message='second commit')
278
['push', self.get_url('to-one'), '-r1'], working_dir='from')
279
self.reset_smart_call_log()
280
self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
281
# This figure represent the amount of work to perform this use case. It
282
# is entirely ok to reduce this number if a test fails due to rpc_count
283
# being too low. If rpc_count increases, more network roundtrips have
284
# become necessary for this use case. Please do not adjust this number
285
# upwards without agreement from bzr's network support maintainers.
286
self.assertLength(11, self.hpss_calls)
288
def test_push_smart_with_default_stacking_url_path_segment(self):
289
# If the default stacked-on location is a path element then branches
290
# we push there over the smart server are stacked and their
291
# stacked_on_url is that exact path segment. Added to nail bug 385132.
292
self.setup_smart_server_with_call_log()
293
self.make_branch('stack-on', format='1.9')
294
self.make_bzrdir('.').get_config().set_default_stack_on(
296
self.make_branch('from', format='1.9')
297
out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
298
b = branch.Branch.open(self.get_url('to'))
299
self.assertEqual('/extra/stack-on', b.get_stacked_on_url())
301
def test_push_smart_with_default_stacking_relative_path(self):
302
# If the default stacked-on location is a relative path then branches
303
# we push there over the smart server are stacked and their
304
# stacked_on_url is a relative path. Added to nail bug 385132.
305
self.setup_smart_server_with_call_log()
306
self.make_branch('stack-on', format='1.9')
307
self.make_bzrdir('.').get_config().set_default_stack_on('stack-on')
308
self.make_branch('from', format='1.9')
309
out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
310
b = branch.Branch.open(self.get_url('to'))
311
self.assertEqual('../stack-on', b.get_stacked_on_url())
313
def create_simple_tree(self):
314
tree = self.make_branch_and_tree('tree')
315
self.build_tree(['tree/a'])
316
tree.add(['a'], ['a-id'])
317
tree.commit('one', rev_id='r1')
320
def test_push_create_prefix(self):
321
"""'bzr push --create-prefix' will create leading directories."""
322
tree = self.create_simple_tree()
324
self.run_bzr_error(['Parent directory of ../new/tree does not exist'],
327
self.run_bzr('push ../new/tree --create-prefix',
329
new_tree = workingtree.WorkingTree.open('new/tree')
330
self.assertEqual(tree.last_revision(), new_tree.last_revision())
331
self.failUnlessExists('new/tree/a')
333
def test_push_use_existing(self):
334
"""'bzr push --use-existing-dir' can push into an existing dir.
336
By default, 'bzr push' will not use an existing, non-versioned dir.
338
tree = self.create_simple_tree()
339
self.build_tree(['target/'])
341
self.run_bzr_error(['Target directory ../target already exists',
342
'Supply --use-existing-dir',
344
'push ../target', working_dir='tree')
346
self.run_bzr('push --use-existing-dir ../target',
349
new_tree = workingtree.WorkingTree.open('target')
350
self.assertEqual(tree.last_revision(), new_tree.last_revision())
351
# The push should have created target/a
352
self.failUnlessExists('target/a')
354
def test_push_use_existing_into_empty_bzrdir(self):
355
"""'bzr push --use-existing-dir' into a dir with an empty .bzr dir
358
tree = self.create_simple_tree()
359
self.build_tree(['target/', 'target/.bzr/'])
361
['Target directory ../target already contains a .bzr directory, '
362
'but it is not valid.'],
363
'push ../target --use-existing-dir', working_dir='tree')
365
def test_push_onto_repo(self):
366
"""We should be able to 'bzr push' into an existing bzrdir."""
367
tree = self.create_simple_tree()
368
repo = self.make_repository('repo', shared=True)
370
self.run_bzr('push ../repo',
373
# Pushing onto an existing bzrdir will create a repository and
374
# branch as needed, but will only create a working tree if there was
376
self.assertRaises(errors.NoWorkingTree,
377
workingtree.WorkingTree.open, 'repo')
378
new_branch = branch.Branch.open('repo')
379
self.assertEqual(tree.last_revision(), new_branch.last_revision())
381
def test_push_onto_just_bzrdir(self):
382
"""We don't handle when the target is just a bzrdir.
384
Because you shouldn't be able to create *just* a bzrdir in the wild.
386
# TODO: jam 20070109 Maybe it would be better to create the repository
388
tree = self.create_simple_tree()
389
a_bzrdir = self.make_bzrdir('dir')
391
self.run_bzr_error(['At ../dir you have a valid .bzr control'],
395
def test_push_with_revisionspec(self):
396
"""We should be able to push a revision older than the tip."""
397
tree_from = self.make_branch_and_tree('from')
398
tree_from.commit("One.", rev_id="from-1")
399
tree_from.commit("Two.", rev_id="from-2")
401
self.run_bzr('push -r1 ../to', working_dir='from')
403
tree_to = workingtree.WorkingTree.open('to')
404
repo_to = tree_to.branch.repository
405
self.assertTrue(repo_to.has_revision('from-1'))
406
self.assertFalse(repo_to.has_revision('from-2'))
407
self.assertEqual(tree_to.branch.last_revision_info()[1], 'from-1')
410
['bzr: ERROR: bzr push --revision '
411
'takes exactly one revision identifier\n'],
412
'push -r0..2 ../to', working_dir='from')
414
def create_trunk_and_feature_branch(self):
416
trunk_tree = self.make_branch_and_tree('target',
418
trunk_tree.commit('mainline')
419
# and a branch from it
420
branch_tree = self.make_branch_and_tree('branch',
422
branch_tree.pull(trunk_tree.branch)
423
branch_tree.branch.set_parent(trunk_tree.branch.base)
424
# with some work on it
425
branch_tree.commit('moar work plz')
426
return trunk_tree, branch_tree
428
def assertPublished(self, branch_revid, stacked_on):
429
"""Assert that the branch 'published' has been published correctly."""
430
published_branch = branch.Branch.open('published')
431
# The published branch refers to the mainline
432
self.assertEqual(stacked_on, published_branch.get_stacked_on_url())
433
# and the branch's work was pushed
434
self.assertTrue(published_branch.repository.has_revision(branch_revid))
436
def test_push_new_branch_stacked_on(self):
437
"""Pushing a new branch with --stacked-on creates a stacked branch."""
438
trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
439
# we publish branch_tree with a reference to the mainline.
440
out, err = self.run_bzr(['push', '--stacked-on', trunk_tree.branch.base,
441
self.get_url('published')], working_dir='branch')
442
self.assertEqual('', out)
443
self.assertEqual('Created new stacked branch referring to %s.\n' %
444
trunk_tree.branch.base, err)
445
self.assertPublished(branch_tree.last_revision(),
446
trunk_tree.branch.base)
448
def test_push_new_branch_stacked_uses_parent_when_no_public_url(self):
449
"""When the parent has no public url the parent is used as-is."""
450
trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
451
# now we do a stacked push, which should determine the public location
453
out, err = self.run_bzr(['push', '--stacked',
454
self.get_url('published')], working_dir='branch')
455
self.assertEqual('', out)
456
self.assertEqual('Created new stacked branch referring to %s.\n' %
457
trunk_tree.branch.base, err)
458
self.assertPublished(branch_tree.last_revision(),
459
trunk_tree.branch.base)
461
def test_push_new_branch_stacked_uses_parent_public(self):
462
"""Pushing a new branch with --stacked creates a stacked branch."""
463
trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
464
# the trunk is published on a web server
465
self.transport_readonly_server = http_server.HttpServer
466
trunk_public = self.make_branch('public_trunk', format='1.9')
467
trunk_public.pull(trunk_tree.branch)
468
trunk_public_url = self.get_readonly_url('public_trunk')
469
trunk_tree.branch.set_public_branch(trunk_public_url)
470
# now we do a stacked push, which should determine the public location
472
out, err = self.run_bzr(['push', '--stacked',
473
self.get_url('published')], working_dir='branch')
474
self.assertEqual('', out)
475
self.assertEqual('Created new stacked branch referring to %s.\n' %
476
trunk_public_url, err)
477
self.assertPublished(branch_tree.last_revision(), trunk_public_url)
479
def test_push_new_branch_stacked_no_parent(self):
480
"""Pushing with --stacked and no parent branch errors."""
481
branch = self.make_branch_and_tree('branch', format='1.9')
482
# now we do a stacked push, which should fail as the place to refer too
483
# cannot be determined.
484
out, err = self.run_bzr_error(
485
['Could not determine branch to refer to\\.'], ['push', '--stacked',
486
self.get_url('published')], working_dir='branch')
487
self.assertEqual('', out)
488
self.assertFalse(self.get_transport('published').has('.'))
490
def test_push_notifies_default_stacking(self):
491
self.make_branch('stack_on', format='1.6')
492
self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
493
self.make_branch('from', format='1.6')
494
out, err = self.run_bzr('push -d from to')
495
self.assertContainsRe(err,
496
'Using default stacking branch stack_on at .*')
498
def test_push_stacks_with_default_stacking_if_target_is_stackable(self):
499
self.make_branch('stack_on', format='1.6')
500
self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
501
self.make_branch('from', format='pack-0.92')
502
out, err = self.run_bzr('push -d from to')
503
b = branch.Branch.open('to')
504
self.assertEqual('../stack_on', b.get_stacked_on_url())
506
def test_push_does_not_change_format_with_default_if_target_cannot(self):
507
self.make_branch('stack_on', format='pack-0.92')
508
self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
509
self.make_branch('from', format='pack-0.92')
510
out, err = self.run_bzr('push -d from to')
511
b = branch.Branch.open('to')
512
self.assertRaises(errors.UnstackableBranchFormat, b.get_stacked_on_url)
514
def test_push_doesnt_create_broken_branch(self):
515
"""Pushing a new standalone branch works even when there's a default
516
stacking policy at the destination.
518
The new branch will preserve the repo format (even if it isn't the
519
default for the branch), and will be stacked when the repo format
520
allows (which means that the branch format isn't necessarly preserved).
522
self.make_repository('repo', shared=True, format='1.6')
523
builder = self.make_branch_builder('repo/local', format='pack-0.92')
524
builder.start_series()
525
builder.build_snapshot('rev-1', None, [
526
('add', ('', 'root-id', 'directory', '')),
527
('add', ('filename', 'f-id', 'file', 'content\n'))])
528
builder.build_snapshot('rev-2', ['rev-1'], [])
529
builder.build_snapshot('rev-3', ['rev-2'],
530
[('modify', ('f-id', 'new-content\n'))])
531
builder.finish_series()
532
branch = builder.get_branch()
533
# Push rev-1 to "trunk", so that we can stack on it.
534
self.run_bzr('push -d repo/local trunk -r 1')
535
# Set a default stacking policy so that new branches will automatically
537
self.make_bzrdir('.').get_config().set_default_stack_on('trunk')
538
# Push rev-2 to a new branch "remote". It will be stacked on "trunk".
539
out, err = self.run_bzr('push -d repo/local remote -r 2')
540
self.assertContainsRe(
541
err, 'Using default stacking branch trunk at .*')
542
# Push rev-3 onto "remote". If "remote" not stacked and is missing the
543
# fulltext record for f-id @ rev-1, then this will fail.
544
out, err = self.run_bzr('push -d repo/local remote -r 3')
546
def test_push_verbose_shows_log(self):
547
tree = self.make_branch_and_tree('source')
549
out, err = self.run_bzr('push -v -d source target')
550
# initial push contains log
551
self.assertContainsRe(out, 'rev1')
553
out, err = self.run_bzr('push -v -d source target')
554
# subsequent push contains log
555
self.assertContainsRe(out, 'rev2')
556
# subsequent log is accurate
557
self.assertNotContainsRe(out, 'rev1')
559
def test_push_from_subdir(self):
560
t = self.make_branch_and_tree('tree')
561
self.build_tree(['tree/dir/', 'tree/dir/file'])
562
t.add('dir', 'dir/file')
564
out, err = self.run_bzr('push ../../pushloc', working_dir='tree/dir')
565
self.assertEqual('', out)
566
self.assertEqual('Created new branch.\n', err)
569
class RedirectingMemoryTransport(memory.MemoryTransport):
571
def mkdir(self, relpath, mode=None):
572
if self._cwd == '/source/':
573
raise errors.RedirectRequested(self.abspath(relpath),
574
self.abspath('../target'),
576
elif self._cwd == '/infinite-loop/':
577
raise errors.RedirectRequested(self.abspath(relpath),
578
self.abspath('../infinite-loop'),
581
return super(RedirectingMemoryTransport, self).mkdir(
584
def get(self, relpath):
585
if self.clone(relpath)._cwd == '/infinite-loop/':
586
raise errors.RedirectRequested(self.abspath(relpath),
587
self.abspath('../infinite-loop'),
590
return super(RedirectingMemoryTransport, self).get(relpath)
592
def _redirected_to(self, source, target):
593
# We do accept redirections
594
return transport.get_transport(target)
597
class RedirectingMemoryServer(memory.MemoryServer):
599
def start_server(self):
600
self._dirs = {'/': None}
603
self._scheme = 'redirecting-memory+%s:///' % id(self)
604
transport.register_transport(self._scheme, self._memory_factory)
606
def _memory_factory(self, url):
607
result = RedirectingMemoryTransport(url)
608
result._dirs = self._dirs
609
result._files = self._files
610
result._locks = self._locks
613
def stop_server(self):
614
transport.unregister_transport(self._scheme, self._memory_factory)
617
class TestPushRedirect(tests.TestCaseWithTransport):
620
tests.TestCaseWithTransport.setUp(self)
621
self.memory_server = RedirectingMemoryServer()
622
self.start_server(self.memory_server)
623
# Make the branch and tree that we'll be pushing.
624
t = self.make_branch_and_tree('tree')
625
self.build_tree(['tree/file'])
629
def test_push_redirects_on_mkdir(self):
630
"""If the push requires a mkdir, push respects redirect requests.
632
This is added primarily to handle lp:/ URI support, so that users can
633
push to new branches by specifying lp:/ URIs.
635
destination_url = self.memory_server.get_url() + 'source'
636
self.run_bzr(['push', '-d', 'tree', destination_url])
638
local_revision = branch.Branch.open('tree').last_revision()
639
remote_revision = branch.Branch.open(
640
self.memory_server.get_url() + 'target').last_revision()
641
self.assertEqual(remote_revision, local_revision)
643
def test_push_gracefully_handles_too_many_redirects(self):
644
"""Push fails gracefully if the mkdir generates a large number of
647
destination_url = self.memory_server.get_url() + 'infinite-loop'
648
out, err = self.run_bzr_error(
649
['Too many redirections trying to make %s\\.\n'
650
% re.escape(destination_url)],
651
['push', '-d', 'tree', destination_url], retcode=3)
652
self.assertEqual('', out)
655
class TestPushStrictMixin(object):
657
def make_local_branch_and_tree(self):
658
self.tree = self.make_branch_and_tree('local')
659
self.build_tree_contents([('local/file', 'initial')])
660
self.tree.add('file')
661
self.tree.commit('adding file', rev_id='added')
662
self.build_tree_contents([('local/file', 'modified')])
663
self.tree.commit('modify file', rev_id='modified')
665
def set_config_push_strict(self, value):
666
# set config var (any of bazaar.conf, locations.conf, branch.conf
668
conf = self.tree.branch.get_config()
669
conf.set_user_option('push_strict', value)
671
_default_command = ['push', '../to']
672
_default_wd = 'local'
673
_default_errors = ['Working tree ".*/local/" has uncommitted '
674
'changes \(See bzr status\)\.',]
675
_default_additional_error = 'Use --no-strict to force the push.\n'
676
_default_additional_warning = 'Uncommitted changes will not be pushed.'
679
def assertPushFails(self, args):
680
out, err = self.run_bzr_error(self._default_errors,
681
self._default_command + args,
682
working_dir=self._default_wd, retcode=3)
683
self.assertContainsRe(err, self._default_additional_error)
685
def assertPushSucceeds(self, args, with_warning=False, revid_to_push=None):
687
error_regexes = self._default_errors
690
out, err = self.run_bzr(self._default_command + args,
691
working_dir=self._default_wd,
692
error_regexes=error_regexes)
694
self.assertContainsRe(err, self._default_additional_warning)
696
self.assertNotContainsRe(err, self._default_additional_warning)
697
branch_from = branch.Branch.open(self._default_wd)
698
if revid_to_push is None:
699
revid_to_push = branch_from.last_revision()
700
branch_to = branch.Branch.open('to')
701
repo_to = branch_to.repository
702
self.assertTrue(repo_to.has_revision(revid_to_push))
703
self.assertEqual(revid_to_push, branch_to.last_revision())
707
class TestPushStrictWithoutChanges(tests.TestCaseWithTransport,
708
TestPushStrictMixin):
711
super(TestPushStrictWithoutChanges, self).setUp()
712
self.make_local_branch_and_tree()
714
def test_push_default(self):
715
self.assertPushSucceeds([])
717
def test_push_strict(self):
718
self.assertPushSucceeds(['--strict'])
720
def test_push_no_strict(self):
721
self.assertPushSucceeds(['--no-strict'])
723
def test_push_config_var_strict(self):
724
self.set_config_push_strict('true')
725
self.assertPushSucceeds([])
727
def test_push_config_var_no_strict(self):
728
self.set_config_push_strict('false')
729
self.assertPushSucceeds([])
732
class TestPushStrictWithChanges(tests.TestCaseWithTransport,
733
TestPushStrictMixin):
735
_changes_type = None # Set by load_tests
738
super(TestPushStrictWithChanges, self).setUp()
739
# Apply the changes defined in load_tests: one of _uncommitted_changes,
740
# _pending_merges or _out_of_sync_trees
741
getattr(self, self._changes_type)()
743
def _uncommitted_changes(self):
744
self.make_local_branch_and_tree()
745
# Make a change without committing it
746
self.build_tree_contents([('local/file', 'in progress')])
748
def _pending_merges(self):
749
self.make_local_branch_and_tree()
750
# Create 'other' branch containing a new file
751
other_bzrdir = self.tree.bzrdir.sprout('other')
752
other_tree = other_bzrdir.open_workingtree()
753
self.build_tree_contents([('other/other-file', 'other')])
754
other_tree.add('other-file')
755
other_tree.commit('other commit', rev_id='other')
756
# Merge and revert, leaving a pending merge
757
self.tree.merge_from_branch(other_tree.branch)
758
self.tree.revert(filenames=['other-file'], backups=False)
760
def _out_of_sync_trees(self):
761
self.make_local_branch_and_tree()
762
self.run_bzr(['checkout', '--lightweight', 'local', 'checkout'])
763
# Make a change and commit it
764
self.build_tree_contents([('local/file', 'modified in local')])
765
self.tree.commit('modify file', rev_id='modified-in-local')
766
# Exercise commands from the checkout directory
767
self._default_wd = 'checkout'
768
self._default_errors = ["Working tree is out of date, please run"
771
def test_push_default(self):
772
self.assertPushSucceeds([], with_warning=True)
774
def test_push_with_revision(self):
775
self.assertPushSucceeds(['-r', 'revid:added'], revid_to_push='added')
777
def test_push_no_strict(self):
778
self.assertPushSucceeds(['--no-strict'])
780
def test_push_strict_with_changes(self):
781
self.assertPushFails(['--strict'])
783
def test_push_respect_config_var_strict(self):
784
self.set_config_push_strict('true')
785
self.assertPushFails([])
787
def test_push_bogus_config_var_ignored(self):
788
self.set_config_push_strict("I don't want you to be strict")
789
self.assertPushSucceeds([], with_warning=True)
791
def test_push_no_strict_command_line_override_config(self):
792
self.set_config_push_strict('yES')
793
self.assertPushFails([])
794
self.assertPushSucceeds(['--no-strict'])
796
def test_push_strict_command_line_override_config(self):
797
self.set_config_push_strict('oFF')
798
self.assertPushFails(['--strict'])
799
self.assertPushSucceeds([])
802
class TestPushForeign(tests.TestCaseWithTransport):
805
super(TestPushForeign, self).setUp()
806
test_foreign.register_dummy_foreign_for_test(self)
808
def make_dummy_builder(self, relpath):
809
builder = self.make_branch_builder(
810
relpath, format=test_foreign.DummyForeignVcsDirFormat())
811
builder.build_snapshot('revid', None,
812
[('add', ('', 'TREE_ROOT', 'directory', None)),
813
('add', ('foo', 'fooid', 'file', 'bar'))])
816
def test_no_roundtripping(self):
817
target_branch = self.make_dummy_builder('dp').get_branch()
818
source_tree = self.make_branch_and_tree("dc")
819
output, error = self.run_bzr("push -d dc dp", retcode=3)
820
self.assertEquals("", output)
821
self.assertEquals(error, "bzr: ERROR: It is not possible to losslessly"
822
" push to dummy. You may want to use dpush instead.\n")