~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Jelmer Vernooij
  • Date: 2011-04-19 10:42:59 UTC
  • mto: This revision was merged to the branch mainline in revision 5806.
  • Revision ID: jelmer@samba.org-20110419104259-g9exlcp1f5jdu3ci
Move Inventory._get_mutable_inventory -> mutable_inventory_from_tree.

Show diffs side-by-side

added added

removed removed

Lines of Context:
669
669
        raise errors.UnsupportedOperation(self.get_reference_info, self)
670
670
 
671
671
    @needs_write_lock
672
 
    def fetch(self, from_branch, last_revision=None):
 
672
    def fetch(self, from_branch, last_revision=None, fetch_spec=None):
673
673
        """Copy revisions from from_branch into this branch.
674
674
 
675
675
        :param from_branch: Where to copy from.
676
676
        :param last_revision: What revision to stop at (None for at the end
677
677
                              of the branch.
 
678
        :param fetch_spec: If specified, a SearchResult or
 
679
            PendingAncestryResult that describes which revisions to copy.  This
 
680
            allows copying multiple heads at once.  Mutually exclusive with
 
681
            last_revision.
678
682
        :return: None
679
683
        """
680
 
        return InterBranch.get(from_branch, self).fetch(last_revision)
 
684
        return InterBranch.get(from_branch, self).fetch(last_revision,
 
685
            fetch_spec)
681
686
 
682
687
    def get_bound_location(self):
683
688
        """Return the URL of the branch we are bound to.
994
999
        else:
995
1000
            return (0, _mod_revision.NULL_REVISION)
996
1001
 
 
1002
    def update_revisions(self, other, stop_revision=None, overwrite=False,
 
1003
                         graph=None, fetch_tags=True):
 
1004
        """Pull in new perfect-fit revisions.
 
1005
 
 
1006
        :param other: Another Branch to pull from
 
1007
        :param stop_revision: Updated until the given revision
 
1008
        :param overwrite: Always set the branch pointer, rather than checking
 
1009
            to see if it is a proper descendant.
 
1010
        :param graph: A Graph object that can be used to query history
 
1011
            information. This can be None.
 
1012
        :param fetch_tags: Flag that specifies if tags from other should be
 
1013
            fetched too.
 
1014
        :return: None
 
1015
        """
 
1016
        return InterBranch.get(other, self).update_revisions(stop_revision,
 
1017
            overwrite, graph, fetch_tags=fetch_tags)
 
1018
 
997
1019
    @deprecated_method(deprecated_in((2, 4, 0)))
998
1020
    def import_last_revision_info(self, source_repo, revno, revid):
999
1021
        """Set the last revision info, importing from another repo if necessary.
1023
1045
            (should only be different from the arguments when lossy=True)
1024
1046
        """
1025
1047
        if not self.repository.has_same_location(source.repository):
1026
 
            self.fetch(source, revid)
 
1048
            try:
 
1049
                tags_to_fetch = set(source.tags.get_reverse_tag_dict())
 
1050
            except errors.TagsNotSupported:
 
1051
                tags_to_fetch = set()
 
1052
            fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
 
1053
                source.repository, [revid],
 
1054
                if_present_ids=tags_to_fetch).execute()
 
1055
            self.repository.fetch(source.repository, fetch_spec=fetch_spec)
1027
1056
        self.set_last_revision_info(revno, revid)
1028
1057
        return (revno, revid)
1029
1058
 
2482
2511
            'revision-history', '\n'.join(history),
2483
2512
            mode=self.bzrdir._get_file_mode())
2484
2513
 
2485
 
    @deprecated_method(deprecated_in((2, 4, 0)))
 
2514
    @needs_write_lock
2486
2515
    def set_revision_history(self, rev_history):
2487
2516
        """See Branch.set_revision_history."""
2488
 
        self._set_revision_history(rev_history)
2489
 
 
2490
 
    @needs_write_lock
2491
 
    def _set_revision_history(self, rev_history):
2492
2517
        if 'evil' in debug.debug_flags:
2493
2518
            mutter_callsite(3, "set_revision_history scales with history.")
2494
2519
        check_not_reserved_id = _mod_revision.check_not_reserved_id
2538
2563
            except ValueError:
2539
2564
                rev = self.repository.get_revision(revision_id)
2540
2565
                new_history = rev.get_history(self.repository)[1:]
2541
 
        destination._set_revision_history(new_history)
 
2566
        destination.set_revision_history(new_history)
2542
2567
 
2543
2568
    @needs_write_lock
2544
2569
    def set_last_revision_info(self, revno, revision_id):
2552
2577
        configured to check constraints on history, in which case this may not
2553
2578
        be permitted.
2554
2579
        """
2555
 
        if not revision_id or not isinstance(revision_id, basestring):
2556
 
            raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
 
2580
        revision_id = _mod_revision.ensure_null(revision_id)
2557
2581
        # this old format stores the full history, but this api doesn't
2558
2582
        # provide it, so we must generate, and might as well check it's
2559
2583
        # correct
2560
2584
        history = self._lefthand_history(revision_id)
2561
2585
        if len(history) != revno:
