20
20
from cStringIO import StringIO
21
21
from urlparse import urlparse
23
from bzrlib import branch, errors, repository
23
from bzrlib import branch, errors, lockdir, repository
24
24
from bzrlib.branch import BranchReferenceFormat
25
25
from bzrlib.bzrdir import BzrDir, BzrDirFormat, RemoteBzrDirFormat
26
26
from bzrlib.config import BranchConfig, TreeConfig
27
27
from bzrlib.decorators import needs_read_lock, needs_write_lock
28
28
from bzrlib.errors import NoSuchRevision
29
from bzrlib.lockable_files import LockableFiles
29
30
from bzrlib.revision import NULL_REVISION
30
31
from bzrlib.smart import client, vfs
31
32
from bzrlib.urlutils import unescape
85
86
real_workingtree = self._real_bzrdir.create_workingtree(revision_id=revision_id)
86
87
return RemoteWorkingTree(self, real_workingtree)
88
def open_branch(self, _unsupported=False):
89
assert _unsupported == False, 'unsupported flag support not implemented yet.'
89
def find_branch_format(self):
90
"""Find the branch 'format' for this bzrdir.
92
This might be a synthetic object for e.g. RemoteBranch and SVN.
94
b = self.open_branch()
97
def get_branch_reference(self):
98
"""See BzrDir.get_branch_reference()."""
90
99
path = self._path_for_remote_call(self._client)
91
100
response = self._client.call('BzrDir.open_branch', path)
92
101
if response[0] == 'ok':
93
102
if response[1] == '':
94
103
# branch at this location.
95
return RemoteBranch(self, self.find_repository())
97
106
# a branch reference, use the existing BranchReference logic.
98
format = BranchReferenceFormat()
99
return format.open(self, _found=True, location=response[1])
100
108
elif response == ('nobranch',):
101
109
raise errors.NotBranchError(path=self.root_transport.base)
103
111
assert False, 'unexpected response code %r' % (response,)
113
def open_branch(self, _unsupported=False):
114
assert _unsupported == False, 'unsupported flag support not implemented yet.'
115
reference_url = self.get_branch_reference()
116
if reference_url is None:
117
# branch at this location.
118
return RemoteBranch(self, self.find_repository())
120
# a branch reference, use the existing BranchReference logic.
121
format = BranchReferenceFormat()
122
return format.open(self, _found=True, location=reference_url)
105
124
def open_repository(self):
106
125
path = self._path_for_remote_call(self._client)
119
138
raise errors.NoRepositoryPresent(self)
121
140
def open_workingtree(self):
122
return RemoteWorkingTree(self, self._real_bzrdir.open_workingtree())
141
raise errors.NotLocalUrl(self.root_transport)
124
143
def _path_for_remote_call(self, client):
125
144
"""Return the path to be used for this bzrdir in a remote call."""
587
606
return self._real_repository.has_signature_for_revision_id(revision_id)
590
class RemoteBranchLockableFiles(object):
609
class RemoteBranchLockableFiles(LockableFiles):
591
610
"""A 'LockableFiles' implementation that talks to a smart server.
593
612
This is not a public interface class.
596
615
def __init__(self, bzrdir, _client):
597
616
self.bzrdir = bzrdir
598
617
self._client = _client
618
# XXX: This assumes that the branch control directory is .bzr/branch,
619
# which isn't necessarily true.
620
LockableFiles.__init__(
621
self, bzrdir.root_transport.clone('.bzr/branch'),
622
'lock', lockdir.LockDir)
600
624
def get(self, path):
601
625
"""'get' a remote path as per the LockableFiles interface.
604
628
just retrieve a file, instead we ask the smart server to generate
605
629
a configuration for us - which is retrieved as an INI file.
607
assert path == 'branch.conf'
608
path = self.bzrdir._path_for_remote_call(self._client)
609
response = self._client.call2('Branch.get_config_file', path)
610
assert response[0][0] == 'ok', \
611
'unexpected response code %s' % (response[0],)
612
return StringIO(response[1].read_body_bytes())
631
if path == 'branch.conf':
632
path = self.bzrdir._path_for_remote_call(self._client)
633
response = self._client.call2('Branch.get_config_file', path)
634
assert response[0][0] == 'ok', \
635
'unexpected response code %s' % (response[0],)
636
return StringIO(response[1].read_body_bytes())
639
return LockableFiles.get(self, path)
615
642
class RemoteBranchFormat(branch.BranchFormat):
644
def __eq__(self, other):
645
return (isinstance(other, RemoteBranchFormat) and
646
self.__dict__ == other.__dict__)
617
648
def get_format_description(self):
618
649
return 'Remote BZR Branch'
918
949
other, stop_revision=stop_revision)
921
class RemoteWorkingTree(object):
923
def __init__(self, remote_bzrdir, real_workingtree):
924
self.real_workingtree = real_workingtree
925
self.bzrdir = remote_bzrdir
927
def __getattr__(self, name):
928
# XXX: temporary way to lazily delegate everything to the real
930
return getattr(self.real_workingtree, name)
933
952
class RemoteBranchConfig(BranchConfig):
935
954
def username(self):