193
191
:param message: Message sent by the remote git server
195
193
message = str(message).strip()
196
if (message.startswith("Could not find Repository ") or
197
message == 'Repository not found.' or
198
(message.startswith('Repository ') and message.endswith(' not found.'))):
194
if (message.startswith("Could not find Repository ")
195
or message == 'Repository not found.'
196
or (message.startswith('Repository ') and
197
message.endswith(' not found.'))):
199
198
return NotBranchError(url, message)
200
199
if message == "HEAD failed to update":
201
200
base_url, _ = urlutils.split_segment_parameters(url)
203
202
if message.startswith('access denied or repository not exported:'):
204
203
extra, path = message.split(': ', 1)
205
204
return PermissionDenied(path, extra)
205
if message.endswith('You are not allowed to push code to this project.'):
206
return PermissionDenied(url, message)
207
if message.endswith(' does not appear to be a git repository'):
208
return NotBranchError(url, message)
209
m = re.match(r'Permission to ([^ ]+) denied to ([^ ]+)\.', message)
211
return PermissionDenied(m.group(1), 'denied to %s' % m.group(2))
206
212
# Don't know, just return it to the user as-is
207
213
return RemoteGitError(message)
259
265
if self._host == '':
260
266
# return dulwich.client.LocalGitClient()
261
267
return dulwich.client.SubprocessGitClient()
262
return dulwich.client.TCPGitClient(self._host, self._port,
263
report_activity=self._report_activity)
268
return dulwich.client.TCPGitClient(
269
self._host, self._port, report_activity=self._report_activity)
266
272
class SSHSocketWrapper(object):
285
291
self.bzr_ssh_vendor = ssh._get_ssh_vendor()
287
293
def run_command(self, host, command, username=None, port=None):
288
connection = self.bzr_ssh_vendor.connect_ssh(username=username,
289
password=None, port=port, host=host, command=command)
294
connection = self.bzr_ssh_vendor.connect_ssh(
295
username=username, password=None, port=port, host=host,
290
297
(kind, io_object) = connection.get_sock_or_pipes()
291
298
if kind == 'socket':
292
299
return SSHSocketWrapper(io_object)
313
320
self._client = None
315
322
location_config = config.LocationConfig(self.base)
316
client = dulwich.client.SSHGitClient(self._host, self._port, self._username,
323
client = dulwich.client.SSHGitClient(
324
self._host, self._port, self._username,
317
325
report_activity=self._report_activity)
318
326
# Set up alternate pack program paths
319
327
upload_pack = location_config.get_user_option('git_upload_pack')
350
358
def progress(self, text):
351
359
text = text.rstrip(b"\r\n")
352
360
text = text.decode('utf-8')
353
if text.startswith('error: '):
361
if text.lower().startswith('error: '):
354
362
trace.show_error('git: %s', text[len(b'error: '):])
356
364
trace.mutter("git: %s", text)
383
391
def _gitrepository_class(self):
384
392
return RemoteGitRepository
386
def archive(self, format, committish, write_data, progress=None, write_error=None,
387
subdirs=None, prefix=None):
388
if format not in ('tar', 'zip'):
389
raise errors.NoSuchExportFormat(format)
394
def archive(self, format, committish, write_data, progress=None,
395
write_error=None, subdirs=None, prefix=None):
390
396
if progress is None:
391
397
pb = ui.ui_factory.nested_progress_bar()
392
398
progress = DefaultProgressReporter(pb).progress
401
def progress_wrapper(message):
402
if message.startswith(b"fatal: Unknown archive format \'"):
403
format = message.strip()[len(b"fatal: Unknown archive format '"):-1]
404
raise errors.NoSuchExportFormat(format.decode('ascii'))
405
return progress(message)
396
self._client.archive(self._client_path, committish,
397
write_data, progress, write_error, format=format,
398
subdirs=subdirs, prefix=prefix)
407
self._client.archive(
408
self._client_path, committish, write_data, progress_wrapper,
410
format=(format.encode('ascii') if format else None),
412
prefix=(prefix.encode('utf-8') if prefix else None))
399
413
except GitProtocolError as e:
400
414
raise parse_git_error(self.transport.external_url(), e)
402
416
if pb is not None:
405
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
419
def fetch_pack(self, determine_wants, graph_walker, pack_data,
406
421
if progress is None:
407
422
pb = ui.ui_factory.nested_progress_bar()
408
423
progress = DefaultProgressReporter(pb).progress
412
result = self._client.fetch_pack(self._client_path, determine_wants,
413
graph_walker, pack_data, progress)
427
result = self._client.fetch_pack(
428
self._client_path, determine_wants, graph_walker, pack_data,
414
430
if result.refs is None:
416
self._refs = remote_refs_dict_to_container(result.refs, result.symrefs)
432
self._refs = remote_refs_dict_to_container(
433
result.refs, result.symrefs)
418
435
except GitProtocolError as e:
419
436
raise parse_git_error(self.transport.external_url(), e)
427
444
progress = DefaultProgressReporter(pb).progress
430
448
def get_changed_refs_wrapper(refs):
431
449
# TODO(jelmer): This drops symref information
432
450
self._refs = remote_refs_dict_to_container(refs)
433
451
return get_changed_refs(refs)
435
return self._client.send_pack(self._client_path,
436
get_changed_refs_wrapper, generate_pack_data, progress)
453
return self._client.send_pack(
454
self._client_path, get_changed_refs_wrapper,
455
generate_pack_data, progress)
437
456
except GitProtocolError as e:
438
457
raise parse_git_error(self.transport.external_url(), e)
446
465
if refname != b'HEAD' and refname in self.get_refs_container():
447
466
raise AlreadyBranchError(self.user_url)
448
467
if refname in self.get_refs_container():
449
ref_chain, unused_sha = self.get_refs_container().follow(self._get_selected_ref(None))
468
ref_chain, unused_sha = self.get_refs_container().follow(
469
self._get_selected_ref(None))
450
470
if ref_chain[0] == b'HEAD':
451
471
refname = ref_chain[1]
452
472
repo = self.open_repository()
455
475
def destroy_branch(self, name=None):
456
476
refname = self._get_selected_ref(name)
457
478
def get_changed_refs(old_refs):
458
479
ret = dict(old_refs)
459
if not refname in ret:
480
if refname not in ret:
460
481
raise NotBranchError(self.user_url)
461
482
ret[refname] = dulwich.client.ZERO_SHA
463
485
def generate_pack_data(have, want, ofs_delta=False):
464
486
return pack_objects_to_data([])
465
487
self.send_pack(get_changed_refs, generate_pack_data)
483
505
def open_repository(self):
484
506
return RemoteGitRepository(self)
508
def get_branch_reference(self, name=None):
509
ref = branch_name_to_ref(name)
510
val = self.get_refs_container().read_ref(ref)
511
if val.startswith(SYMREF):
512
return val[len(SYMREF):]
486
515
def open_branch(self, name=None, unsupported=False,
487
ignore_fallbacks=False, ref=None, possible_transports=None,
516
ignore_fallbacks=False, ref=None, possible_transports=None,
489
518
repo = self.open_repository()
490
519
ref = self._get_selected_ref(name, ref)
491
if not nascent_ok and ref not in self.get_refs_container():
521
if not nascent_ok and ref not in self.get_refs_container():
522
raise NotBranchError(
523
self.root_transport.base, controldir=self)
524
except NotGitRepository:
492
525
raise NotBranchError(self.root_transport.base,
494
527
ref_chain, unused_sha = self.get_refs_container().follow(ref)
495
528
return RemoteGitBranch(self, repo, ref_chain[-1])
507
540
if self._refs is not None:
508
541
return self._refs
509
542
result = self.fetch_pack(lambda x: None, None,
510
lambda x: None, lambda x: trace.mutter("git: %s" % x))
544
lambda x: trace.mutter("git: %s" % x))
511
545
self._refs = remote_refs_dict_to_container(
512
result.refs, result.symrefs)
546
result.refs, result.symrefs)
513
547
return self._refs
515
549
def push_branch(self, source, revision_id=None, overwrite=False,
542
576
new_sha = source_store._lookup_revision_sha1(revision_id)
544
new_sha = repo.lookup_bzr_revision_id(revision_id)[0]
579
new_sha = repo.lookup_bzr_revision_id(revision_id)[0]
580
except errors.NoSuchRevision:
581
raise errors.NoRoundtrippingSupport(
582
source, self.open_branch(name=name, nascent_ok=True))
545
583
if not overwrite:
546
if remote_divergence(ret.get(refname), new_sha, source_store):
584
if remote_divergence(ret.get(refname), new_sha,
547
586
raise DivergedBranches(
548
source, self.open_branch(name, nascent_ok=True))
587
source, self.open_branch(name, nascent_ok=True))
549
588
ret[refname] = new_sha
565
604
if old_remote != ZERO_SHA:
566
605
push_result.branch_push_result = GitBranchPushResult()
567
606
push_result.branch_push_result.source_branch = source
568
push_result.branch_push_result.target_branch = push_result.target_branch
607
push_result.branch_push_result.target_branch = (
608
push_result.target_branch)
569
609
push_result.branch_push_result.local_branch = None
570
push_result.branch_push_result.master_branch = push_result.target_branch
610
push_result.branch_push_result.master_branch = (
611
push_result.target_branch)
571
612
push_result.branch_push_result.old_revid = push_result.old_revid
572
613
push_result.branch_push_result.new_revid = push_result.new_revid
573
push_result.branch_push_result.new_original_revid = push_result.new_original_revid
614
push_result.branch_push_result.new_original_revid = (
615
push_result.new_original_revid)
574
616
if source.get_push_location() is None or remember:
575
617
source.set_push_location(push_result.target_branch.base)
576
618
return push_result
619
661
def __init__(self, transport, *args, **kwargs):
620
662
self.transport = transport
621
super(BzrGitHttpClient, self).__init__(transport.external_url(), *args, **kwargs)
663
super(BzrGitHttpClient, self).__init__(
664
transport.external_url(), *args, **kwargs)
623
666
def _http_request(self, url, headers=None, data=None,
624
667
allow_compression=False):
732
778
external_url = transport.external_url()
733
779
except InProcessTransport:
734
780
raise NotBranchError(path=transport.base)
735
return (external_url.startswith("http:") or
736
external_url.startswith("https:") or
737
external_url.startswith("git+") or
738
external_url.startswith("git:"))
781
return (external_url.startswith("http:")
782
or external_url.startswith("https:")
783
or external_url.startswith("git+")
784
or external_url.startswith("git:"))
741
787
class GitRemoteRevisionTree(RevisionTree):
764
810
# Let's hope for the best.
765
811
committish = commit
766
812
self._repository.archive(
767
format, committish, f.write,
768
subdirs=([subdir] if subdir else None),
769
prefix=(root+'/') if root else '')
813
format, committish, f.write,
814
subdirs=([subdir] if subdir else None),
815
prefix=(root + '/') if root else '')
771
817
return osutils.file_iterator(f)
819
def is_versioned(self, path, file_id=None):
820
raise GitSmartRemoteNotSupported(self.is_versioned, self)
822
def has_filename(self, path):
823
raise GitSmartRemoteNotSupported(self.has_filename, self)
825
def get_file_text(self, path, file_id=None):
826
raise GitSmartRemoteNotSupported(self.get_file_text, self)
774
829
class RemoteGitRepository(GitRepository):
786
841
def fetch_pack(self, determine_wants, graph_walker, pack_data,
788
return self.controldir.fetch_pack(determine_wants, graph_walker,
843
return self.controldir.fetch_pack(
844
determine_wants, graph_walker, pack_data, progress)
791
846
def send_pack(self, get_changed_refs, generate_pack_data):
792
847
return self.controldir.send_pack(get_changed_refs, generate_pack_data)
796
851
fd, path = tempfile.mkstemp(suffix=".pack")
798
853
self.fetch_pack(determine_wants, graph_walker,
799
lambda x: os.write(fd, x), progress)
854
lambda x: os.write(fd, x), progress)
802
857
if os.path.getsize(path) == 0:
804
859
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
806
861
def lookup_bzr_revision_id(self, bzr_revid, mapping=None):
807
# This won't work for any round-tripped bzr revisions, but it's a start..
862
# This won't work for any round-tripped bzr revisions, but it's a
809
865
return mapping_registry.revision_id_bzr_to_foreign(bzr_revid)
810
866
except InvalidRevisionId:
841
897
def _set_ref(self, name, sha):
842
898
ref = tag_name_to_ref(name)
843
900
def get_changed_refs(old_refs):
844
901
ret = dict(old_refs)
845
902
if sha == dulwich.client.ZERO_SHA and ref not in ret:
846
903
raise NoSuchTag(name)
849
907
def generate_pack_data(have, want, ofs_delta=False):
850
908
return pack_objects_to_data([])
851
909
self.repository.send_pack(get_changed_refs, generate_pack_data)
920
980
raise TypeError(tag_name)
921
981
yield (ref_name, tag_name, peeled, unpeeled)
983
def set_last_revision_info(self, revno, revid):
984
self.generate_revision_history(revid)
986
def generate_revision_history(self, revision_id, last_rev=None,
988
sha = self.lookup_bzr_revision_id(revision_id)[0]
989
def get_changed_refs(old_refs):
990
return {self.ref: sha}
991
def generate_pack_data(have, want, ofs_delta=False):
992
return pack_objects_to_data([])
993
self.repository.send_pack(get_changed_refs, generate_pack_data)
924
997
def remote_refs_dict_to_container(refs_dict, symrefs_dict={}):