2562
2586
            raise AssertionError('%d != %d' % (len(history), revno))
2563
 
        self._set_revision_history(history)
 
2587
        self.set_revision_history(history)
2564
2588
 
2565
2589
    def _gen_revision_history(self):
2566
2590
        history = self._transport.get_bytes('revision-history').split('\n')
2580
2604
        :param other_branch: The other branch that DivergedBranches should
2581
2605
            raise with respect to.
2582
2606
        """
2583
 
        self._set_revision_history(self._lefthand_history(revision_id,
 
2607
        self.set_revision_history(self._lefthand_history(revision_id,
2584
2608
            last_rev, other_branch))
2585
2609
 
2586
2610
    def basis_tree(self):
2596
2620
                pass
2597
2621
        return None
2598
2622
 
 
2623
    def _basic_push(self, target, overwrite, stop_revision):
 
2624
        """Basic implementation of push without bound branches or hooks.
 
2625
 
 
2626
        Must be called with source read locked and target write locked.
 
2627
        """
 
2628
        result = BranchPushResult()
 
2629
        result.source_branch = self
 
2630
        result.target_branch = target
 
2631
        result.old_revno, result.old_revid = target.last_revision_info()
 
2632
        self.update_references(target)
 
2633
        if result.old_revid != stop_revision:
 
2634
            # We assume that during 'push' this repository is closer than
 
2635
            # the target.
 
2636
            graph = self.repository.get_graph(target.repository)
 
2637
            target.update_revisions(self, stop_revision,
 
2638
                overwrite=overwrite, graph=graph)
 
2639
        if self._push_should_merge_tags():
 
2640
            result.tag_conflicts = self.tags.merge_to(target.tags, overwrite)
 
2641
        result.new_revno, result.new_revid = target.last_revision_info()
 
2642
        return result
 
2643
 
2599
2644
    def get_stacked_on_url(self):
2600
2645
        raise errors.UnstackableBranchFormat(self._format, self.user_url)
2601
2646
 
2768
2813
 
2769
2814
    @needs_write_lock
2770
2815
    def set_last_revision_info(self, revno, revision_id):
2771
 
        if not revision_id or not isinstance(revision_id, basestring):
2772
 
            raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
 
2816
        revision_id = _mod_revision.ensure_null(revision_id)
2773
2817
        old_revno, old_revid = self.last_revision_info()
2774
2818
        if self._get_append_revisions_only():
2775
2819
            self._check_history_violation(revision_id)
3251
3295
        raise NotImplementedError(self.pull)
3252
3296
 
3253
3297
    @needs_write_lock
 
3298
    def update_revisions(self, stop_revision=None, overwrite=False,
 
3299
                         graph=None, fetch_tags=True):
 
3300
        """Pull in new perfect-fit revisions.
 
3301
 
 
3302
        :param stop_revision: Updated until the given revision
 
3303
        :param overwrite: Always set the branch pointer, rather than checking
 
3304
            to see if it is a proper descendant.
 
3305
        :param graph: A Graph object that can be used to query history
 
3306
            information. This can be None.
 
3307
        :param fetch_tags: Flag that specifies if tags from source should be
 
3308
            fetched too.
 
3309
        :return: None
 
3310
        """
 
3311
        raise NotImplementedError(self.update_revisions)
 
3312
 
 
3313
    @needs_write_lock
3254
3314
    def push(self, overwrite=False, stop_revision=None,
3255
3315
             _override_hook_source_branch=None):
3256
3316
        """Mirror the source branch into the target branch.
3269
3329
        raise NotImplementedError(self.copy_content_into)
3270
3330
 
3271
3331
    @needs_write_lock
3272
 
    def fetch(self, stop_revision=None):
 
3332
    def fetch(self, stop_revision=None, fetch_spec=None):
3273
3333
        """Fetch revisions.
3274
3334
 
3275
3335
        :param stop_revision: Last revision to fetch
 
3336
        :param fetch_spec: Fetch spec.
3276
3337
        """
3277
3338
        raise NotImplementedError(self.fetch)
3278
3339
 
3316
3377
            self.source.tags.merge_to(self.target.tags)
3317
3378
 
3318
3379
    @needs_write_lock
3319
 
    def fetch(self, stop_revision=None):
 
3380
    def fetch(self, stop_revision=None, fetch_spec=None):
 
3381
        if fetch_spec is not None and stop_revision is not None:
 
3382
            raise AssertionError(
 
3383
                "fetch_spec and last_revision are mutually exclusive.")
3320
3384
        if self.target.base == self.source.base:
3321
3385
            return (0, [])
3322
3386
        self.source.lock_read()
3323
3387
        try:
3324
 
            fetch_spec_factory = fetch.FetchSpecFactory()
3325
 
            fetch_spec_factory.source_branch = self.source
3326
 
            fetch_spec_factory.source_branch_stop_revision_id = stop_revision
3327
 
            fetch_spec_factory.source_repo = self.source.repository
3328
 
            fetch_spec_factory.target_repo = self.target.repository
3329
 
            fetch_spec_factory.target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
3330
 
            fetch_spec = fetch_spec_factory.make_fetch_spec()
 
