diff options
author | Shawn O. Pearce <sop@google.com> | 2012-01-11 14:58:54 -0800 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2012-01-11 16:18:40 -0800 |
commit | c9571423f843340de19ef576ccaa418ac72fdb58 (patch) | |
tree | 938fdcdde76dfc1cc8b299e0f6d96648242902e1 | |
parent | 34fb20f67c7bdca2b1321a40f2fd558f9a34d866 (diff) | |
download | git-repo-c9571423f843340de19ef576ccaa418ac72fdb58.tar.gz |
upload: Support uploading to Gerrit over https://v1.7.8.2
If SSH is not available, Gerrit returns NOT_AVAILABLE to the /ssh_info
query made by repo upload. In this case fallback to the /p/$PROJECT URL
that Gerrit also exports and use that for uploads.
Change-Id: I1e3e39ab709ecc0a692614a41a42446426f39c08
-rw-r--r-- | git_config.py | 75 | ||||
-rw-r--r-- | project.py | 31 |
2 files changed, 42 insertions, 64 deletions
diff --git a/git_config.py b/git_config.py index a52677cf..17937649 100644 --- a/git_config.py +++ b/git_config.py | |||
@@ -527,7 +527,7 @@ class Remote(object): | |||
527 | self.projectname = self._Get('projectname') | 527 | self.projectname = self._Get('projectname') |
528 | self.fetch = map(lambda x: RefSpec.FromString(x), | 528 | self.fetch = map(lambda x: RefSpec.FromString(x), |
529 | self._Get('fetch', all=True)) | 529 | self._Get('fetch', all=True)) |
530 | self._review_protocol = None | 530 | self._review_url = None |
531 | 531 | ||
532 | def _InsteadOf(self): | 532 | def _InsteadOf(self): |
533 | globCfg = GitConfig.ForUser() | 533 | globCfg = GitConfig.ForUser() |
@@ -554,9 +554,8 @@ class Remote(object): | |||
554 | connectionUrl = self._InsteadOf() | 554 | connectionUrl = self._InsteadOf() |
555 | return _preconnect(connectionUrl) | 555 | return _preconnect(connectionUrl) |
556 | 556 | ||
557 | @property | 557 | def ReviewUrl(self, userEmail): |
558 | def ReviewProtocol(self): | 558 | if self._review_url is None: |
559 | if self._review_protocol is None: | ||
560 | if self.review is None: | 559 | if self.review is None: |
561 | return None | 560 | return None |
562 | 561 | ||
@@ -565,67 +564,47 @@ class Remote(object): | |||
565 | u = 'http://%s' % u | 564 | u = 'http://%s' % u |
566 | if u.endswith('/Gerrit'): | 565 | if u.endswith('/Gerrit'): |
567 | u = u[:len(u) - len('/Gerrit')] | 566 | u = u[:len(u) - len('/Gerrit')] |
568 | if not u.endswith('/ssh_info'): | 567 | if u.endswith('/ssh_info'): |
569 | if not u.endswith('/'): | 568 | u = u[:len(u) - len('/ssh_info')] |
570 | u += '/' | 569 | if not u.endswith('/'): |
571 | u += 'ssh_info' | 570 | u += '/' |
571 | http_url = u | ||
572 | 572 | ||
573 | if u in REVIEW_CACHE: | 573 | if u in REVIEW_CACHE: |
574 | info = REVIEW_CACHE[u] | 574 | self._review_url = REVIEW_CACHE[u] |
575 | self._review_protocol = info[0] | ||
576 | self._review_host = info[1] | ||
577 | self._review_port = info[2] | ||
578 | elif 'REPO_HOST_PORT_INFO' in os.environ: | 575 | elif 'REPO_HOST_PORT_INFO' in os.environ: |
579 | info = os.environ['REPO_HOST_PORT_INFO'] | 576 | host, port = os.environ['REPO_HOST_PORT_INFO'].split() |
580 | self._review_protocol = 'ssh' | 577 | self._review_url = self._SshReviewUrl(userEmail, host, port) |
581 | self._review_host = info.split(" ")[0] | 578 | REVIEW_CACHE[u] = self._review_url |
582 | self._review_port = info.split(" ")[1] | ||
583 | |||
584 | REVIEW_CACHE[u] = ( | ||
585 | self._review_protocol, | ||
586 | self._review_host, | ||
587 | self._review_port) | ||
588 | else: | 579 | else: |
589 | try: | 580 | try: |
590 | info = urllib2.urlopen(u).read() | 581 | info_url = u + 'ssh_info' |
591 | if info == 'NOT_AVAILABLE': | 582 | info = urllib2.urlopen(info_url).read() |
592 | raise UploadError('%s: SSH disabled' % self.review) | ||
593 | if '<' in info: | 583 | if '<' in info: |
594 | # Assume the server gave us some sort of HTML | 584 | # Assume the server gave us some sort of HTML |
595 | # response back, like maybe a login page. | 585 | # response back, like maybe a login page. |
596 | # | 586 | # |
597 | raise UploadError('%s: Cannot parse response' % u) | 587 | raise UploadError('%s: Cannot parse response' % info_url) |
598 | 588 | ||
599 | self._review_protocol = 'ssh' | 589 | if info == 'NOT_AVAILABLE': |
600 | self._review_host = info.split(" ")[0] | 590 | # Assume HTTP if SSH is not enabled. |
601 | self._review_port = info.split(" ")[1] | 591 | self._review_url = http_url + 'p/' |
602 | except urllib2.HTTPError, e: | ||
603 | if e.code == 404: | ||
604 | self._review_protocol = 'http-post' | ||
605 | self._review_host = None | ||
606 | self._review_port = None | ||
607 | else: | 592 | else: |
608 | raise UploadError('Upload over SSH unavailable') | 593 | host, port = info.split() |
594 | self._review_url = self._SshReviewUrl(userEmail, host, port) | ||
595 | except urllib2.HTTPError, e: | ||
596 | raise UploadError('%s: %s' % (self.review, str(e))) | ||
609 | except urllib2.URLError, e: | 597 | except urllib2.URLError, e: |
610 | raise UploadError('%s: %s' % (self.review, str(e))) | 598 | raise UploadError('%s: %s' % (self.review, str(e))) |
611 | 599 | ||
612 | REVIEW_CACHE[u] = ( | 600 | REVIEW_CACHE[u] = self._review_url |
613 | self._review_protocol, | 601 | return self._review_url + self.projectname |
614 | self._review_host, | ||
615 | self._review_port) | ||
616 | return self._review_protocol | ||
617 | 602 | ||
618 | def SshReviewUrl(self, userEmail): | 603 | def _SshReviewUrl(self, userEmail, host, port): |
619 | if self.ReviewProtocol != 'ssh': | ||
620 | return None | ||
621 | username = self._config.GetString('review.%s.username' % self.review) | 604 | username = self._config.GetString('review.%s.username' % self.review) |
622 | if username is None: | 605 | if username is None: |
623 | username = userEmail.split("@")[0] | 606 | username = userEmail.split('@')[0] |
624 | return 'ssh://%s@%s:%s/%s' % ( | 607 | return 'ssh://%s@%s:%s/' % (username, host, port) |
625 | username, | ||
626 | self._review_host, | ||
627 | self._review_port, | ||
628 | self.projectname) | ||
629 | 608 | ||
630 | def ToLocal(self, rev): | 609 | def ToLocal(self, rev): |
631 | """Convert a remote revision string to something we have locally. | 610 | """Convert a remote revision string to something we have locally. |
@@ -866,31 +866,30 @@ class Project(object): | |||
866 | branch.remote.projectname = self.name | 866 | branch.remote.projectname = self.name |
867 | branch.remote.Save() | 867 | branch.remote.Save() |
868 | 868 | ||
869 | if branch.remote.ReviewProtocol == 'ssh': | 869 | url = branch.remote.ReviewUrl(self.UserEmail) |
870 | if dest_branch.startswith(R_HEADS): | 870 | if url is None: |
871 | dest_branch = dest_branch[len(R_HEADS):] | 871 | raise UploadError('review not configured') |
872 | cmd = ['push'] | ||
872 | 873 | ||
874 | if url.startswith('ssh://'): | ||
873 | rp = ['gerrit receive-pack'] | 875 | rp = ['gerrit receive-pack'] |
874 | for e in people[0]: | 876 | for e in people[0]: |
875 | rp.append('--reviewer=%s' % sq(e)) | 877 | rp.append('--reviewer=%s' % sq(e)) |
876 | for e in people[1]: | 878 | for e in people[1]: |
877 | rp.append('--cc=%s' % sq(e)) | 879 | rp.append('--cc=%s' % sq(e)) |
878 | |||
879 | ref_spec = '%s:refs/for/%s' % (R_HEADS + branch.name, dest_branch) | ||
880 | if auto_topic: | ||
881 | ref_spec = ref_spec + '/' + branch.name | ||
882 | |||
883 | cmd = ['push'] | ||
884 | cmd.append('--receive-pack=%s' % " ".join(rp)) | 880 | cmd.append('--receive-pack=%s' % " ".join(rp)) |
885 | cmd.append(branch.remote.SshReviewUrl(self.UserEmail)) | ||
886 | cmd.append(ref_spec) | ||
887 | 881 | ||
888 | if GitCommand(self, cmd, bare = True).Wait() != 0: | 882 | cmd.append(url) |
889 | raise UploadError('Upload failed') | ||
890 | 883 | ||
891 | else: | 884 | if dest_branch.startswith(R_HEADS): |
892 | raise UploadError('Unsupported protocol %s' \ | 885 | dest_branch = dest_branch[len(R_HEADS):] |
893 | % branch.remote.review) | 886 | ref_spec = '%s:refs/for/%s' % (R_HEADS + branch.name, dest_branch) |
887 | if auto_topic: | ||
888 | ref_spec = ref_spec + '/' + branch.name | ||
889 | cmd.append(ref_spec) | ||
890 | |||
891 | if GitCommand(self, cmd, bare = True).Wait() != 0: | ||
892 | raise UploadError('Upload failed') | ||
894 | 893 | ||
895 | msg = "posted to %s for %s" % (branch.remote.review, dest_branch) | 894 | msg = "posted to %s for %s" % (branch.remote.review, dest_branch) |
896 | self.bare_git.UpdateRef(R_PUB + branch.name, | 895 | self.bare_git.UpdateRef(R_PUB + branch.name, |