~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-06-25 23:07:24 UTC
  • mfrom: (3441.5.33 smart-push-gpm)
  • Revision ID: pqm@pqm.ubuntu.com-20080625230724-lyux37pu8nx8tq34
Add Branch.set_last_revision_ex HPSS verb to accelerate push. (Andrew
        Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1201
1201
        # And the parent's __init__ doesn't do much anyway.
1202
1202
        self._revision_id_to_revno_cache = None
1203
1203
        self._revision_history_cache = None
 
1204
        self._last_revision_info_cache = None
1204
1205
        self.bzrdir = remote_bzrdir
1205
1206
        if _client is not None:
1206
1207
            self._client = _client
1264
1265
            if self._lock_mode == 'r':
1265
1266
                self._real_branch.lock_read()
1266
1267
 
 
1268
    def _clear_cached_state(self):
 
1269
        super(RemoteBranch, self)._clear_cached_state()
 
1270
        if self._real_branch is not None:
 
1271
            self._real_branch._clear_cached_state()
 
1272
 
 
1273
    def _clear_cached_state_of_remote_branch_only(self):
 
1274
        """Like _clear_cached_state, but doesn't clear the cache of
 
1275
        self._real_branch.
 
1276
 
 
1277
        This is useful when falling back to calling a method of
 
1278
        self._real_branch that changes state.  In that case the underlying
 
1279
        branch changes, so we need to invalidate this RemoteBranch's cache of
 
1280
        it.  However, there's no need to invalidate the _real_branch's cache
 
1281
        too, in fact doing so might harm performance.
 
1282
        """
 
1283
        super(RemoteBranch, self)._clear_cached_state()
 
1284
        
1267
1285
    @property
1268
1286
    def control_files(self):
1269
1287
        # Defer actually creating RemoteBranchLockableFiles until its needed,
1415
1433
            raise NotImplementedError(self.dont_leave_lock_in_place)
1416
1434
        self._leave_lock = False
1417
1435
 
1418
 
    def last_revision_info(self):
1419
 
        """See Branch.last_revision_info()."""
 
1436
    def _last_revision_info(self):
1420
1437
        path = self.bzrdir._path_for_remote_call(self._client)
1421
1438
        response = self._client.call('Branch.last_revision_info', path)
1422
1439
        if response[0] != 'ok':
1431
1448
        response_tuple, response_handler = self._client.call_expecting_body(
1432
1449
            'Branch.revision_history', path)
1433
1450
        if response_tuple[0] != 'ok':
1434
 
            raise UnexpectedSmartServerResponse(response_tuple)
 
1451
            raise errors.UnexpectedSmartServerResponse(response_tuple)
1435
1452
        result = response_handler.read_body_bytes().split('\x00')
1436
1453
        if result == ['']:
1437
1454
            return []
1438
1455
        return result
1439
1456
 
 
1457
    def _set_last_revision_descendant(self, revision_id, other_branch,
 
1458
            allow_diverged=False, allow_overwrite_descendant=False):
 
1459
        path = self.bzrdir._path_for_remote_call(self._client)
 
1460
        try:
 
1461
            response = self._client.call('Branch.set_last_revision_ex',
 
1462
                path, self._lock_token, self._repo_lock_token, revision_id,
 
1463
                int(allow_diverged), int(allow_overwrite_descendant))
 
1464
        except errors.ErrorFromSmartServer, err:
 
1465
            if err.error_verb == 'NoSuchRevision':
 
1466
                raise NoSuchRevision(self, revision_id)
 
1467
            elif err.error_verb == 'Diverged':
 
1468
                raise errors.DivergedBranches(self, other_branch)
 
1469
            raise
 
1470
        self._clear_cached_state()
 
1471
        if len(response) != 3 and response[0] != 'ok':
 
1472
            raise errors.UnexpectedSmartServerResponse(response)
 
1473
        new_revno, new_revision_id = response[1:]
 
1474
        self._last_revision_info_cache = new_revno, new_revision_id
 
1475
        self._real_branch._last_revision_info_cache = new_revno, new_revision_id
 
1476
 
 
1477
    def _set_last_revision(self, revision_id):
 
1478
        path = self.bzrdir._path_for_remote_call(self._client)
 
1479
        self._clear_cached_state()
 
1480
        try:
 
1481
            response = self._client.call('Branch.set_last_revision',
 
1482
                path, self._lock_token, self._repo_lock_token, revision_id)
 
1483
        except errors.ErrorFromSmartServer, err:
 
1484
            if err.error_verb == 'NoSuchRevision':
 
1485
                raise NoSuchRevision(self, revision_id)
 
1486
            raise
 
1487
        if response != ('ok',):
 
1488
            raise errors.UnexpectedSmartServerResponse(response)
 
1489
 
1440
1490
    @needs_write_lock
1441
1491
    def set_revision_history(self, rev_history):
1442
1492
        # Send just the tip revision of the history; the server will generate
1443
1493
        # the full history from that.  If the revision doesn't exist in this
1444
1494
        # branch, NoSuchRevision will be raised.
1445
 
        path = self.bzrdir._path_for_remote_call(self._client)
1446
1495
        if rev_history == []:
1447
1496
            rev_id = 'null:'
1448
1497
        else:
1449
1498
            rev_id = rev_history[-1]
1450
 
        self._clear_cached_state()
1451
 
        try:
1452
 
            response = self._client.call('Branch.set_last_revision',
1453
 
                path, self._lock_token, self._repo_lock_token, rev_id)
1454
 
        except errors.ErrorFromSmartServer, err:
1455
 
            if err.error_verb == 'NoSuchRevision':
1456
 
                raise NoSuchRevision(self, rev_id)
1457
 
            raise
1458
 
        if response != ('ok',):
1459
 
            raise errors.UnexpectedSmartServerResponse(response)
 
1499
        self._set_last_revision(rev_id)
1460
1500
        self._cache_revision_history(rev_history)
1461
1501
 
1462
1502
    def get_parent(self):
1481
1521
    @needs_write_lock
1482
1522
    def pull(self, source, overwrite=False, stop_revision=None,
1483
1523
             **kwargs):
 
1524
        self._clear_cached_state_of_remote_branch_only()
1484
1525
        self._ensure_real()
1485
1526
        return self._real_branch.pull(
1486
1527
            source, overwrite=overwrite, stop_revision=stop_revision,
1505
1546
                path, self._lock_token, self._repo_lock_token, str(revno), revision_id)
1506
1547
        except errors.UnknownSmartMethod:
1507
1548
            self._ensure_real()
1508
 
            self._clear_cached_state()
1509
 
            return self._real_branch.set_last_revision_info(revno, revision_id)
 
1549
            self._clear_cached_state_of_remote_branch_only()
 
1550
            self._real_branch.set_last_revision_info(revno, revision_id)
 
1551
            self._last_revision_info_cache = revno, revision_id
 
1552
            return
1510
1553
        except errors.ErrorFromSmartServer, err:
1511
1554
            if err.error_verb == 'NoSuchRevision':
1512
1555
                raise NoSuchRevision(self, err.error_args[0])
1513
1556
            raise
1514
1557
        if response == ('ok',):
1515
1558
            self._clear_cached_state()
 
1559
            self._last_revision_info_cache = revno, revision_id
 
1560
            # Update the _real_branch's cache too.
 
1561
            if self._real_branch is not None:
 
1562
                cache = self._last_revision_info_cache
 
1563
                self._real_branch._last_revision_info_cache = cache
1516
1564
        else:
1517
1565
            raise errors.UnexpectedSmartServerResponse(response)
1518
1566
 
 
1567
    @needs_write_lock
1519
1568
    def generate_revision_history(self, revision_id, last_rev=None,
1520
1569
                                  other_branch=None):
 
1570
        medium = self._client._medium
 
1571
        if not medium._is_remote_before((1, 6)):
 
1572
            try:
 
1573
                self._set_last_revision_descendant(revision_id, other_branch,
 
1574
                    allow_diverged=True, allow_overwrite_descendant=True)
 
1575
                return
 
1576
            except errors.UnknownSmartMethod:
 
1577
                medium._remember_remote_is_before((1, 6))
 
1578
        self._clear_cached_state_of_remote_branch_only()
1521
1579
        self._ensure_real()
1522
 
        return self._real_branch.generate_revision_history(
 
1580
        self._real_branch.generate_revision_history(
1523
1581
            revision_id, last_rev=last_rev, other_branch=other_branch)
1524
1582
 
1525
1583
    @property
1531
1589
        self._ensure_real()
1532
1590
        return self._real_branch.set_push_location(location)
1533
1591
 
 
1592
    @needs_write_lock
1534
1593
    def update_revisions(self, other, stop_revision=None, overwrite=False,
1535
1594
                         graph=None):
1536
 
        self._ensure_real()
1537
 
        return self._real_branch.update_revisions(
1538
 
            other, stop_revision=stop_revision, overwrite=overwrite,
1539
 
            graph=graph)
 
1595
        """See Branch.update_revisions."""
 
1596
        other.lock_read()
 
1597
        try:
 
1598
            if stop_revision is None:
 
1599
                stop_revision = other.last_revision()
 
1600
                if revision.is_null(stop_revision):
 
1601
                    # if there are no commits, we're done.
 
1602
                    return
 
1603
            self.fetch(other, stop_revision)
 
1604
 
 
1605
            if overwrite:
 
1606
                # Just unconditionally set the new revision.  We don't care if
 
1607
                # the branches have diverged.
 
1608
                self._set_last_revision(stop_revision)
 
1609
            else:
 
1610
                medium = self._client._medium
 
1611
                if not medium._is_remote_before((1, 6)):
 
1612
                    try:
 
1613
                        self._set_last_revision_descendant(stop_revision, other)
 
1614
                        return
 
1615
                    except errors.UnknownSmartMethod:
 
1616
                        medium._remember_remote_is_before((1, 6))
 
1617
                # Fallback for pre-1.6 servers: check for divergence
 
1618
                # client-side, then do _set_last_revision.
 
1619
                last_rev = revision.ensure_null(self.last_revision())
 
1620
                if graph is None:
 
1621
                    graph = self.repository.get_graph()
 
1622
                if self._check_if_descendant_or_diverged(
 
1623
                        stop_revision, last_rev, graph, other):
 
1624
                    # stop_revision is a descendant of last_rev, but we aren't
 
1625
                    # overwriting, so we're done.
 
1626
                    return
 
1627
                self._set_last_revision(stop_revision)
 
1628
        finally:
 
1629
            other.unlock()
1540
1630
 
1541
1631
 
1542
1632
def _extract_tar(tar, to_dir):