33
32
from bzrlib.branch import BranchReferenceFormat
34
33
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
35
from bzrlib.config import BranchConfig, TreeConfig
36
34
from bzrlib.decorators import needs_read_lock, needs_write_lock
37
35
from bzrlib.errors import (
39
37
SmartProtocolError,
41
39
from bzrlib.lockable_files import LockableFiles
42
from bzrlib.pack import ContainerPushParser
43
40
from bzrlib.smart import client, vfs
44
from bzrlib.symbol_versioning import (
48
41
from bzrlib.revision import ensure_null, NULL_REVISION
49
42
from bzrlib.trace import mutter, note, warning
357
350
Used before calls to self._real_repository.
359
if not self._real_repository:
352
if self._real_repository is None:
360
353
self.bzrdir._ensure_real()
361
#self._real_repository = self.bzrdir._real_bzrdir.open_repository()
362
self._set_real_repository(self.bzrdir._real_bzrdir.open_repository())
354
self._set_real_repository(
355
self.bzrdir._real_bzrdir.open_repository())
364
357
def _translate_error(self, err, **context):
365
358
self.bzrdir._translate_error(err, repository=self, **context)
550
543
raise errors.UnexpectedSmartServerResponse(response)
552
def lock_write(self, token=None):
545
def lock_write(self, token=None, _skip_rpc=False):
553
546
if not self._lock_mode:
554
self._lock_token = self._remote_lock_write(token)
548
if self._lock_token is not None:
549
if token != self._lock_token:
550
raise errors.TokenMismatch(token, self._lock_token)
551
self._lock_token = token
553
self._lock_token = self._remote_lock_write(token)
555
554
# if self._lock_token is None, then this is something like packs or
556
555
# svn where we don't get to lock the repo, or a weave style repository
557
556
# where we cannot lock it over the wire and attempts to do so will
589
588
:param repository: The repository to fallback to for non-hpss
590
589
implemented operations.
591
if self._real_repository is not None:
592
raise AssertionError('_real_repository is already set')
592
593
if isinstance(repository, RemoteRepository):
593
594
raise AssertionError()
594
595
self._real_repository = repository
703
704
# FIXME: It ought to be possible to call this without immediately
704
705
# triggering _ensure_real. For now it's the easiest thing to do.
705
706
self._ensure_real()
706
builder = self._real_repository.get_commit_builder(branch, parents,
707
real_repo = self._real_repository
708
builder = real_repo.get_commit_builder(branch, parents,
707
709
config, timestamp=timestamp, timezone=timezone,
708
710
committer=committer, revprops=revprops, revision_id=revision_id)
1301
1303
'to use vfs implementation')
1302
1304
self.bzrdir._ensure_real()
1303
1305
self._real_branch = self.bzrdir._real_bzrdir.open_branch()
1304
# Give the remote repository the matching real repo.
1305
real_repo = self._real_branch.repository
1306
if isinstance(real_repo, RemoteRepository):
1307
real_repo._ensure_real()
1308
real_repo = real_repo._real_repository
1309
self.repository._set_real_repository(real_repo)
1310
# Give the branch the remote repository to let fast-pathing happen.
1306
if self.repository._real_repository is None:
1307
# Give the remote repository the matching real repo.
1308
real_repo = self._real_branch.repository
1309
if isinstance(real_repo, RemoteRepository):
1310
real_repo._ensure_real()
1311
real_repo = real_repo._real_repository
1312
self.repository._set_real_repository(real_repo)
1313
# Give the real branch the remote repository to let fast-pathing
1311
1315
self._real_branch.repository = self.repository
1312
# XXX: deal with _lock_mode == 'w'
1313
1316
if self._lock_mode == 'r':
1314
1317
self._real_branch.lock_read()
1318
elif self._lock_mode == 'w':
1319
self._real_branch.lock_write(token=self._lock_token)
1316
1321
def _translate_error(self, err, **context):
1317
1322
self.repository._translate_error(err, branch=self, **context)
1394
1400
def lock_write(self, token=None):
1395
1401
if not self._lock_mode:
1402
# Lock the branch and repo in one remote call.
1396
1403
remote_tokens = self._remote_lock_write(token)
1397
1404
self._lock_token, self._repo_lock_token = remote_tokens
1398
1405
if not self._lock_token:
1399
1406
raise SmartProtocolError('Remote server did not return a token!')
1400
# TODO: We really, really, really don't want to call _ensure_real
1401
# here, but it's the easiest way to ensure coherency between the
1402
# state of the RemoteBranch and RemoteRepository objects and the
1403
# physical locks. If we don't materialise the real objects here,
1404
# then getting everything in the right state later is complex, so
1405
# for now we just do it the lazy way.
1406
# -- Andrew Bennetts, 2007-02-22.
1407
# Tell the self.repository object that it is locked.
1408
self.repository.lock_write(
1409
self._repo_lock_token, _skip_rpc=True)
1408
1411
if self._real_branch is not None:
1409
self._real_branch.repository.lock_write(
1410
token=self._repo_lock_token)
1412
self._real_branch.lock_write(token=self._lock_token)
1414
self._real_branch.repository.unlock()
1412
self._real_branch.lock_write(token=self._lock_token)
1415
1413
if token is not None:
1416
1414
self._leave_lock = True
1418
# XXX: this case seems to be unreachable; token cannot be None.
1419
1416
self._leave_lock = False
1420
1417
self._lock_mode = 'w'
1421
1418
self._lock_count = 1
1423
1420
raise errors.ReadOnlyTransaction
1425
1422
if token is not None:
1426
# A token was given to lock_write, and we're relocking, so check
1427
# that the given token actually matches the one we already have.
1423
# A token was given to lock_write, and we're relocking, so
1424
# check that the given token actually matches the one we
1428
1426
if token != self._lock_token:
1429
1427
raise errors.TokenMismatch(token, self._lock_token)
1430
1428
self._lock_count += 1
1429
# Re-lock the repository too.
1430
self.repository.lock_write(self._repo_lock_token)
1431
1431
return self._lock_token or None
1433
1433
def _unlock(self, branch_token, repo_token):
1442
1442
raise errors.UnexpectedSmartServerResponse(response)
1444
1444
def unlock(self):
1445
self._lock_count -= 1
1446
if not self._lock_count:
1447
self._clear_cached_state()
1448
mode = self._lock_mode
1449
self._lock_mode = None
1450
if self._real_branch is not None:
1451
if (not self._leave_lock and mode == 'w' and
1452
self._repo_lock_token):
1453
# If this RemoteBranch will remove the physical lock for the
1454
# repository, make sure the _real_branch doesn't do it
1455
# first. (Because the _real_branch's repository is set to
1456
# be the RemoteRepository.)
1457
self._real_branch.repository.leave_lock_in_place()
1458
self._real_branch.unlock()
1460
# Only write-locked branched need to make a remote method call
1461
# to perfom the unlock.
1463
if not self._lock_token:
1464
raise AssertionError('Locked, but no token!')
1465
branch_token = self._lock_token
1466
repo_token = self._repo_lock_token
1467
self._lock_token = None
1468
self._repo_lock_token = None
1469
if not self._leave_lock:
1470
self._unlock(branch_token, repo_token)
1446
self._lock_count -= 1
1447
if not self._lock_count:
1448
self._clear_cached_state()
1449
mode = self._lock_mode
1450
self._lock_mode = None
1451
if self._real_branch is not None:
1452
if (not self._leave_lock and mode == 'w' and
1453
self._repo_lock_token):
1454
# If this RemoteBranch will remove the physical lock
1455
# for the repository, make sure the _real_branch
1456
# doesn't do it first. (Because the _real_branch's
1457
# repository is set to be the RemoteRepository.)
1458
self._real_branch.repository.leave_lock_in_place()
1459
self._real_branch.unlock()
1461
# Only write-locked branched need to make a remote method
1462
# call to perfom the unlock.
1464
if not self._lock_token:
1465
raise AssertionError('Locked, but no token!')
1466
branch_token = self._lock_token
1467
repo_token = self._repo_lock_token
1468
self._lock_token = None
1469
self._repo_lock_token = None
1470
if not self._leave_lock:
1471
self._unlock(branch_token, repo_token)
1473
self.repository.unlock()
1472
1475
def break_lock(self):
1473
1476
self._ensure_real()
1518
1521
raise errors.UnexpectedSmartServerResponse(response)
1519
1522
new_revno, new_revision_id = response[1:]
1520
1523
self._last_revision_info_cache = new_revno, new_revision_id
1521
self._real_branch._last_revision_info_cache = new_revno, new_revision_id
1524
if self._real_branch is not None:
1525
cache = new_revno, new_revision_id
1526
self._real_branch._last_revision_info_cache = cache
1523
1528
def _set_last_revision(self, revision_id):
1524
1529
path = self.bzrdir._path_for_remote_call(self._client)
1732
1740
raise errors.DivergedBranches(find('branch'), find('other_branch'))
1733
1741
elif err.error_verb == 'TipChangeRejected':
1734
1742
raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
1743
raise errors.UnknownErrorFromSmartServer(err)