/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Andrew Bennetts
  • Date: 2011-06-02 07:25:33 UTC
  • mfrom: (5952 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5955.
  • Revision ID: andrew.bennetts@canonical.com-20110602072533-v0pe1ivh27cp0pd8
MergeĀ lp:bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
from bzrlib import (
25
25
        bzrdir,
26
26
        cache_utf8,
 
27
        cleanup,
27
28
        config as _mod_config,
28
29
        debug,
29
30
        errors,
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:
 
458
 
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':
 
466
 
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)
668
671
 
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.
672
675
 
673
676
        :param from_branch: Where to copy from.
674
677
        :param last_revision: What revision to stop at (None for at the end
675
678
                              of the branch.
 
679
        :param limit: Optional rough limit of revisions to fetch
676
680
        :return: None
677
681
        """
678
 
        return InterBranch.get(from_branch, self).fetch(last_revision)
 
682
        return InterBranch.get(from_branch, self).fetch(last_revision, limit=limit)
679
683
 
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
775
779
        be permitted.
776
780
        """
777
 
        raise NotImplementedError(self.last_revision_info)
 
781
        raise NotImplementedError(self.set_last_revision_info)
778
782
 
779
783
    @needs_write_lock
780
784
    def generate_revision_history(self, revision_id, last_rev=None,
928
932
 
929
933
        :seealso: Branch._get_tags_bytes.
930
934
        """
931
 
        return _run_with_write_locked_target(self, self._set_tags_bytes_locked,
932
 
                bytes)
 
935
        op = cleanup.OperationWithCleanups(self._set_tags_bytes_locked)
 
936
        op.add_cleanup(self.lock_write().unlock)
 
937
        return op.run_simple(bytes)
933
938
 
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)
1104
1109
 
1105
 
    def push(self, target, overwrite=False, stop_revision=None, *args,
1106
 
        **kwargs):
 
1110
    def push(self, target, overwrite=False, stop_revision=None, lossy=False,
 
1111
            *args, **kwargs):
1107
1112
        """Mirror this branch into target.
1108
1113
 
1109
1114
        This branch is considered to be 'local', having low latency.
1110
1115
        """
1111
1116
        return InterBranch.get(self, target).push(overwrite, stop_revision,
1112
 
            *args, **kwargs)
1113
 
 
1114
 
    def lossy_push(self, target, stop_revision=None):
1115
 
        """Push deltas into another branch.
1116
 
 
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.
1121
 
 
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.
1128
 
        """
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)
1134
1118
 
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
1490
1474
 
1491
1475
    def reference_parent(self, file_id, path, possible_transports=None):
1492
1476
        """Return the parent branch for a tree-reference file_id
 
1477
 
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
1885
1870
 
1886
1871
 
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.
1889
1874
 
1890
1875
    There are 5 fields that hooks may wish to access:
1891
1876
 
1923
1908
 
1924
1909
 
1925
1910
class BranchInitHookParams(object):
1926
 
    """Object holding parameters passed to *_branch_init hooks.
 
1911
    """Object holding parameters passed to `*_branch_init` hooks.
1927
1912
 
1928
1913
    There are 4 fields that hooks may wish to access:
1929
1914
 
1963
1948
 
1964
1949
 
1965
1950
class SwitchHookParams(object):
1966
 
    """Object holding parameters passed to *_switch hooks.
 
1951
    """Object holding parameters passed to `*_switch` hooks.
1967
1952
 
1968
1953
    There are 4 fields that hooks may wish to access:
1969
1954
 
3185
3170
        branch._transport.put_bytes('format', format.get_format_string())
3186
3171
 
3187
3172
 
3188
 
def _run_with_write_locked_target(target, callable, *args, **kwargs):
3189
 
    """Run ``callable(*args, **kwargs)``, write-locking target for the
3190
 
    duration.
3191
 
 
3192
 
    _run_with_write_locked_target will attempt to release the lock it acquires.
3193
 
 
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::
3197
 
 
3198
 
        target.lock_write()
3199
 
        try:
3200
 
            return callable(*args, **kwargs)
3201
 
        finally:
3202
 
            target.unlock()
3203
 
 
3204
 
    """
3205
 
    # This is very similar to bzrlib.decorators.needs_write_lock.  Perhaps they
3206
 
    # should share code?
3207
 
    target.lock_write()
3208
 
    try:
3209
 
        result = callable(*args, **kwargs)
3210
 
    except:
3211
 
        exc_info = sys.exc_info()
3212
 
        try:
3213
 
            target.unlock()
3214
 
        finally:
3215
 
            raise exc_info[0], exc_info[1], exc_info[2]
3216
 
    else:
3217
 
        target.unlock()
3218
 
        return result
3219
 
 
3220
 
 
3221
3173
class InterBranch(InterObject):
3222
3174
    """This class represents operations taking place between two branches.
3223
3175
 
3251
3203
        raise NotImplementedError(self.pull)
3252
3204
 
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.
3257
3209
 
3269
3221
        raise NotImplementedError(self.copy_content_into)
3270
3222
 
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.
3274
3226
 
3275
3227
        :param stop_revision: Last revision to fetch
 
3228
        :param limit: Optional rough limit of revisions to fetch
3276
3229
        """
3277
3230
        raise NotImplementedError(self.fetch)
3278
3231
 
3316
3269
            self.source.tags.merge_to(self.target.tags)
3317
3270
 
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:
3321
3274
            return (0, [])
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()
3407
3361
 
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.
3411
3365
 
3412
3366
        This is the basic concrete implementation of push()
3413
3367
 
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
 
3371
            vfs-based Branch.
3418
3372
        """
 
3373
        if lossy:
 
3374
            raise errors.LossyPushToSameVCS(self.source, self.target)
3419
3375
        # TODO: Public option to disable running hooks - should be trivial but
3420
3376
        # needs tests.
3421
 
        self.source.lock_read()
3422
 
        try:
3423
 
            return _run_with_write_locked_target(
3424
 
                self.target, self._push_with_bound_branches, overwrite,
3425
 
                stop_revision,
3426
 
                _override_hook_source_branch=_override_hook_source_branch)
3427
 
        finally:
3428
 
            self.source.unlock()
 
3377
 
 
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)
3429
3383
 
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()
3450
3404
        return result
3451
3405
 
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.
3455
3409
        """
3467
3421
            # be bound to itself? -- mbp 20070507
3468
3422
            master_branch = self.target.get_master_branch()
3469
3423
            master_branch.lock_write()
3470
 
            try:
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
3480
 
                _run_hooks()
3481
 
                return result
3482
 
            finally:
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
3484
3434
        else:
 
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
3489
3440
            # 20070504
3490
3441
            result.master_branch = self.target
3491
3442
            result.local_branch = None
3492
 
            _run_hooks()
3493
 
            return result
 
3443
        _run_hooks()
 
3444
        return result
3494
3445
 
3495
3446
    def _pull(self, overwrite=False, stop_revision=None,
3496
3447
             possible_transports=None, _hook_master=None, run_hooks=True,