~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
    repository,
29
29
    revision,
30
30
    symbol_versioning,
 
31
    urlutils,
31
32
)
32
33
from bzrlib.branch import BranchReferenceFormat
33
34
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
425
426
            'Repository.has_revision', path, revision_id)
426
427
        if response[0] not in ('yes', 'no'):
427
428
            raise errors.UnexpectedSmartServerResponse(response)
428
 
        return response[0] == 'yes'
 
429
        if response[0] == 'yes':
 
430
            return True
 
431
        for fallback_repo in self._fallback_repositories:
 
432
            if fallback_repo.has_revision(revision_id):
 
433
                return True
 
434
        return False
429
435
 
430
436
    def has_revisions(self, revision_ids):
431
437
        """See Repository.has_revisions()."""
 
438
        # FIXME: This does many roundtrips, particularly when there are
 
439
        # fallback repositories.  -- mbp 20080905
432
440
        result = set()
433
441
        for revision_id in revision_ids:
434
442
            if self.has_revision(revision_id):
593
601
        if isinstance(repository, RemoteRepository):
594
602
            raise AssertionError()
595
603
        self._real_repository = repository
 
604
        for fb in self._fallback_repositories:
 
605
            self._real_repository.add_fallback_repository(fb)
596
606
        if self._lock_mode == 'w':
597
607
            # if we are already locked, the real repository must be able to
598
608
            # acquire the lock with our token.
715
725
        
716
726
        :param repository: A repository.
717
727
        """
718
 
        if not self._format.supports_external_lookups:
719
 
            raise errors.UnstackableRepositoryFormat(self._format, self.base)
 
728
        # XXX: At the moment the RemoteRepository will allow fallbacks
 
729
        # unconditionally - however, a _real_repository will usually exist,
 
730
        # and may raise an error if it's not accommodated by the underlying
 
731
        # format.  Eventually we should check when opening the repository
 
732
        # whether it's willing to allow them or not.
 
733
        #
720
734
        # We need to accumulate additional repositories here, to pass them in
721
735
        # on various RPC's.
722
736
        self._fallback_repositories.append(repository)
 
737
        # They are also seen by the fallback repository.  If it doesn't exist
 
738
        # yet they'll be added then.  This implicitly copies them.
 
739
        self._ensure_real()
723
740
 
724
741
    def add_inventory(self, revid, inv, parents):
725
742
        self._ensure_real()
1279
1296
        self._repo_lock_token = None
1280
1297
        self._lock_count = 0
1281
1298
        self._leave_lock = False
 
1299
        # The base class init is not called, so we duplicate this:
 
1300
        hooks = branch.Branch.hooks['open']
 
1301
        for hook in hooks:
 
1302
            hook(self)
 
1303
        self._setup_stacking()
 
1304
 
 
1305
    def _setup_stacking(self):
 
1306
        # configure stacking into the remote repository, by reading it from
 
1307
        # the vfs branch.
 
1308
        try:
 
1309
            fallback_url = self.get_stacked_on_url()
 
1310
        except (errors.NotStacked, errors.UnstackableBranchFormat,
 
1311
            errors.UnstackableRepositoryFormat), e:
 
1312
            return
 
1313
        # it's relative to this branch...
 
1314
        fallback_url = urlutils.join(self.base, fallback_url)
 
1315
        transports = [self.bzrdir.root_transport]
 
1316
        if self._real_branch is not None:
 
1317
            transports.append(self._real_branch._transport)
 
1318
        fallback_bzrdir = BzrDir.open(fallback_url, transports)
 
1319
        fallback_repo = fallback_bzrdir.open_repository()
 
1320
        self.repository.add_fallback_repository(fallback_repo)
1282
1321
 
1283
1322
    def _get_real_transport(self):
1284
1323
        # if we try vfs access, return the real branch's vfs transport
1366
1405
        :raises UnstackableRepositoryFormat: If the repository does not support
1367
1406
            stacking.
1368
1407
        """
1369
 
        self._ensure_real()
1370
 
        return self._real_branch.get_stacked_on_url()
 
1408
        try:
 
1409
            response = self._client.call('Branch.get_stacked_on_url',
 
1410
                self._remote_path())
 
1411
            if response[0] != 'ok':
 
1412
                raise errors.UnexpectedSmartServerResponse(response)
 
1413
            return response[1]
 
1414
        except errors.ErrorFromSmartServer, err:
 
1415
            # there may not be a repository yet, so we can't call through
 
1416
            # its _translate_error
 
1417
            _translate_error(err, branch=self)
 
1418
        except errors.UnknownSmartMethod, err:
 
1419
            self._ensure_real()
 
1420
            return self._real_branch.get_stacked_on_url()
1371
1421
 
1372
1422
    def lock_read(self):
1373
1423
        self.repository.lock_read()
1386
1436
            branch_token = token
1387
1437
            repo_token = self.repository.lock_write()
1388
1438
            self.repository.unlock()
1389
 
        path = self.bzrdir._path_for_remote_call(self._client)
1390
1439
        try:
