~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Robert Collins
  • Date: 2009-02-24 05:37:17 UTC
  • mto: This revision was merged to the branch mainline in revision 4038.
  • Revision ID: robertc@robertcollins.net-20090224053717-sau62hnxgo2f1pzr
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.

Show diffs side-by-side

added added

removed removed

Lines of Context:
69
69
                method, args, body_bytes)
70
70
        except errors.ErrorFromSmartServer, err:
71
71
            self._translate_error(err, **err_context)
72
 
        
 
72
 
 
73
 
 
74
def response_tuple_to_repo_format(response):
 
75
    """Convert a response tuple describing a repository format to a format."""
 
76
    format = RemoteRepositoryFormat()
 
77
    format.rich_root_data = (response[0] == 'yes')
 
78
    format.supports_tree_reference = (response[1] == 'yes')
 
79
    format.supports_external_lookups = (response[2] == 'yes')
 
80
    format._network_name = response[3]
 
81
    return format
 
82
 
 
83
 
73
84
# Note: RemoteBzrDirFormat is in bzrdir.py
74
85
 
75
86
class RemoteBzrDir(BzrDir, _RpcHelper):
343
354
            return self._vfs_initialize(a_bzrdir, shared)
344
355
        else:
345
356
            # Turn the response into a RemoteRepository object.
346
 
            format = RemoteRepositoryFormat()
347
 
            format.rich_root_data = (response[1] == 'yes')
348
 
            format.supports_tree_reference = (response[2] == 'yes')
349
 
            format.supports_external_lookups = (response[3] == 'yes')
350
 
            format._network_name = response[4]
 
357
            format = response_tuple_to_repo_format(response[1:])
351
358
            # Used to support creating a real format instance when needed.
352
359
            format._creating_bzrdir = a_bzrdir
353
360
            remote_repo = RemoteRepository(a_bzrdir, format)
382
389
 
383
390
    @property
384
391
    def _serializer(self):
385
 
        # We should only be getting asked for the serializer for
386
 
        # RemoteRepositoryFormat objects when the RemoteRepositoryFormat object
387
 
        # is a concrete instance for a RemoteRepository. In this case we know
388
 
        # the creating_repo and can use it to supply the serializer.
389
 
        self._creating_repo._ensure_real()
390
 
        return self._creating_repo._real_repository._format._serializer
 
392
        if self._custom_format is not None:
 
393
            return self._custom_format._serializer
 
394
        elif self._network_name is not None:
 
395
            self._custom_format = repository.network_format_registry.get(
 
396
                self._network_name)
 
397
            return self._custom_format._serializer
 
398
        else:
 
399
            # We should only be getting asked for the serializer for
 
400
            # RemoteRepositoryFormat objects when the RemoteRepositoryFormat object
 
401
            # is a concrete instance for a RemoteRepository. In this case we know
 
402
            # the creating_repo and can use it to supply the serializer.
 
403
            self._creating_repo._ensure_real()
 
404
            return self._creating_repo._real_repository._format._serializer
391
405
 
392
406
 
393
407
class RemoteRepository(_RpcHelper):
754
768
            raise errors.UnexpectedSmartServerResponse(response)
755
769
 
756
770
    def unlock(self):
 
771
        if not self._lock_count:
 
772
            raise errors.LockNotHeld(self)
757
773
        self._lock_count -= 1
758
774
        if self._lock_count > 0:
759
775
            return
1456
1472
        super(RemoteBranchFormat, self).__init__()
1457
1473
        self._matchingbzrdir = RemoteBzrDirFormat()
1458
1474
        self._matchingbzrdir.set_branch_format(self)
 
1475
        self._custom_format = None
1459
1476
 
1460
1477
    def __eq__(self, other):
