~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: John Arbash Meinel
  • Date: 2007-06-28 23:18:09 UTC
  • mfrom: (2562 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2566.
  • Revision ID: john@arbash-meinel.com-20070628231809-pqbt7puoqj8bl07b
[merge] bzr.dev 2562

Show diffs side-by-side

added added

removed removed

Lines of Context:
783
783
        :return: The tree of the created checkout
784
784
        """
785
785
        t = transport.get_transport(to_location)
786
 
        try:
787
 
            t.mkdir('.')
788
 
        except errors.FileExists:
789
 
            pass
 
786
        t.ensure_base()
790
787
        if lightweight:
791
788
            format = self._get_checkout_format()
792
789
            checkout = format.initialize_on_transport(t)
850
847
    _formats = {}
851
848
    """The known formats."""
852
849
 
 
850
    def __eq__(self, other):
 
851
        return self.__class__ is other.__class__
 
852
 
 
853
    def __ne__(self, other):
 
854
        return not (self == other)
 
855
 
853
856
    @classmethod
854
857
    def find_format(klass, a_bzrdir):
855
858
        """Return the format for the branch object in a_bzrdir."""
1000
1003
        # (push_result)
1001
1004
        # containing the members
1002
1005
        # (source, local, master, old_revno, old_revid, new_revno, new_revid)
1003
 
        # where local is the local branch or None, master is the target 
 
1006
        # where local is the local target branch or None, master is the target 
1004
1007
        # master branch, and the rest should be self explanatory. The source
1005
1008
        # is read locked and the target branches write locked. Source will
1006
1009
        # be the local low-latency branch.
1451
1454
            # we fetch here regardless of whether we need to so that we pickup
1452
1455
            # filled in ghosts.
1453
1456
            self.fetch(other, stop_revision)
1454
 
            my_ancestry = self.repository.get_ancestry(last_rev)
 
1457
            my_ancestry = self.repository.get_ancestry(last_rev,
 
1458
                                                       topo_sorted=False)
1455
1459
            if stop_revision in my_ancestry:
1456
1460
                # last_revision is a descendant of stop_revision
1457
1461
                return
1476
1480
 
1477
1481
    @needs_write_lock
1478
1482
    def pull(self, source, overwrite=False, stop_revision=None,
1479
 
        _hook_master=None, _run_hooks=True):
 
1483
             _hook_master=None, run_hooks=True):
1480
1484
        """See Branch.pull.
1481
1485
 
1482
1486
        :param _hook_master: Private parameter - set the branch to 
1483
1487
            be supplied as the master to push hooks.
1484
 
        :param _run_hooks: Private parameter - allow disabling of
1485
 
            hooks, used when pushing to a master branch.
 
1488
        :param run_hooks: Private parameter - if false, this branch
 
1489
            is being called because it's the master of the primary branch,
 
1490
            so it should not run its hooks.
1486
1491
        """
1487
1492
        result = PullResult()
1488
1493
        result.source_branch = source
1507
1512
            else:
1508
1513
                result.master_branch = self
1509
1514
                result.local_branch = None
1510
 
            if _run_hooks:
 
1515
            if run_hooks:
1511
1516
                for hook in Branch.hooks['post_pull']:
1512
1517
                    hook(result)
1513
1518
        finally:
1525
1530
 
1526
1531
    @needs_read_lock
1527
1532
    def push(self, target, overwrite=False, stop_revision=None,
1528
 
        _hook_master=None, _run_hooks=True):
 
1533
             _override_hook_source_branch=None):
1529
1534
        """See Branch.push.
 
1535
 
 
1536
        This is the basic concrete implementation of push()
 
1537
 
 
1538
        :param _override_hook_source_branch: If specified, run
 
1539
        the hooks passing this Branch as the source, rather than self.  
 
1540
        This is for use of RemoteBranch, where push is delegated to the
 
1541
        underlying vfs-based Branch. 
 
1542
        """
 
1543
        # TODO: Public option to disable running hooks - should be trivial but
 
1544
        # needs tests.
 
1545
        target.lock_write()
 
1546
        try:
 
1547
            result = self._push_with_bound_branches(target, overwrite,
 
1548
                    stop_revision,
 
1549
                    _override_hook_source_branch=_override_hook_source_branch)
 
1550
            return result
 
1551
        finally:
 
1552
            target.unlock()
 
1553
 
 
1554
    def _push_with_bound_branches(self, target, overwrite,
 
1555
            stop_revision,
 
1556
            _override_hook_source_branch=None):
 
1557
        """Push from self into target, and into target's master if any.
1530
1558
        
1531
 
        :param _hook_master: Private parameter - set the branch to 
1532
 
            be supplied as the master to push hooks.
1533
 
        :param _run_hooks: Private parameter - allow disabling of
1534
 
            hooks, used when pushing to a master branch.
 
1559
        This is on the base BzrBranch class even though it doesn't support 
 
1560
        bound branches because the *target* might be bound.
 
1561
        """
 
1562
        def _run_hooks():
 
1563
            if _override_hook_source_branch:
 
1564
                result.source_branch = _override_hook_source_branch
 
1565
            for hook in Branch.hooks['post_push']:
 
1566
                hook(result)
 
1567
 
 
1568
        bound_location = target.get_bound_location()
 
1569
        if bound_location and target.base != bound_location:
 
1570
            # there is a master branch.
 
1571
            #
 
1572
            # XXX: Why the second check?  Is it even supported for a branch to
 
1573
            # be bound to itself? -- mbp 20070507
 
1574
            master_branch = target.get_master_branch()
 
1575
            master_branch.lock_write()
 
1576
            try:
 
1577
                # push into the master from this branch.
 
1578
                self._basic_push(master_branch, overwrite, stop_revision)
 
1579
                # and push into the target branch from this. Note that we push from
 
1580
                # this branch again, because its considered the highest bandwidth
 
1581
                # repository.
 
1582
                result = self._basic_push(target, overwrite, stop_revision)
 
1583
                result.master_branch = master_branch
 
1584
                result.local_branch = target
 
1585
                _run_hooks()
 
1586
                return result
 
1587
            finally:
 
1588
                master_branch.unlock()
 
1589
        else:
 
1590
            # no master branch
 
1591
            result = self._basic_push(target, overwrite, stop_revision)
 
1592
            # TODO: Why set master_branch and local_branch if there's no
 
1593
            # binding?  Maybe cleaner to just leave them unset? -- mbp
 
1594
            # 20070504
 
1595
            result.master_branch = target
 
1596
            result.local_branch = None
 
1597
            _run_hooks()
 
1598
            return result
 
1599
 
 
1600
    def _basic_push(self, target, overwrite, stop_revision):
 
1601
        """Basic implementation of push without bound branches or hooks.
 
1602
 
 
1603
        Must be called with self read locked and target write locked.
1535
1604
        """
1536
1605
        result = PushResult()
1537
1606
        result.source_branch = self
1538
1607
        result.target_branch = target
1539
 
        target.lock_write()
 
1608
        result.old_revno, result.old_revid = target.last_revision_info()
1540
1609
        try:
1541
 
            result.old_revno, result.old_revid = target.last_revision_info()
1542
 
            try:
1543
 
                target.update_revisions(self, stop_revision)
1544
 
            except DivergedBranches:
1545
 
                if not overwrite:
1546
 
                    raise
1547
 
            if overwrite:
1548
 
                target.set_revision_history(self.revision_history())
1549
 
            result.tag_conflicts = self.tags.merge_to(target.tags)
1550
 
            result.new_revno, result.new_revid = target.last_revision_info()
1551
 
            if _hook_master:
1552
 
                result.master_branch = _hook_master
1553
 
                result.local_branch = target
1554
 
            else:
1555
 
                result.master_branch = target
1556
 
                result.local_branch = None
1557
 
            if _run_hooks:
1558
 
                for hook in Branch.hooks['post_push']:
1559
 
                    hook(result)
1560
 
        finally:
1561
 
            target.unlock()
 
1610
            target.update_revisions(self, stop_revision)
 
1611
        except DivergedBranches:
 
1612
            if not overwrite:
 
1613
                raise
 
1614
        if overwrite:
 
1615
            target.set_revision_history(self.revision_history())
 
1616
        result.tag_conflicts = self.tags.merge_to(target.tags)
 
1617
        result.new_revno, result.new_revid = target.last_revision_info()
1562
1618
        return result
1563
1619
 
1564
1620
    def get_parent(self):
1634
1690
        
1635
1691
    @needs_write_lock
1636
1692
    def pull(self, source, overwrite=False, stop_revision=None,
1637
 
        _run_hooks=True):
1638
 
        """Extends branch.pull to be bound branch aware.
 
1693
             run_hooks=True):
 