3388
            if stop_revision is None and fetch_spec is None:
 
3389
                stop_revision = self.source.last_revision()
 
3390
                stop_revision = _mod_revision.ensure_null(stop_revision)
3331
3391
            return self.target.repository.fetch(self.source.repository,
3332
 
                fetch_spec=fetch_spec)
 
3392
                revision_id=stop_revision, fetch_spec=fetch_spec)
3333
3393
        finally:
3334
3394
            self.source.unlock()
3335
3395
 
3336
3396
    @needs_write_lock
3337
 
    def _update_revisions(self, stop_revision=None, overwrite=False,
3338
 
            graph=None):
 
3397
    def update_revisions(self, stop_revision=None, overwrite=False,
 
3398
        graph=None, fetch_tags=True):
 
3399
        """See InterBranch.update_revisions()."""
3339
3400
        other_revno, other_last_revision = self.source.last_revision_info()
3340
3401
        stop_revno = None # unknown
3341
3402
        if stop_revision is None:
3352
3413
        # case of having something to pull, and so that the check for
3353
3414
        # already merged can operate on the just fetched graph, which will
3354
3415
        # be cached in memory.
3355
 
        self.fetch(stop_revision=stop_revision)
 
3416
        if fetch_tags:
 
3417
            fetch_spec_factory = fetch.FetchSpecFactory()
 
3418
            fetch_spec_factory.source_branch = self.source
 
3419
            fetch_spec_factory.source_branch_stop_revision_id = stop_revision
 
3420
            fetch_spec_factory.source_repo = self.source.repository
 
3421
            fetch_spec_factory.target_repo = self.target.repository
 
3422
            fetch_spec_factory.target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
 
3423
            fetch_spec = fetch_spec_factory.make_fetch_spec()
 
3424
        else:
 
3425
            fetch_spec = _mod_graph.NotInOtherForRevs(self.target.repository,
 
3426
                self.source.repository, revision_ids=[stop_revision]).execute()
 
3427
        self.target.fetch(self.source, fetch_spec=fetch_spec)
3356
3428
        # Check to see if one is an ancestor of the other
3357
3429
        if not overwrite:
3358
3430
            if graph is None:
3427
3499
        finally:
3428
3500
            self.source.unlock()
3429
3501
 
3430
 
    def _basic_push(self, overwrite, stop_revision):
3431
 
        """Basic implementation of push without bound branches or hooks.
3432
 
 
3433
 
        Must be called with source read locked and target write locked.
3434
 
        """
3435
 
        result = BranchPushResult()
3436
 
        result.source_branch = self.source
3437
 
        result.target_branch = self.target
3438
 
        result.old_revno, result.old_revid = self.target.last_revision_info()
3439
 
        self.source.update_references(self.target)
3440
 
        if result.old_revid != stop_revision:
3441
 
            # We assume that during 'push' this repository is closer than
3442
 
            # the target.
3443
 
            graph = self.source.repository.get_graph(self.target.repository)
3444
 
            self._update_revisions(stop_revision, overwrite=overwrite,
3445
 
                    graph=graph)
3446
 
        if self.source._push_should_merge_tags():
3447
 
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3448
 
                overwrite)
3449
 
        result.new_revno, result.new_revid = self.target.last_revision_info()
3450
 
        return result
3451
 
 
3452
3502
    def _push_with_bound_branches(self, overwrite, stop_revision,
3453
3503
            _override_hook_source_branch=None):
3454
3504
        """Push from source into target, and into target's master if any.
3469
3519
            master_branch.lock_write()
3470
3520
            try:
3471
3521
                # 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)
 
3522
                self.source._basic_push(master_branch, overwrite, stop_revision)
 
3523
                # and push into the target branch from the source. Note that we
 
3524
                # push from the source branch again, because it's considered the
 
3525
                # highest bandwidth repository.
 
3526
                result = self.source._basic_push(self.target, overwrite,
 
3527
                    stop_revision)
3478
3528
                result.master_branch = master_branch
3479
3529
                result.local_branch = self.target
3480
3530
                _run_hooks()
3483
3533
                master_branch.unlock()
3484
3534
        else:
3485
3535
            # no master branch
3486
 
            result = self._basic_push(overwrite, stop_revision)
 
3536
            result = self.source._basic_push(self.target, overwrite,
 
3537
                stop_revision)
3487
3538
            # TODO: Why set master_branch and local_branch if there's no
3488
3539
            # binding?  Maybe cleaner to just leave them unset? -- mbp
3489
3540
            # 20070504
3532
3583
            # -- JRV20090506
3533
3584
            result.old_revno, result.old_revid = \
3534
3585
                self.target.last_revision_info()
3535
 
            self._update_revisions(stop_revision, overwrite=overwrite,
3536
 
                graph=graph)
 
3586
            self.target.update_revisions(self.source, stop_revision,
 
3587
                overwrite=overwrite, graph=graph)
3537
3588
            # TODO: The old revid should be specified when merging tags, 
3538
3589
            # so a tags implementation that versions tags can only 
3539
3590
            # pull in the most recent changes. -- JRV20090506