15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
from bzrlib.bzrdir import (
27
from bzrlib.errors import (
32
from bzrlib.lockable_files import (
35
from bzrlib.repository import (
38
from bzrlib.trace import (
41
from bzrlib.transport import (
45
from bzrlib.plugins.git import (
50
from bzrlib.plugins.git.branch import (
53
from bzrlib.plugins.git.errors import (
54
GitSmartRemoteNotSupported,
57
from bzrlib.plugins.git.dir import (
60
from bzrlib.plugins.git.foreign import (
63
from bzrlib.plugins.git.repository import (
69
from dulwich.errors import (
72
from dulwich.pack import (
18
from bzrlib import urlutils
19
from bzrlib.bzrdir import BzrDir, BzrDirFormat
20
from bzrlib.errors import NoSuchFile, NotLocalUrl
21
from bzrlib.lockable_files import TransportLock
22
from bzrlib.repository import Repository
23
from bzrlib.trace import info
24
from bzrlib.transport import Transport
26
from bzrlib.plugins.git import git
27
from bzrlib.plugins.git.branch import GitBranch
28
from bzrlib.plugins.git.foreign import ForeignBranch
29
from bzrlib.plugins.git.repository import GitFormat, GitRepository
82
from dulwich.pack import load_pack_index
84
from dulwich.pack import PackIndex as load_pack_index
87
# Don't run any tests on GitSmartTransport as it is not intended to be
88
# a full implementation of Transport
89
def get_test_permutations():
93
35
class GitSmartTransport(Transport):
95
37
def __init__(self, url, _client=None):
96
38
Transport.__init__(self, url)
97
39
(scheme, _, loc, _, _) = urlparse.urlsplit(url)
40
assert scheme == "git"
98
41
hostport, self._path = urllib.splithost(loc)
99
42
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
100
self._client = _client
102
def has(self, relpath):
105
def _get_client(self):
106
raise NotImplementedError(self._get_client)
43
if _client is not None:
44
self._client = _client
46
self._client = git.client.TCPGitClient(self._host, self._port)
108
48
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
109
49
if progress is None:
110
50
def progress(text):
111
51
info("git: %s" % text)
112
client = self._get_client()
114
client.fetch_pack(self._path, determine_wants,
115
graph_walker, pack_data, progress)
116
except GitProtocolError, e:
52
self._client.fetch_pack(self._path, determine_wants, graph_walker,
119
55
def get(self, path):
120
56
raise NoSuchFile(path)
122
def abspath(self, relpath):
123
return urlutils.join(self.base, relpath)
125
58
def clone(self, offset=None):
126
59
"""See Transport.clone()."""
127
60
if offset is None:
130
63
newurl = urlutils.join(self.base, offset)
132
return self.__class__(newurl, self._client)
135
class TCPGitSmartTransport(GitSmartTransport):
137
def _get_client(self):
138
if self._client is not None:
142
return git.client.TCPGitClient(self._host, self._port, thin_packs=False)
145
class SSHGitSmartTransport(GitSmartTransport):
147
def _get_client(self):
148
if self._client is not None:
152
return git.client.SSHGitClient(self._host, self._port, thin_packs=False)
155
class RemoteGitDir(GitDir):
65
return GitSmartTransport(newurl, self._client)
68
class RemoteGitDir(BzrDir):
157
70
def __init__(self, transport, lockfiles, format):
158
71
self._format = format
171
87
def open_workingtree(self):
172
88
raise NotLocalUrl(self.transport.base)
175
class EmptyObjectStoreIterator(dict):
177
def iterobjects(self):
181
class TemporaryPackIterator(Pack):
183
def __init__(self, path, resolve_ext_ref):
184
super(TemporaryPackIterator, self).__init__(path)
185
self.resolve_ext_ref = resolve_ext_ref
189
if self._idx is None:
190
if self._data is None:
191
self._data = PackData(self._data_path)
192
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref)
193
self._idx = load_pack_index(self._idx_path)
197
os.remove(self._data_path)
198
os.remove(self._idx_path)
90
def cloning_metadir(self, stacked=False):
91
"""Produce a metadir suitable for cloning with."""
93
return bzrlib.bzrdir.format_registry.make_bzrdir("1.6.1-rich-root")
95
return bzrlib.bzrdir.format_registry.make_bzrdir("rich-root-pack")
201
98
class RemoteGitRepository(GitRepository):
203
100
def __init__(self, gitdir, lockfiles):
204
101
GitRepository.__init__(self, gitdir, lockfiles)
208
def inventories(self):
209
raise GitSmartRemoteNotSupported()
213
raise GitSmartRemoteNotSupported()
217
raise GitSmartRemoteNotSupported()
220
if self._refs is not None:
222
def determine_wants(heads):
225
self.bzrdir.root_transport.fetch_pack(determine_wants, None,
226
lambda x: None, lambda x: mutter("git: %s" % x))
229
def fetch_pack(self, determine_wants, graph_walker, pack_data,
231
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
234
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
235
fd, path = tempfile.mkstemp(suffix=".pack")
236
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
238
if os.path.getsize(path) == 0:
239
return EmptyObjectStoreIterator()
240
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
243
class RemoteGitTagDict(tag.BasicTags):
245
def __init__(self, branch):
247
self.repository = branch.repository
249
def get_tag_dict(self):
251
refs = self.repository.get_refs()
252
for k,v in refs.iteritems():
253
if k.startswith("refs/tags/") and not k.endswith("^{}"):
254
v = refs.get(k+"^{}", v)
255
ret[k[len("refs/tags/"):]] = self.branch.mapping.revision_id_foreign_to_bzr(v)
258
def set_tag(self, name, revid):
259
# FIXME: Not supported yet, should do a push of a new ref
260
raise NotImplementedError(self.set_tag)
103
def fetch_pack(self, determine_wants, graph_walker, pack_data):
104
self._transport.fetch_pack(determine_wants, graph_walker, pack_data)
263
107
class RemoteGitBranch(GitBranch):
265
109
def __init__(self, bzrdir, repository, name, lockfiles):
266
heads = repository.get_refs()
267
if not name in heads:
268
raise NoSuchRef(name)
269
self._ref = heads[name]
110
def determine_wants(heads):
111
self._ref = heads[name]
112
bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None,
113
lambda x: mutter("git: %s" % x))
270
114
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
272
116
def last_revision(self):
273
return self.mapping.revision_id_foreign_to_bzr(self._ref)
275
def _synchronize_history(self, destination, revision_id):
276
"""See Branch._synchronize_history()."""
277
destination.generate_revision_history(self.last_revision())