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
88
81
self._real_bzrdir = BzrDir.open_from_transport(
89
82
self.root_transport, _server_formats=False)
91
def cloning_metadir(self):
84
def cloning_metadir(self, stacked=False):
92
85
self._ensure_real()
93
return self._real_bzrdir.cloning_metadir()
86
return self._real_bzrdir.cloning_metadir(stacked)
95
88
def _translate_error(self, err, **context):
96
89
_translate_error(err, bzrdir=self, **context)
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)
1050
1051
tar = tarfile.open('repository', fileobj=tar_file,
1052
tmpdir = tempfile.mkdtemp()
1053
tmpdir = osutils.mkdtemp()
1054
1055
_extract_tar(tar, tmpdir)
1055
1056
tmp_bzrdir = BzrDir.open(tmpdir)
1302
1303
'to use vfs implementation')
1303
1304
self.bzrdir._ensure_real()
1304
1305
self._real_branch = self.bzrdir._real_bzrdir.open_branch()
1305
# Give the remote repository the matching real repo.
1306
real_repo = self._real_branch.repository
1307
if isinstance(real_repo, RemoteRepository):
1308
real_repo._ensure_real()
1309
real_repo = real_repo._real_repository
1310
self.repository._set_real_repository(real_repo)
1311
# 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
1312
1315
self._real_branch.repository = self.repository
1313
# XXX: deal with _lock_mode == 'w'
1314
1316
if self._lock_mode == 'r':
1315
1317
self._real_branch.lock_read()
1318
elif self._lock_mode == 'w':
1319
self._real_branch.lock_write(token=self._lock_token)
1317
1321
def _translate_error(self, err, **context):
1318
1322
self.repository._translate_error(err, branch=self, **context)
1395
1400
def lock_write(self, token=None):
1396
1401
if not self._lock_mode:
1402
# Lock the branch and repo in one remote call.
1397
1403
remote_tokens = self._remote_lock_write(token)
1398
1404
self._lock_token, self._repo_lock_token = remote_tokens
1399
1405
if not self._lock_token:
1400
1406
raise SmartProtocolError('Remote server did not return a token!')
1401
# TODO: We really, really, really don't want to call _ensure_real
1402
# here, but it's the easiest way to ensure coherency between the
1403
# state of the RemoteBranch and RemoteRepository objects and the
1404
# physical locks. If we don't materialise the real objects here,
1405
# then getting everything in the right state later is complex, so
1406
# for now we just do it the lazy way.
1407
# -- 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)
1409
1411
if self._real_branch is not None:
1410
self._real_branch.repository.lock_write(
1411
token=self._repo_lock_token)
1413
self._real_branch.lock_write(token=self._lock_token)
1415
self._real_branch.repository.unlock()
1412
self._real_branch.lock_write(token=self._lock_token)
1416
1413
if token is not None:
1417
1414
self._leave_lock = True
1419
# XXX: this case seems to be unreachable; token cannot be None.
1420
1416
self._leave_lock = False
1421
1417
self._lock_mode = 'w'
1422
1418
self._lock_count = 1
1424
1420
raise errors.ReadOnlyTransaction
1426
1422
if token is not None:
1427
# A token was given to lock_write, and we're relocking, so check
1428
# 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
1429
1426
if token != self._lock_token:
1430
1427
raise errors.TokenMismatch(token, self._lock_token)
1431
1428
self._lock_count += 1
1429
# Re-lock the repository too.
1430
self.repository.lock_write(self._repo_lock_token)
1432
1431
return self._lock_token or None
1434
1433
def _unlock(self, branch_token, repo_token):
1443
1442
raise errors.UnexpectedSmartServerResponse(response)
1445
1444
def unlock(self):
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 for the
1455
# repository, make sure the _real_branch doesn't do it
1456
# first. (Because the _real_branch's repository is set to
1457
# 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 call
1462
# 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)
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()
1473
1475
def break_lock(self):
1474
1476
self._ensure_real()
1519
1521
raise errors.UnexpectedSmartServerResponse(response)
1520
1522
new_revno, new_revision_id = response[1:]
1521
1523
self._last_revision_info_cache = new_revno, new_revision_id
1522
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
1524
1528
def _set_last_revision(self, revision_id):
1525
1529
path = self.bzrdir._path_for_remote_call(self._client)
1593
1597
def is_locked(self):
1594
1598
return self._lock_count >= 1
1601
def revision_id_to_revno(self, revision_id):
1603
return self._real_branch.revision_id_to_revno(revision_id)
1596
1605
@needs_write_lock
1597
1606
def set_last_revision_info(self, revno, revision_id):
1598
1607
revision_id = ensure_null(revision_id)
1728
1740
raise errors.DivergedBranches(find('branch'), find('other_branch'))
1729
1741
elif err.error_verb == 'TipChangeRejected':
1730
1742
raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
1743
raise errors.UnknownErrorFromSmartServer(err)