1694
        """Pull from source into self, updating my master if any.
1639
1695
        
1640
 
        :param _run_hooks: Private parameter used to force hook running
1641
 
            off during bound branch double-pushing.
 
1696
        :param run_hooks: Private parameter - if false, this branch
 
1697
            is being called because it's the master of the primary branch,
 
1698
            so it should not run its hooks.
1642
1699
        """
1643
1700
        bound_location = self.get_bound_location()
1644
1701
        master_branch = None
1650
1707
            if master_branch:
1651
1708
                # pull from source into master.
1652
1709
                master_branch.pull(source, overwrite, stop_revision,
1653
 
                    _run_hooks=False)
 
1710
                    run_hooks=False)
1654
1711
            return super(BzrBranch5, self).pull(source, overwrite,
1655
1712
                stop_revision, _hook_master=master_branch,
1656
 
                _run_hooks=_run_hooks)
1657
 
        finally:
1658
 
            if master_branch:
1659
 
                master_branch.unlock()
1660
 
 
1661
 
    @needs_read_lock
1662
 
    def push(self, target, overwrite=False, stop_revision=None):
1663
 
        """Updates branch.push to be bound branch aware."""
1664
 
        bound_location = target.get_bound_location()
1665
 
        master_branch = None
1666
 
        if bound_location and target.base != bound_location:
