49
51
from ..revision import NULL_REVISION
50
52
from ..revisiontree import RevisionTree
53
from ..sixish import (
51
57
from ..transport import (
53
59
register_urlparse_netloc_protocol,
120
import urllib.parse as urlparse
121
from urllib.parse import splituser
127
import urllib.parse as urlparse
128
from urllib.parse import splituser
131
from urllib import splituser
123
133
# urlparse only supports a limited number of schemes by default
124
134
register_urlparse_netloc_protocol('git')
204
214
if re.match('(.+) is not a valid repository name',
205
215
message.splitlines()[0]):
206
216
return NotBranchError(url, message)
208
'GitLab: You are not allowed to push code to protected branches '
210
return PermissionDenied(url, message)
211
217
m = re.match(r'Permission to ([^ ]+) denied to ([^ ]+)\.', message)
213
219
return PermissionDenied(m.group(1), 'denied to %s' % m.group(2))
215
221
return RemoteGitError(message)
218
def parse_git_hangup(url, e):
219
"""Parse the error lines from a git servers stderr on hangup.
221
:param url: URL of the remote repository
222
:param e: A HangupException
224
stderr_lines = getattr(e, 'stderr_lines', None)
227
if all(line.startswith(b'remote: ') for line in stderr_lines):
229
line[len(b'remote: '):] for line in stderr_lines]
230
interesting_lines = [
231
line for line in stderr_lines
232
if line and line.replace(b'=', b'')]
233
if len(interesting_lines) == 1:
234
interesting_line = interesting_lines[0]
235
return parse_git_error(
236
url, interesting_line.decode('utf-8', 'surrogateescape'))
237
return RemoteGitError(
238
b'\n'.join(stderr_lines).decode('utf-8', 'surrogateescape'))
241
224
class GitSmartTransport(Transport):
243
226
def __init__(self, url, _client=None):
435
418
format=(format.encode('ascii') if format else None),
437
prefix=(encode_git_path(prefix) if prefix else None))
438
except HangupException as e:
439
raise parse_git_hangup(self.transport.external_url(), e)
420
prefix=(prefix.encode('utf-8') if prefix else None))
440
421
except GitProtocolError as e:
441
422
raise parse_git_error(self.transport.external_url(), e)
459
440
self._refs = remote_refs_dict_to_container(
460
441
result.refs, result.symrefs)
462
except HangupException as e:
463
raise parse_git_hangup(self.transport.external_url(), e)
464
443
except GitProtocolError as e:
465
444
raise parse_git_error(self.transport.external_url(), e)
482
461
return self._client.send_pack(
483
462
self._client_path, get_changed_refs_wrapper,
484
463
generate_pack_data, progress)
485
except HangupException as e:
486
raise parse_git_hangup(self.transport.external_url(), e)
487
464
except GitProtocolError as e:
488
465
raise parse_git_error(self.transport.external_url(), e)
515
492
def generate_pack_data(have, want, ofs_delta=False):
516
493
return pack_objects_to_data([])
517
result = self.send_pack(get_changed_refs, generate_pack_data)
518
if result is not None and not isinstance(result, dict):
519
error = result.ref_status.get(refname)
521
raise RemoteGitError(error)
494
self.send_pack(get_changed_refs, generate_pack_data)
524
497
def user_url(self):
588
561
# No revision supplied by the user, default to the branch
590
563
revision_id = source.last_revision()
592
if not source.repository.has_revision(revision_id):
593
raise NoSuchRevision(source, revision_id)
595
565
push_result = GitPushResult()
596
566
push_result.workingtree_updated = None
629
599
source, self.open_branch(name, nascent_ok=True))
630
600
ret[actual_refname] = new_sha
632
for tagname, revid in source.tags.get_tag_dict().items():
602
for tagname, revid in viewitems(source.tags.get_tag_dict()):
633
603
if tag_selector and not tag_selector(tagname):
643
613
new_sha = repo.lookup_bzr_revision_id(revid)[0]
644
614
except errors.NoSuchRevision:
647
if not source.repository.has_revision(revid):
649
616
ret[tag_name_to_ref(tagname)] = new_sha
651
618
with source_store.lock_read():
652
def generate_pack_data(have, want, progress=None,
654
git_repo = getattr(source.repository, '_git', None)
656
shallow = git_repo.get_shallow()
660
return source_store.generate_lossy_pack_data(
661
have, want, shallow=shallow,
662
progress=progress, ofs_delta=ofs_delta)
664
return source_store.generate_pack_data(
665
have, want, shallow=shallow,
666
progress=progress, ofs_delta=ofs_delta)
668
return source_store.generate_pack_data(
669
have, want, progress=progress, ofs_delta=ofs_delta)
670
dw_result = self.send_pack(get_changed_refs, generate_pack_data)
671
if not isinstance(dw_result, dict):
672
new_refs = dw_result.refs
673
error = dw_result.ref_status.get(actual_refname)
675
raise RemoteGitError(error)
676
for ref, error in dw_result.ref_status.items():
678
trace.warning('unable to open ref %s: %s',
680
else: # dulwich < 0.20.4
620
generate_pack_data = source_store.generate_lossy_pack_data
622
generate_pack_data = source_store.generate_pack_data
623
new_refs = self.send_pack(get_changed_refs, generate_pack_data)
682
624
push_result.new_revid = repo.lookup_foreign_revision_id(
683
625
new_refs[actual_refname])
684
626
if old_sha is not None:
780
722
raise NotGitRepository()
781
723
elif response.status != 200:
782
724
raise GitProtocolError("unexpected http resp %d for %s" %
783
(response.status, url))
725
(response.code, url))
785
727
# TODO: Optimization available by adding `preload_content=False` to the
786
728
# request and just passing the `read` method on instead of going via
941
882
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref,
944
884
fd, path = tempfile.mkstemp(suffix=".pack")
946
886
self.fetch_pack(determine_wants, graph_walker,
1000
940
def generate_pack_data(have, want, ofs_delta=False):
1001
941
return pack_objects_to_data([])
1002
result = self.repository.send_pack(
1003
get_changed_refs, generate_pack_data)
1004
if result and not isinstance(result, dict):
1005
error = result.ref_status.get(ref)
1007
raise RemoteGitError(error)
942
self.repository.send_pack(get_changed_refs, generate_pack_data)
1010
945
class RemoteGitBranch(GitBranch):
1074
1009
if peeled is None:
1075
1010
# Let's just hope it's a commit
1076
1011
peeled = unpeeled
1077
if not isinstance(tag_name, str):
1012
if not isinstance(tag_name, text_type):
1078
1013
raise TypeError(tag_name)
1079
1014
yield (ref_name, tag_name, peeled, unpeeled)
1088
1023
return {self.ref: sha}
1089
1024
def generate_pack_data(have, want, ofs_delta=False):
1090
1025
return pack_objects_to_data([])
1091
result = self.repository.send_pack(
1092
get_changed_refs, generate_pack_data)
1093
if result is not None and not isinstance(result, dict):
1094
error = result.ref_status.get(self.ref)
1096
raise RemoteGitError(error)
1026
self.repository.send_pack(get_changed_refs, generate_pack_data)
1097
1027
self._sha = sha