118
146
raise NotImplementedError(self._get_client)
120
148
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:
149
return self._stripped_path
142
151
def get(self, path):
143
152
raise NoSuchFile(path)
198
208
class RemoteGitDir(GitDir):
200
def __init__(self, transport, lockfiles, format):
210
def __init__(self, transport, format, get_client, client_path):
201
211
self._format = format
202
212
self.root_transport = transport
203
213
self.transport = transport
204
self._lockfiles = lockfiles
205
214
self._mode_check_done = None
207
def _branch_name_to_ref(self, name, default=None):
208
return branch_name_to_ref(name, default=default)
215
self._get_client = get_client
216
self._client_path = client_path
217
self.base = self.root_transport.base
220
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
223
trace.info("git: %s" % text)
224
def wrap_determine_wants(refs_dict):
225
return determine_wants(remote_refs_dict_to_container(refs_dict))
226
client = self._get_client(thin_packs=False)
228
refs_dict = client.fetch_pack(self._client_path, wrap_determine_wants,
229
graph_walker, pack_data, progress)
230
self._refs = remote_refs_dict_to_container(refs_dict)
232
except GitProtocolError, e:
233
raise parse_git_error(self.transport.external_url(), e)
235
def send_pack(self, get_changed_refs, generate_pack_contents):
236
client = self._get_client(thin_packs=False)
238
return client.send_pack(self._client_path, get_changed_refs,
239
generate_pack_contents)
240
except GitProtocolError, e:
241
raise parse_git_error(self.transport.external_url(), e)
243
def _get_default_ref(self):
244
return "refs/heads/master"
246
def destroy_branch(self, name=None):
247
refname = self._get_selected_ref(name)
248
def get_changed_refs(old_refs):
250
if not refname in ret:
251
raise NotBranchError(self.user_url)
252
ret[refname] = "00" * 20
254
self.send_pack(get_changed_refs, lambda have, want: [])
258
return self.control_url
261
def user_transport(self):
262
return self.root_transport
265
def control_url(self):
266
return self.control_transport.base
269
def control_transport(self):
270
return self.root_transport
210
272
def open_repository(self):
211
return RemoteGitRepository(self, self._lockfiles)
273
return RemoteGitRepository(self)
213
def _open_branch(self, name=None, ignore_fallbacks=False,
275
def open_branch(self, name=None, unsupported=False,
276
ignore_fallbacks=False, ref=None, possible_transports=None):
215
277
repo = self.open_repository()
216
refname = self._branch_name_to_ref(name)
217
return RemoteGitBranch(self, repo, refname, self._lockfiles)
278
refname = self._get_selected_ref(name, ref)
279
return RemoteGitBranch(self, repo, refname)
219
281
def open_workingtree(self, recommend_upgrade=False):
220
282
raise NotLocalUrl(self.transport.base)
284
def get_peeled(self, name):
285
return self.get_refs_container().get_peeled(name)
287
def get_refs_container(self):
288
if self._refs is not None:
290
refs_dict = self.fetch_pack(lambda x: [], None,
291
lambda x: None, lambda x: trace.mutter("git: %s" % x))
292
self._refs = remote_refs_dict_to_container(refs_dict)
223
296
class EmptyObjectStoreIterator(dict):
262
335
os.remove(self._data_path)
338
class BzrGitHttpClient(dulwich.client.HttpGitClient):
340
def __init__(self, transport, *args, **kwargs):
341
self.transport = transport
342
super(BzrGitHttpClient, self).__init__(transport.external_url(), *args, **kwargs)
344
self._http_perform = getattr(self.transport, "_perform", urllib2.urlopen)
346
def _perform(self, req):
347
req.accepted_errors = (200, 404)
348
req.follow_redirections = True
349
req.redirected_to = None
350
return self._http_perform(req)
353
class RemoteGitControlDirFormat(GitControlDirFormat):
354
"""The .git directory control format."""
356
supports_workingtrees = False
359
def _known_formats(self):
360
return set([RemoteGitControlDirFormat()])
362
def is_initializable(self):
365
def is_supported(self):
368
def open(self, transport, _found=None):
369
"""Open this directory.
372
# we dont grok readonly - git isn't integrated with transport.
374
if url.startswith('readonly+'):
375
url = url[len('readonly+'):]
376
if isinstance(transport, GitSmartTransport):
377
get_client = transport._get_client
378
client_path = transport._get_path()
379
elif urlparse.urlsplit(transport.external_url())[0] in ("http", "https"):
380
def get_client(thin_packs=False):
381
return BzrGitHttpClient(transport, thin_packs=thin_packs)
382
client_path, _ = urlutils.split_segment_parameters(transport._path)
384
raise NotBranchError(transport.base)
385
return RemoteGitDir(transport, self, get_client, client_path)
387
def get_format_description(self):
388
return "Remote Git Repository"
390
def initialize_on_transport(self, transport):
391
raise UninitializableFormat(self)
393
def supports_transport(self, transport):
395
external_url = transport.external_url()
396
except InProcessTransport:
397
raise NotBranchError(path=transport.base)
398
return (external_url.startswith("http:") or
399
external_url.startswith("https:") or
400
external_url.startswith("git+") or
401
external_url.startswith("git:"))
265
404
class RemoteGitRepository(GitRepository):
267
def __init__(self, gitdir, lockfiles):
268
GitRepository.__init__(self, gitdir, lockfiles)
272
def inventories(self):
273
raise GitSmartRemoteNotSupported()
277
raise GitSmartRemoteNotSupported()
281
raise GitSmartRemoteNotSupported()
284
if self._refs is not None:
286
self._refs = self.bzrdir.root_transport.fetch_pack(lambda x: [], None,
287
lambda x: None, lambda x: trace.mutter("git: %s" % x))
408
return self.control_url
410
def get_parent_map(self, revids):
411
raise GitSmartRemoteNotSupported(self.get_parent_map, self)
290
413
def fetch_pack(self, determine_wants, graph_walker, pack_data,
292
return self._transport.fetch_pack(determine_wants, graph_walker,
415
return self.bzrdir.fetch_pack(determine_wants, graph_walker,
293
416
pack_data, progress)
295
418
def send_pack(self, get_changed_refs, generate_pack_contents):
296
return self._transport.send_pack(get_changed_refs, generate_pack_contents)
419
return self.bzrdir.send_pack(get_changed_refs, generate_pack_contents)
298
421
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref,
300
423
fd, path = tempfile.mkstemp(suffix=".pack")
301
self.fetch_pack(determine_wants, graph_walker,
302
lambda x: os.write(fd, x), progress)
425
self.fetch_pack(determine_wants, graph_walker,
426
lambda x: os.write(fd, x), progress)
304
429
if os.path.getsize(path) == 0:
305
430
return EmptyObjectStoreIterator()
306
431
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
321
446
# Not really an easy way to parse foreign revids here..
322
447
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)
449
def revision_tree(self, revid):
450
raise GitSmartRemoteNotSupported(self.revision_tree, self)
452
def get_revisions(self, revids):
453
raise GitSmartRemoteNotSupported(self.get_revisions, self)
455
def has_revisions(self, revids):
456
raise GitSmartRemoteNotSupported(self.get_revisions, self)
459
class RemoteGitTagDict(GitTags):
461
def get_refs_container(self):
462
return self.repository.bzrdir.get_refs_container()
337
464
def set_tag(self, name, revid):
338
465
# FIXME: Not supported yet, should do a push of a new ref
342
469
class RemoteGitBranch(GitBranch):
344
def __init__(self, bzrdir, repository, name, lockfiles):
471
def __init__(self, bzrdir, repository, name):
346
super(RemoteGitBranch, self).__init__(bzrdir, repository, name,
473
super(RemoteGitBranch, self).__init__(bzrdir, repository, name)
475
def last_revision_info(self):
476
raise GitSmartRemoteNotSupported(self.last_revision_info, self)
480
return self.control_url
483
def control_url(self):
349
486
def revision_history(self):
350
raise GitSmartRemoteNotSupported()
487
raise GitSmartRemoteNotSupported(self.revision_history, self)
489
def revision_id_to_revno(self, revision_id):
490
raise GitSmartRemoteNotSupported(self.revision_id_to_revno, self)
352
492
def last_revision(self):
353
493
return self.lookup_foreign_revision_id(self.head)
355
def _get_config(self):
356
class EmptyConfig(object):
358
def _get_configobj(self):
359
return config.ConfigObj()
365
497
if self._sha is not None:
367
heads = self.repository.get_refs()
368
name = self.bzrdir._branch_name_to_ref(self.name, "HEAD")
370
self._sha = heads[name]
372
raise NoSuchRef(self.name)
499
refs = self.bzrdir.get_refs_container()
500
name = branch_name_to_ref(self.name)
502
self._sha = refs[name]
504
raise NoSuchRef(name, self.repository.user_url, refs)
375
507
def _synchronize_history(self, destination, revision_id):