1391
1440
            response = self._client.call(
1392
 
                'Branch.lock_write', path, branch_token, repo_token or '')
 
1441
                'Branch.lock_write', self._remote_path(),
 
1442
                branch_token, repo_token or '')
1393
1443
        except errors.ErrorFromSmartServer, err:
1394
1444
            self._translate_error(err, token=token)
1395
1445
        if response[0] != 'ok':
1431
1481
        return self._lock_token or None
1432
1482
 
1433
1483
    def _unlock(self, branch_token, repo_token):
1434
 
        path = self.bzrdir._path_for_remote_call(self._client)
1435
1484
        try:
1436
 
            response = self._client.call('Branch.unlock', path, branch_token,
 
1485
            response = self._client.call('Branch.unlock', self._remote_path(), branch_token,
1437
1486
                                         repo_token or '')
1438
1487
        except errors.ErrorFromSmartServer, err:
1439
1488
            self._translate_error(err, token=str((branch_token, repo_token)))
1487
1536
        self._leave_lock = False
1488
1537
 
1489
1538
    def _last_revision_info(self):
1490
 
        path = self.bzrdir._path_for_remote_call(self._client)
1491
 
        response = self._client.call('Branch.last_revision_info', path)
 
1539
        response = self._client.call('Branch.last_revision_info', self._remote_path())
1492
1540
        if response[0] != 'ok':
1493
1541
            raise SmartProtocolError('unexpected response code %s' % (response,))
1494
1542
        revno = int(response[1])
1497
1545
 
1498
1546
    def _gen_revision_history(self):
1499
1547
        """See Branch._gen_revision_history()."""
1500
 
        path = self.bzrdir._path_for_remote_call(self._client)
1501
1548
        response_tuple, response_handler = self._client.call_expecting_body(
1502
 
            'Branch.revision_history', path)
 
1549
            'Branch.revision_history', self._remote_path())
1503
1550
        if response_tuple[0] != 'ok':
1504
1551
            raise errors.UnexpectedSmartServerResponse(response_tuple)
1505
1552
        result = response_handler.read_body_bytes().split('\x00')
1507
1554
            return []
1508
1555
        return result
1509
1556
 
 
1557
    def _remote_path(self):
 
1558
        return self.bzrdir._path_for_remote_call(self._client)
 
1559
 
1510
1560
    def _set_last_revision_descendant(self, revision_id, other_branch,
1511
1561
            allow_diverged=False, allow_overwrite_descendant=False):
1512
 
        path = self.bzrdir._path_for_remote_call(self._client)
1513
1562
        try:
1514
1563
            response = self._client.call('Branch.set_last_revision_ex',
1515
 
                path, self._lock_token, self._repo_lock_token, revision_id,
 
1564
                self._remote_path(), self._lock_token, self._repo_lock_token, revision_id,
1516
1565
                int(allow_diverged), int(allow_overwrite_descendant))
1517
1566
        except errors.ErrorFromSmartServer, err:
1518
1567
            self._translate_error(err, other_branch=other_branch)
1526
1575
            self._real_branch._last_revision_info_cache = cache
1527
1576
 
1528
1577
    def _set_last_revision(self, revision_id):
1529
 
        path = self.bzrdir._path_for_remote_call(self._client)
1530
1578
        self._clear_cached_state()
1531
1579
        try:
1532
1580
            response = self._client.call('Branch.set_last_revision',
1533
 
                path, self._lock_token, self._repo_lock_token, revision_id)
 
1581
                self._remote_path(), self._lock_token, self._repo_lock_token, revision_id)
1534
1582
        except errors.ErrorFromSmartServer, err:
1535
1583
            self._translate_error(err)
1536
1584
        if response != ('ok',):
1605
1653
    @needs_write_lock
1606
1654
    def set_last_revision_info(self, revno, revision_id):
1607
1655
        revision_id = ensure_null(revision_id)
1608
 
        path = self.bzrdir._path_for_remote_call(self._client)
1609
1656
        try:
1610
1657
            response = self._client.call('Branch.set_last_revision_info',
1611
 
                path, self._lock_token, self._repo_lock_token, str(revno), revision_id)
 
1658
                self._remote_path(), self._lock_token, self._repo_lock_token, str(revno), revision_id)
1612
1659
        except errors.UnknownSmartMethod:
1613
1660
            self._ensure_real()
1614
1661
            self._clear_cached_state_of_remote_branch_only()
1740
1787
        raise errors.DivergedBranches(find('branch'), find('other_branch'))
1741
1788
    elif err.error_verb == 'TipChangeRejected':
1742
1789
        raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
 
1790
    elif err.error_verb == 'UnstackableBranchFormat':
 
1791
        raise errors.UnstackableBranchFormat(*err.error_args)
 
1792
    elif err.error_verb == 'UnstackableRepositoryFormat':
 
1793
        raise errors.UnstackableRepositoryFormat(*err.error_args)
 
1794
    elif err.error_verb == 'NotStacked':
 
1795
        raise errors.NotStacked(branch=find('branch'))
1743
1796
    raise errors.UnknownErrorFromSmartServer(err)
1744