454
455
after. If None, the rest of history is included.
455
456
:param stop_rule: if stop_revision_id is not None, the precise rule
456
457
to use for termination:
457
459
* 'exclude' - leave the stop revision out of the result (default)
458
460
* 'include' - the stop revision is the last item in the result
459
461
* 'with-merges' - include the stop revision and all of its
461
463
* 'with-merges-without-common-ancestry' - filter out revisions
462
464
that are in both ancestries
463
465
:param direction: either 'reverse' or 'forward':
464
467
* reverse means return the start_revision_id first, i.e.
465
468
start at the most recent revision and go backwards in history
466
469
* forward returns tuples in the opposite order to reverse.
667
670
raise errors.UnsupportedOperation(self.get_reference_info, self)
669
672
@needs_write_lock
670
def fetch(self, from_branch, last_revision=None):
673
def fetch(self, from_branch, last_revision=None, limit=None):
671
674
"""Copy revisions from from_branch into this branch.
673
676
:param from_branch: Where to copy from.
674
677
:param last_revision: What revision to stop at (None for at the end
679
:param limit: Optional rough limit of revisions to fetch
678
return InterBranch.get(from_branch, self).fetch(last_revision)
682
return InterBranch.get(from_branch, self).fetch(last_revision, limit=limit)
680
684
def get_bound_location(self):
681
685
"""Return the URL of the branch we are bound to.
774
778
configured to check constraints on history, in which case this may not
777
raise NotImplementedError(self.last_revision_info)
781
raise NotImplementedError(self.set_last_revision_info)
779
783
@needs_write_lock
780
784
def generate_revision_history(self, revision_id, last_rev=None,
929
933
:seealso: Branch._get_tags_bytes.
931
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)
934
939
def _set_tags_bytes_locked(self, bytes):
935
940
self._tags_bytes = bytes
1102
1107
stop_revision=stop_revision,
1103
1108
possible_transports=possible_transports, *args, **kwargs)
1105
def push(self, target, overwrite=False, stop_revision=None, *args,
1110
def push(self, target, overwrite=False, stop_revision=None, lossy=False,
1107
1112
"""Mirror this branch into target.
1109
1114
This branch is considered to be 'local', having low latency.
1111
1116
return InterBranch.get(self, target).push(overwrite, stop_revision,
1114
def lossy_push(self, target, stop_revision=None):
1115
"""Push deltas into another branch.
1117
:note: This does not, like push, retain the revision ids from
1118
the source branch and will, rather than adding bzr-specific
1119
metadata, push only those semantics of the revision that can be
1120
natively represented by this branch' VCS.
1122
:param target: Target branch
1123
:param stop_revision: Revision to push, defaults to last revision.
1124
:return: BranchPushResult with an extra member revidmap:
1125
A dictionary mapping revision ids from the target branch
1126
to new revision ids in the target branch, for each
1127
revision that was pushed.
1129
inter = InterBranch.get(self, target)
1130
lossy_push = getattr(inter, "lossy_push", None)
1131
if lossy_push is None:
1132
raise errors.LossyPushToSameVCS(self, target)
1133
return lossy_push(stop_revision)
1117
lossy, *args, **kwargs)
1135
1119
def basis_tree(self):
1136
1120
"""Return `Tree` object for last revision."""
1438
1422
:param to_location: The url to produce the checkout at
1439
1423
:param revision_id: The revision to check out
1440
1424
:param lightweight: If True, produce a lightweight checkout, otherwise,
1441
produce a bound branch (heavyweight checkout)
1425
produce a bound branch (heavyweight checkout)
1442
1426
:param accelerator_tree: A tree which can be used for retrieving file
1443
1427
contents more quickly than the revision tree, i.e. a workingtree.
1444
1428
The revision tree will be used for cases where accelerator_tree's
1491
1475
def reference_parent(self, file_id, path, possible_transports=None):
1492
1476
"""Return the parent branch for a tree-reference file_id
1493
1478
:param file_id: The file_id of the tree reference
1494
1479
:param path: The path of the file_id in the tree
1495
1480
:return: A branch associated with the file_id
1887
1872
class ChangeBranchTipParams(object):
1888
"""Object holding parameters passed to *_change_branch_tip hooks.
1873
"""Object holding parameters passed to `*_change_branch_tip` hooks.
1890
1875
There are 5 fields that hooks may wish to access:
1925
1910
class BranchInitHookParams(object):
1926
"""Object holding parameters passed to *_branch_init hooks.
1911
"""Object holding parameters passed to `*_branch_init` hooks.
1928
1913
There are 4 fields that hooks may wish to access:
3185
3170
branch._transport.put_bytes('format', format.get_format_string())
3188
def _run_with_write_locked_target(target, callable, *args, **kwargs):
3189
"""Run ``callable(*args, **kwargs)``, write-locking target for the
3192
_run_with_write_locked_target will attempt to release the lock it acquires.
3194
If an exception is raised by callable, then that exception *will* be
3195
propagated, even if the unlock attempt raises its own error. Thus
3196
_run_with_write_locked_target should be preferred to simply doing::
3200
return callable(*args, **kwargs)
3205
# This is very similar to bzrlib.decorators.needs_write_lock. Perhaps they
3206
# should share code?
3209
result = callable(*args, **kwargs)
3211
exc_info = sys.exc_info()
3215
raise exc_info[0], exc_info[1], exc_info[2]
3221
3173
class InterBranch(InterObject):
3222
3174
"""This class represents operations taking place between two branches.
3251
3203
raise NotImplementedError(self.pull)
3253
3205
@needs_write_lock
3254
def push(self, overwrite=False, stop_revision=None,
3206
def push(self, overwrite=False, stop_revision=None, lossy=False,
3255
3207
_override_hook_source_branch=None):
3256
3208
"""Mirror the source branch into the target branch.
3269
3221
raise NotImplementedError(self.copy_content_into)
3271
3223
@needs_write_lock
3272
def fetch(self, stop_revision=None):
3224
def fetch(self, stop_revision=None, limit=None):
3273
3225
"""Fetch revisions.
3275
3227
:param stop_revision: Last revision to fetch
3228
:param limit: Optional rough limit of revisions to fetch
3277
3230
raise NotImplementedError(self.fetch)
3316
3269
self.source.tags.merge_to(self.target.tags)
3318
3271
@needs_write_lock
3319
def fetch(self, stop_revision=None):
3272
def fetch(self, stop_revision=None, limit=None):
3320
3273
if self.target.base == self.source.base:
3322
3275
self.source.lock_read()
3327
3280
fetch_spec_factory.source_repo = self.source.repository
3328
3281
fetch_spec_factory.target_repo = self.target.repository
3329
3282
fetch_spec_factory.target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
3283
fetch_spec_factory.limit = limit
3330
3284
fetch_spec = fetch_spec_factory.make_fetch_spec()
3331
3285
return self.target.repository.fetch(self.source.repository,
3332
3286
fetch_spec=fetch_spec)
3405
3359
if master_branch:
3406
3360
master_branch.unlock()
3408
def push(self, overwrite=False, stop_revision=None,
3362
def push(self, overwrite=False, stop_revision=None, lossy=False,
3409
3363
_override_hook_source_branch=None):
3410
3364
"""See InterBranch.push.
3412
3366
This is the basic concrete implementation of push()
3414
:param _override_hook_source_branch: If specified, run
3415
the hooks passing this Branch as the source, rather than self.
3416
This is for use of RemoteBranch, where push is delegated to the
3417
underlying vfs-based Branch.
3368
:param _override_hook_source_branch: If specified, run the hooks
3369
passing this Branch as the source, rather than self. This is for
3370
use of RemoteBranch, where push is delegated to the underlying
3374
raise errors.LossyPushToSameVCS(self.source, self.target)
3419
3375
# TODO: Public option to disable running hooks - should be trivial but
3421
self.source.lock_read()
3423
return _run_with_write_locked_target(
3424
self.target, self._push_with_bound_branches, overwrite,
3426
_override_hook_source_branch=_override_hook_source_branch)
3428
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)
3430
3384
def _basic_push(self, overwrite, stop_revision):
3431
3385
"""Basic implementation of push without bound branches or hooks.
3449
3403
result.new_revno, result.new_revid = self.target.last_revision_info()
3452
def _push_with_bound_branches(self, overwrite, stop_revision,
3406
def _push_with_bound_branches(self, operation, overwrite, stop_revision,
3453
3407
_override_hook_source_branch=None):
3454
3408
"""Push from source into target, and into target's master if any.
3467
3421
# be bound to itself? -- mbp 20070507
3468
3422
master_branch = self.target.get_master_branch()
3469
3423
master_branch.lock_write()
3471
# push into the master from the source branch.
3472
master_inter = InterBranch.get(self.source, master_branch)
3473
master_inter._basic_push(overwrite, stop_revision)
3474
# and push into the target branch from the source. Note that
3475
# we push from the source branch again, because it's considered
3476
# the highest bandwidth repository.
3477
result = self._basic_push(overwrite, stop_revision)
3478
result.master_branch = master_branch
3479
result.local_branch = self.target
3483
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
3485
3436
# no master branch
3486
3437
result = self._basic_push(overwrite, stop_revision)
3487
3438
# TODO: Why set master_branch and local_branch if there's no
3490
3441
result.master_branch = self.target
3491
3442
result.local_branch = None
3495
3446
def _pull(self, overwrite=False, stop_revision=None,
3496
3447
possible_transports=None, _hook_master=None, run_hooks=True,