1667
 
            # not pushing to master, so we need to update master.
1668
 
            master_branch = target.get_master_branch()
1669
 
            master_branch.lock_write()
1670
 
        try:
1671
 
            if master_branch:
1672
 
                # push into the master from this branch.
1673
 
                super(BzrBranch5, self).push(master_branch, overwrite,
1674
 
                    stop_revision, _run_hooks=False)
1675
 
            # and push into the target branch from this. Note that we push from
1676
 
            # this branch again, because its considered the highest bandwidth
1677
 
            # repository.
1678
 
            return super(BzrBranch5, self).push(target, overwrite,
1679
 
                stop_revision, _hook_master=master_branch)
 
1713
                run_hooks=run_hooks)
1680
1714
        finally:
1681
1715
            if master_branch:
1682
1716
                master_branch.unlock()
1780
1814
        if master is not None:
1781
1815
            old_tip = self.last_revision()
1782
1816
            self.pull(master, overwrite=True)
1783
 
            if old_tip in self.repository.get_ancestry(self.last_revision()):
 
1817
            if old_tip in self.repository.get_ancestry(self.last_revision(),
 
1818
                                                       topo_sorted=False):
1784
1819
                return None
1785
1820
            return old_tip
1786
1821
        return None
2050
2085
        if revision_id is None:
2051
2086
            revno, revision_id = self.last_revision_info()
2052
2087
        else:
2053
 
            revno = self.revision_id_to_revno(revision_id)
 
2088
            # To figure out the revno for a random revision, we need to build
 
2089
            # the revision history, and count its length.
 
2090
            # We don't care about the order, just how long it is.
 
2091
            # Alternatively, we could start at the current location, and count
 
2092
            # backwards. But there is no guarantee that we will find it since
 
2093
            # it may be a merged revision.
 
2094
            revno = len(list(self.repository.iter_reverse_revision_history(
 
2095
                                                                revision_id)))
2054
2096
        destination.set_last_revision_info(revno, revision_id)
2055
2097
 
2056
2098
    def _make_tags(self):