97
102
return (host, port, username, path)
105
def parse_git_error(url, message):
106
"""Parse a remote git server error and return a bzr exception.
108
:param url: URL of the remote repository
109
:param message: Message sent by the remote git server
111
message = str(message).strip()
112
if message.startswith("Could not find Repository "):
113
return NotBranchError(url, message)
114
# Don't know, just return it to the user as-is
115
return BzrError(message)
100
118
class GitSmartTransport(Transport):
102
120
def __init__(self, url, _client=None):
118
136
raise NotImplementedError(self._get_client)
120
138
def _get_path(self):
123
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
126
trace.info("git: %s" % text)
127
client = self._get_client(thin_packs=False)
129
return client.fetch_pack(self._get_path(), determine_wants,
130
graph_walker, pack_data, progress)
131
except GitProtocolError, e:
134
def send_pack(self, get_changed_refs, generate_pack_contents):
135
client = self._get_client(thin_packs=False)
137
return client.send_pack(self._get_path(), get_changed_refs,
138
generate_pack_contents)
139
except GitProtocolError, e:
139
return urlutils.split_segment_parameters_raw(self._path)[0]
142
141
def get(self, path):
143
142
raise NoSuchFile(path)
198
198
class RemoteGitDir(GitDir):
200
def __init__(self, transport, lockfiles, format):
200
def __init__(self, transport, lockfiles, format, get_client):
201
201
self._format = format
202
202
self.root_transport = transport
203
203
self.transport = transport
204
204
self._lockfiles = lockfiles
205
205
self._mode_check_done = None
207
def _branch_name_to_ref(self, name, default=None):
208
return branch_name_to_ref(name, default=default)
206
self._get_client = get_client
208
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
211
trace.info("git: %s" % text)
212
client = self._get_client(thin_packs=False)
214
return client.fetch_pack(self.transport._get_path(), determine_wants,
215
graph_walker, pack_data, progress)
216
except GitProtocolError, e:
217
raise parse_git_error(self.transport.external_url(), e)
219
def send_pack(self, get_changed_refs, generate_pack_contents):
220
client = self._get_client(thin_packs=False)
222
return client.send_pack(self.transport._get_path(), get_changed_refs,
223
generate_pack_contents)
224
except GitProtocolError, e:
225
raise parse_git_error(self.transport.external_url(), e)
229
return self.control_url
232
def user_transport(self):
233
return self.root_transport
210
235
def open_repository(self):
211
236
return RemoteGitRepository(self, self._lockfiles)
213
def _open_branch(self, name=None, ignore_fallbacks=False,
238
def open_branch(self, name=None, unsupported=False,
239
ignore_fallbacks=False):
215
240
repo = self.open_repository()
216
refname = self._branch_name_to_ref(name)
241
refname = self._get_selected_ref(name)
217
242
return RemoteGitBranch(self, repo, refname, self._lockfiles)
219
244
def open_workingtree(self, recommend_upgrade=False):
262
287
os.remove(self._data_path)
290
class RemoteGitControlDirFormat(GitControlDirFormat):
291
"""The .git directory control format."""
293
supports_workingtrees = False
296
def _known_formats(self):
297
return set([RemoteGitControlDirFormat()])
299
def open(self, transport, _found=None):
300
"""Open this directory.
303
# we dont grok readonly - git isn't integrated with transport.
305
if url.startswith('readonly+'):
306
url = url[len('readonly+'):]
307
if (not url.startswith("git://") and not url.startswith("git+")):
308
raise NotBranchError(transport.base)
309
if not isinstance(transport, GitSmartTransport):
310
raise NotBranchError(transport.base)
311
lockfiles = GitLockableFiles(transport, GitLock())
312
return RemoteGitDir(transport, lockfiles, self, transport._get_client)
314
def get_format_description(self):
315
return "Remote Git Repository"
317
def initialize_on_transport(self, transport):
318
raise UninitializableFormat(self)
265
321
class RemoteGitRepository(GitRepository):
267
323
def __init__(self, gitdir, lockfiles):
269
325
self._refs = None
272
def inventories(self):
273
raise GitSmartRemoteNotSupported()
277
raise GitSmartRemoteNotSupported()
329
return self.control_url
331
def get_parent_map(self, revids):
281
332
raise GitSmartRemoteNotSupported()
283
334
def get_refs(self):
284
335
if self._refs is not None:
285
336
return self._refs
286
self._refs = self.bzrdir.root_transport.fetch_pack(lambda x: [], None,
337
self._refs = self.bzrdir.fetch_pack(lambda x: [], None,
287
338
lambda x: None, lambda x: trace.mutter("git: %s" % x))
288
339
return self._refs
290
341
def fetch_pack(self, determine_wants, graph_walker, pack_data,
292
return self._transport.fetch_pack(determine_wants, graph_walker,
343
return self.bzrdir.fetch_pack(determine_wants, graph_walker,
293
344
pack_data, progress)
295
346
def send_pack(self, get_changed_refs, generate_pack_contents):
296
return self._transport.send_pack(get_changed_refs, generate_pack_contents)
347
return self.bzrdir.send_pack(get_changed_refs, generate_pack_contents)
298
349
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref,
300
351
fd, path = tempfile.mkstemp(suffix=".pack")
301
self.fetch_pack(determine_wants, graph_walker,
302
lambda x: os.write(fd, x), progress)
353
self.fetch_pack(determine_wants, graph_walker,
354
lambda x: os.write(fd, x), progress)
304
357
if os.path.getsize(path) == 0:
305
358
return EmptyObjectStoreIterator()
306
359
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
322
375
return mapping.revision_id_foreign_to_bzr(foreign_revid)
325
class RemoteGitTagDict(tag.BasicTags):
327
def __init__(self, branch):
329
self.repository = branch.repository
331
def get_tag_dict(self):
333
for k, v in extract_tags(self.repository.get_refs()).iteritems():
334
tags[k] = self.branch.mapping.revision_id_foreign_to_bzr(v)
378
class RemoteGitTagDict(GitTags):
381
return self.repository.get_refs()
383
def _iter_tag_refs(self, refs):
384
for k, (peeled, unpeeled) in extract_tags(refs).iteritems():
385
yield (k, peeled, unpeeled,
386
self.branch.mapping.revision_id_foreign_to_bzr(peeled))
337
388
def set_tag(self, name, revid):
338
389
# FIXME: Not supported yet, should do a push of a new ref
346
397
super(RemoteGitBranch, self).__init__(bzrdir, repository, name,
400
def last_revision_info(self):
401
raise GitSmartRemoteNotSupported()
405
return self.control_url
408
def control_url(self):
349
411
def revision_history(self):
350
412
raise GitSmartRemoteNotSupported()