932
933
:seealso: Branch._get_tags_bytes.
934
return _run_with_write_locked_target(self, self._set_tags_bytes_locked,
935
op = cleanup.OperationWithCleanups(self._set_tags_bytes_locked)
936
op.add_cleanup(self.lock_write().unlock)
937
return op.run_simple(bytes)
937
939
def _set_tags_bytes_locked(self, bytes):
938
940
self._tags_bytes = bytes
3168
3170
branch._transport.put_bytes('format', format.get_format_string())
3171
def _run_with_write_locked_target(target, callable, *args, **kwargs):
3172
"""Run ``callable(*args, **kwargs)``, write-locking target for the
3175
_run_with_write_locked_target will attempt to release the lock it acquires.
3177
If an exception is raised by callable, then that exception *will* be
3178
propagated, even if the unlock attempt raises its own error. Thus
3179
_run_with_write_locked_target should be preferred to simply doing::
3183
return callable(*args, **kwargs)
3188
# This is very similar to bzrlib.decorators.needs_write_lock. Perhaps they
3189
# should share code?
3192
result = callable(*args, **kwargs)
3194
exc_info = sys.exc_info()
3199
raise exc_info[0], exc_info[1], exc_info[2]
3207
3173
class InterBranch(InterObject):
3208
3174
"""This class represents operations taking place between two branches.
3408
3374
raise errors.LossyPushToSameVCS(self.source, self.target)
3409
3375
# TODO: Public option to disable running hooks - should be trivial but
3411
self.source.lock_read()
3413
return _run_with_write_locked_target(
3414
self.target, self._push_with_bound_branches, overwrite,
3416
_override_hook_source_branch=_override_hook_source_branch)
3418
self.source.unlock()
3378
op = cleanup.OperationWithCleanups(self._push_with_bound_branches)
3379
op.add_cleanup(self.source.lock_read().unlock)
3380
op.add_cleanup(self.target.lock_write().unlock)
3381
return op.run(overwrite, stop_revision,
3382
_override_hook_source_branch=_override_hook_source_branch)
3420
3384
def _basic_push(self, overwrite, stop_revision):
3421
3385
"""Basic implementation of push without bound branches or hooks.
3439
3403
result.new_revno, result.new_revid = self.target.last_revision_info()
3442
def _push_with_bound_branches(self, overwrite, stop_revision,
3406
def _push_with_bound_branches(self, operation, overwrite, stop_revision,
3443
3407
_override_hook_source_branch=None):
3444
3408
"""Push from source into target, and into target's master if any.
3457
3421
# be bound to itself? -- mbp 20070507
3458
3422
master_branch = self.target.get_master_branch()
3459
3423
master_branch.lock_write()
3461
# push into the master from the source branch.
3462
master_inter = InterBranch.get(self.source, master_branch)
3463
master_inter._basic_push(overwrite, stop_revision)
3464
# and push into the target branch from the source. Note that
3465
# we push from the source branch again, because it's considered
3466
# the highest bandwidth repository.
3467
result = self._basic_push(overwrite, stop_revision)
3468
result.master_branch = master_branch
3469
result.local_branch = self.target
3473
master_branch.unlock()
3424
operation.add_cleanup(master_branch.unlock)
3425
# push into the master from the source branch.
3426
master_inter = InterBranch.get(self.source, master_branch)
3427
master_inter._basic_push(overwrite, stop_revision)
3428
# and push into the target branch from the source. Note that
3429
# we push from the source branch again, because it's considered
3430
# the highest bandwidth repository.
3431
result = self._basic_push(overwrite, stop_revision)
3432
result.master_branch = master_branch
3433
result.local_branch = self.target
3435
master_branch = None
3475
3436
# no master branch
3476
3437
result = self._basic_push(overwrite, stop_revision)
3477
3438
# TODO: Why set master_branch and local_branch if there's no
3480
3441
result.master_branch = self.target
3481
3442
result.local_branch = None
3485
3446
def _pull(self, overwrite=False, stop_revision=None,
3486
3447
possible_transports=None, _hook_master=None, run_hooks=True,