1461
1478
        return (isinstance(other, RemoteBranchFormat) and 
1464
1481
    def get_format_description(self):
1465
1482
        return 'Remote BZR Branch'
1466
1483
 
1467
 
    def get_format_string(self):
1468
 
        return 'Remote BZR Branch'
1469
 
 
1470
1484
    def network_name(self):
1471
1485
        return self._network_name
1472
1486
 
1473
1487
    def open(self, a_bzrdir):
1474
1488
        return a_bzrdir.open_branch()
1475
1489
 
 
1490
    def _vfs_initialize(self, a_bzrdir):
 
1491
        # Initialisation when using a local bzrdir object, or a non-vfs init
 
1492
        # method is not available on the server.
 
1493
        # self._custom_format is always set - the start of initialize ensures
 
1494
        # that.
 
1495
        if isinstance(a_bzrdir, RemoteBzrDir):
 
1496
            a_bzrdir._ensure_real()
 
1497
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
 
1498
        else:
 
1499
            # We assume the bzrdir is parameterised; it may not be.
 
1500
            result = self._custom_format.initialize(a_bzrdir)
 
1501
        if (isinstance(a_bzrdir, RemoteBzrDir) and
 
1502
            not isinstance(result, RemoteBranch)):
 
1503
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
 
1504
        return result
 
1505
 
1476
1506
    def initialize(self, a_bzrdir):
1477
 
        # Delegate to a _real object here - the RemoteBzrDir format now
1478
 
        # supports delegating to parameterised branch formats and as such
1479
 
        # this RemoteBranchFormat method is only called when no specific format
1480
 
        # is selected.
 
1507
        # 1) get the network name to use.
 
1508
        if self._custom_format:
 
1509
            network_name = self._custom_format.network_name()
 
1510
        else:
 
1511
            # Select the current bzrlib default and ask for that.
 
1512
            reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
1513
            reference_format = reference_bzrdir_format.get_branch_format()
 
1514
            self._custom_format = reference_format
 
1515
            network_name = reference_format.network_name()
 
1516
        # Being asked to create on a non RemoteBzrDir:
1481
1517
        if not isinstance(a_bzrdir, RemoteBzrDir):
1482
 
            result = a_bzrdir.create_branch()
 
1518
            return self._vfs_initialize(a_bzrdir)
 
1519
        medium = a_bzrdir._client._medium
 
1520
        if medium._is_remote_before((1, 13)):
 
1521
            return self._vfs_initialize(a_bzrdir)
 
1522
        # Creating on a remote bzr dir.
 
1523
        # 2) try direct creation via RPC
 
1524
        path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
 
1525
        verb = 'BzrDir.create_branch'
 
1526
        try:
 
1527
            response = a_bzrdir._call(verb, path, network_name)
 
1528
        except errors.UnknownSmartMethod:
 
1529
            # Fallback - use vfs methods
 
1530
            return self._vfs_initialize(a_bzrdir)
 
1531
        if response[0] != 'ok':
 
1532
            raise errors.UnexpectedSmartServerResponse(response)
 
1533
        # Turn the response into a RemoteRepository object.
 
1534
        format = RemoteBranchFormat()
 
1535
        format._network_name = response[1]
 
1536
        repo_format = response_tuple_to_repo_format(response[3:])
 
1537
        if response[2] == '':
 
1538
            repo_bzrdir = a_bzrdir
1483
1539
        else:
1484
 
            a_bzrdir._ensure_real()
1485
 
            result = a_bzrdir._real_bzrdir.create_branch()
1486
 
        if not isinstance(result, RemoteBranch):
1487
 
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
1488
 
        return result
 
1540
            repo_bzrdir = RemoteBzrDir(
 
1541
                a_bzrdir.root_transport.clone(response[2]), a_bzrdir._format,
 
1542
                a_bzrdir._client)
 
1543
        remote_repo = RemoteRepository(repo_bzrdir, repo_format)
 
1544
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
 
1545
            format=format, setup_stacking=False)
 
1546
        return remote_branch
1489
1547
 
1490
1548
    def supports_tags(self):
1491
1549
        # Remote branches might support tags, but we won't know until we
1500
1558
    """
1501
1559
 
1502
1560
    def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
1503
 
        _client=None):
 
1561
        _client=None, format=None, setup_stacking=True):
1504
1562
        """Create a RemoteBranch instance.
1505
1563
 
1506
1564
        :param real_branch: An optional local implementation of the branch
1507
1565
            format, usually accessing the data via the VFS.
1508
1566
        :param _client: Private parameter for testing.
 
1567
        :param format: A RemoteBranchFormat object, None to create one
 
1568
            automatically. If supplied it should have a network_name already
 
1569
            supplied.
 
1570
        :param setup_stacking: If True make an RPC call to determine the
 
1571
            stacked (or not) status of the branch. If False assume the branch
 
1572
            is not stacked.
1509
1573
        """
1510
1574
        # We intentionally don't call the parent class's __init__, because it
1511
1575
        # will try to assign to self.tags, which is a property in this subclass.
1534
1598
        else:
1535
1599
            self._real_branch = None
1536
1600
        # Fill out expected attributes of branch for bzrlib api users.
1537
 
        self._format = RemoteBranchFormat()
1538
1601
        self.base = self.bzrdir.root_transport.base
1539
1602
        self._control_files = None
1540
1603
        self._lock_mode = None
1542
1605
        self._repo_lock_token = None
1543
1606
        self._lock_count = 0
1544
1607
        self._leave_lock = False
1545
 
        if real_branch is not None:
1546
 
            self._format._network_name = \
1547
 
                self._real_branch._format.network_name()
 
1608
        # Setup a format: note that we cannot call _ensure_real until all the
 
1609
        # attributes above are set: This code cannot be moved higher up in this
 
1610
        # function.
 
1611
        if format is None:
 
1612
            self._format = RemoteBranchFormat()
 
1613
            if real_branch is not None:
 
1614
                self._format._network_name = \
 
1615
                    self._real_branch._format.network_name()
 
1616
            #else:
 
1617
            #    # XXX: Need to get this from BzrDir.open_branch's return value.
 
1618
            #    self._ensure_real()
 
1619
            #    self._format._network_name = \
 
1620
            #        self._real_branch._format.network_name()
1548
1621
        else:
1549
 
            # XXX: Need to get this from BzrDir.open_branch's return value.
1550
 
            self._ensure_real()
1551
 
            self._format._network_name = \
1552
 
                self._real_branch._format.network_name()
 
1622
            self._format = format
1553
1623
        # The base class init is not called, so we duplicate this:
1554
1624
        hooks = branch.Branch.hooks['open']
1555
1625
        for hook in hooks:
1556
1626
            hook(self)
1557
 
        self._setup_stacking()
 
1627
        if setup_stacking:
 
1628
            self._setup_stacking()
1558
1629
 
1559
1630
    def _setup_stacking(self):
1560
1631
        # configure stacking into the remote repository, by reading it from
1900
1971
        self._ensure_real()
1901
1972
        return self._real_branch.set_stacked_on_url(stacked_location)
1902
1973
 
1903
 
    def sprout(self, to_bzrdir, revision_id=None):
1904
 
        branch_format = to_bzrdir._format._branch_format
1905
 
        if (branch_format is None or
1906
 
            isinstance(branch_format, RemoteBranchFormat)):
1907
 
            # The to_bzrdir specifies RemoteBranchFormat (or no format, which
1908
 
            # implies the same thing), but RemoteBranches can't be created at
1909
 
            # arbitrary URLs.  So create a branch in the same format as
1910
 
            # _real_branch instead.
1911
 
            # XXX: if to_bzrdir is a RemoteBzrDir, this should perhaps do
1912
 
            # to_bzrdir.create_branch to create a RemoteBranch after all...
1913
 
            self._ensure_real()
1914
 
            result = self._real_branch._format.initialize(to_bzrdir)
1915
 
            self.copy_content_into(result, revision_id=revision_id)
1916
 
            result.set_parent(self.bzrdir.root_transport.base)
1917
 
        else:
1918
 
            result = branch.Branch.sprout(
1919
 
                self, to_bzrdir, revision_id=revision_id)
1920
 
        return result
1921
 
 
1922
1974
    @needs_write_lock
1923
1975
    def pull(self, source, overwrite=False, stop_revision=None,
1924
1976
             **kwargs):