OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
7 | 7 |
8 """A git-command for integrating reviews on Rietveld and Gerrit.""" | 8 """A git-command for integrating reviews on Rietveld and Gerrit.""" |
9 | 9 |
10 from distutils.version import LooseVersion | 10 from distutils.version import LooseVersion |
(...skipping 1311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1322 if self.GetBranch() is None: | 1322 if self.GetBranch() is None: |
1323 DieWithError('Can\'t upload from detached HEAD state. Get on a branch!') | 1323 DieWithError('Can\'t upload from detached HEAD state. Get on a branch!') |
1324 | 1324 |
1325 # Default to diffing against common ancestor of upstream branch | 1325 # Default to diffing against common ancestor of upstream branch |
1326 base_branch = self.GetCommonAncestorWithUpstream() | 1326 base_branch = self.GetCommonAncestorWithUpstream() |
1327 git_diff_args = [base_branch, 'HEAD'] | 1327 git_diff_args = [base_branch, 'HEAD'] |
1328 | 1328 |
1329 # Make sure authenticated to codereview before running potentially expensive | 1329 # Make sure authenticated to codereview before running potentially expensive |
1330 # hooks. It is a fast, best efforts check. Codereview still can reject the | 1330 # hooks. It is a fast, best efforts check. Codereview still can reject the |
1331 # authentication during the actual upload. | 1331 # authentication during the actual upload. |
1332 self._codereview_impl.EnsureAuthenticated() | 1332 self._codereview_impl.EnsureAuthenticated(force=options.force) |
1333 | 1333 |
1334 # Apply watchlists on upload. | 1334 # Apply watchlists on upload. |
1335 change = self.GetChange(base_branch, None) | 1335 change = self.GetChange(base_branch, None) |
1336 watchlist = watchlists.Watchlists(change.RepositoryRoot()) | 1336 watchlist = watchlists.Watchlists(change.RepositoryRoot()) |
1337 files = [f.LocalPath() for f in change.AffectedFiles()] | 1337 files = [f.LocalPath() for f in change.AffectedFiles()] |
1338 if not options.bypass_watchlists: | 1338 if not options.bypass_watchlists: |
1339 self.SetWatchers(watchlist.GetWatchersForPaths(files)) | 1339 self.SetWatchers(watchlist.GetWatchersForPaths(files)) |
1340 | 1340 |
1341 if not options.bypass_hooks: | 1341 if not options.bypass_hooks: |
1342 if options.reviewers or options.tbr_owners: | 1342 if options.reviewers or options.tbr_owners: |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1500 directory: switch to directory before applying the patch. Rietveld only. | 1500 directory: switch to directory before applying the patch. Rietveld only. |
1501 """ | 1501 """ |
1502 raise NotImplementedError() | 1502 raise NotImplementedError() |
1503 | 1503 |
1504 @staticmethod | 1504 @staticmethod |
1505 def ParseIssueURL(parsed_url): | 1505 def ParseIssueURL(parsed_url): |
1506 """Parses url and returns instance of _ParsedIssueNumberArgument or None if | 1506 """Parses url and returns instance of _ParsedIssueNumberArgument or None if |
1507 failed.""" | 1507 failed.""" |
1508 raise NotImplementedError() | 1508 raise NotImplementedError() |
1509 | 1509 |
1510 def EnsureAuthenticated(self): | 1510 def EnsureAuthenticated(self, force): |
1511 """Best effort check that user is authenticated with codereview server.""" | 1511 """Best effort check that user is authenticated with codereview server. |
| 1512 |
| 1513 Arguments: |
| 1514 force: whether to skip confirmation questions. |
| 1515 """ |
1512 raise NotImplementedError() | 1516 raise NotImplementedError() |
1513 | 1517 |
1514 def CMDUploadChange(self, options, args, change): | 1518 def CMDUploadChange(self, options, args, change): |
1515 """Uploads a change to codereview.""" | 1519 """Uploads a change to codereview.""" |
1516 raise NotImplementedError() | 1520 raise NotImplementedError() |
1517 | 1521 |
1518 | 1522 |
1519 class _RietveldChangelistImpl(_ChangelistCodereviewBase): | 1523 class _RietveldChangelistImpl(_ChangelistCodereviewBase): |
1520 def __init__(self, changelist, auth_config=None, rietveld_server=None): | 1524 def __init__(self, changelist, auth_config=None, rietveld_server=None): |
1521 super(_RietveldChangelistImpl, self).__init__(changelist) | 1525 super(_RietveldChangelistImpl, self).__init__(changelist) |
(...skipping 11 matching lines...) Expand all Loading... |
1533 # with that branch. | 1537 # with that branch. |
1534 if self.GetIssue(): | 1538 if self.GetIssue(): |
1535 rietveld_server_setting = self.GetCodereviewServerSetting() | 1539 rietveld_server_setting = self.GetCodereviewServerSetting() |
1536 if rietveld_server_setting: | 1540 if rietveld_server_setting: |
1537 self._rietveld_server = gclient_utils.UpgradeToHttps(RunGit( | 1541 self._rietveld_server = gclient_utils.UpgradeToHttps(RunGit( |
1538 ['config', rietveld_server_setting], error_ok=True).strip()) | 1542 ['config', rietveld_server_setting], error_ok=True).strip()) |
1539 if not self._rietveld_server: | 1543 if not self._rietveld_server: |
1540 self._rietveld_server = settings.GetDefaultServerUrl() | 1544 self._rietveld_server = settings.GetDefaultServerUrl() |
1541 return self._rietveld_server | 1545 return self._rietveld_server |
1542 | 1546 |
1543 def EnsureAuthenticated(self): | 1547 def EnsureAuthenticated(self, force): |
1544 """Best effort check that user is authenticated with Rietveld server.""" | 1548 """Best effort check that user is authenticated with Rietveld server.""" |
1545 if self._auth_config.use_oauth2: | 1549 if self._auth_config.use_oauth2: |
1546 authenticator = auth.get_authenticator_for_host( | 1550 authenticator = auth.get_authenticator_for_host( |
1547 self.GetCodereviewServer(), self._auth_config) | 1551 self.GetCodereviewServer(), self._auth_config) |
1548 if not authenticator.has_cached_credentials(): | 1552 if not authenticator.has_cached_credentials(): |
1549 raise auth.LoginRequiredError(self.GetCodereviewServer()) | 1553 raise auth.LoginRequiredError(self.GetCodereviewServer()) |
1550 | 1554 |
1551 def FetchDescription(self): | 1555 def FetchDescription(self): |
1552 issue = self.GetIssue() | 1556 issue = self.GetIssue() |
1553 assert issue | 1557 assert issue |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 issue=int(match.group(1)), | 1782 issue=int(match.group(1)), |
1779 patchset=int(match.group(2)), | 1783 patchset=int(match.group(2)), |
1780 hostname=parsed_url.netloc, | 1784 hostname=parsed_url.netloc, |
1781 patch_url=gclient_utils.UpgradeToHttps(parsed_url.geturl())) | 1785 patch_url=gclient_utils.UpgradeToHttps(parsed_url.geturl())) |
1782 return None | 1786 return None |
1783 | 1787 |
1784 def CMDUploadChange(self, options, args, change): | 1788 def CMDUploadChange(self, options, args, change): |
1785 """Upload the patch to Rietveld.""" | 1789 """Upload the patch to Rietveld.""" |
1786 upload_args = ['--assume_yes'] # Don't ask about untracked files. | 1790 upload_args = ['--assume_yes'] # Don't ask about untracked files. |
1787 upload_args.extend(['--server', self.GetCodereviewServer()]) | 1791 upload_args.extend(['--server', self.GetCodereviewServer()]) |
1788 # TODO(tandrii): refactor this ugliness into _RietveldChangelistImpl. | |
1789 upload_args.extend(auth.auth_config_to_command_options(self._auth_config)) | 1792 upload_args.extend(auth.auth_config_to_command_options(self._auth_config)) |
1790 if options.emulate_svn_auto_props: | 1793 if options.emulate_svn_auto_props: |
1791 upload_args.append('--emulate_svn_auto_props') | 1794 upload_args.append('--emulate_svn_auto_props') |
1792 | 1795 |
1793 change_desc = None | 1796 change_desc = None |
1794 | 1797 |
1795 if options.email is not None: | 1798 if options.email is not None: |
1796 upload_args.extend(['--email', options.email]) | 1799 upload_args.extend(['--email', options.email]) |
1797 | 1800 |
1798 if self.GetIssue(): | 1801 if self.GetIssue(): |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1932 if options.use_commit_queue: | 1935 if options.use_commit_queue: |
1933 self.SetFlag('commit', '1') | 1936 self.SetFlag('commit', '1') |
1934 return 0 | 1937 return 0 |
1935 | 1938 |
1936 | 1939 |
1937 class _GerritChangelistImpl(_ChangelistCodereviewBase): | 1940 class _GerritChangelistImpl(_ChangelistCodereviewBase): |
1938 def __init__(self, changelist, auth_config=None): | 1941 def __init__(self, changelist, auth_config=None): |
1939 # auth_config is Rietveld thing, kept here to preserve interface only. | 1942 # auth_config is Rietveld thing, kept here to preserve interface only. |
1940 super(_GerritChangelistImpl, self).__init__(changelist) | 1943 super(_GerritChangelistImpl, self).__init__(changelist) |
1941 self._change_id = None | 1944 self._change_id = None |
| 1945 # Lazily cached values. |
1942 self._gerrit_server = None # e.g. https://chromium-review.googlesource.com | 1946 self._gerrit_server = None # e.g. https://chromium-review.googlesource.com |
1943 self._gerrit_host = None # e.g. chromium-review.googlesource.com | 1947 self._gerrit_host = None # e.g. chromium-review.googlesource.com |
1944 | 1948 |
1945 def _GetGerritHost(self): | 1949 def _GetGerritHost(self): |
1946 # Lazy load of configs. | 1950 # Lazy load of configs. |
1947 self.GetCodereviewServer() | 1951 self.GetCodereviewServer() |
1948 return self._gerrit_host | 1952 return self._gerrit_host |
1949 | 1953 |
| 1954 def _GetGitHost(self): |
| 1955 """Returns git host to be used when uploading change to Gerrit.""" |
| 1956 return urlparse.urlparse(self.GetRemoteUrl()).netloc |
| 1957 |
1950 def GetCodereviewServer(self): | 1958 def GetCodereviewServer(self): |
1951 if not self._gerrit_server: | 1959 if not self._gerrit_server: |
1952 # If we're on a branch then get the server potentially associated | 1960 # If we're on a branch then get the server potentially associated |
1953 # with that branch. | 1961 # with that branch. |
1954 if self.GetIssue(): | 1962 if self.GetIssue(): |
1955 gerrit_server_setting = self.GetCodereviewServerSetting() | 1963 gerrit_server_setting = self.GetCodereviewServerSetting() |
1956 if gerrit_server_setting: | 1964 if gerrit_server_setting: |
1957 self._gerrit_server = RunGit(['config', gerrit_server_setting], | 1965 self._gerrit_server = RunGit(['config', gerrit_server_setting], |
1958 error_ok=True).strip() | 1966 error_ok=True).strip() |
1959 if self._gerrit_server: | 1967 if self._gerrit_server: |
1960 self._gerrit_host = urlparse.urlparse(self._gerrit_server).netloc | 1968 self._gerrit_host = urlparse.urlparse(self._gerrit_server).netloc |
1961 if not self._gerrit_server: | 1969 if not self._gerrit_server: |
1962 # We assume repo to be hosted on Gerrit, and hence Gerrit server | 1970 # We assume repo to be hosted on Gerrit, and hence Gerrit server |
1963 # has "-review" suffix for lowest level subdomain. | 1971 # has "-review" suffix for lowest level subdomain. |
1964 parts = urlparse.urlparse(self.GetRemoteUrl()).netloc.split('.') | 1972 parts = self._GetGitHost().split('.') |
1965 parts[0] = parts[0] + '-review' | 1973 parts[0] = parts[0] + '-review' |
1966 self._gerrit_host = '.'.join(parts) | 1974 self._gerrit_host = '.'.join(parts) |
1967 self._gerrit_server = 'https://%s' % self._gerrit_host | 1975 self._gerrit_server = 'https://%s' % self._gerrit_host |
1968 return self._gerrit_server | 1976 return self._gerrit_server |
1969 | 1977 |
1970 @classmethod | 1978 @classmethod |
1971 def IssueSettingSuffix(cls): | 1979 def IssueSettingSuffix(cls): |
1972 return 'gerritissue' | 1980 return 'gerritissue' |
1973 | 1981 |
1974 def EnsureAuthenticated(self): | 1982 def EnsureAuthenticated(self, force): |
1975 """Best effort check that user is authenticated with Gerrit server.""" | 1983 """Best effort check that user is authenticated with Gerrit server.""" |
1976 #TODO(tandrii): implement per bug http://crbug.com/583153. | 1984 # Lazy-loader to identify Gerrit and Git hosts. |
| 1985 if gerrit_util.GceAuthenticator.is_gce(): |
| 1986 return |
| 1987 self.GetCodereviewServer() |
| 1988 git_host = self._GetGitHost() |
| 1989 assert self._gerrit_server and self._gerrit_host |
| 1990 cookie_auth = gerrit_util.CookiesAuthenticator() |
| 1991 |
| 1992 gerrit_auth = cookie_auth.get_auth_header(self._gerrit_host) |
| 1993 git_auth = cookie_auth.get_auth_header(git_host) |
| 1994 if gerrit_auth and git_auth: |
| 1995 if gerrit_auth == git_auth: |
| 1996 return |
| 1997 print(( |
| 1998 'WARNING: you have different credentials for Gerrit and git hosts.\n' |
| 1999 ' Check your %s or %s file for credentials of hosts:\n' |
| 2000 ' %s\n' |
| 2001 ' %s\n' |
| 2002 ' %s') % |
| 2003 (cookie_auth.get_gitcookies_path(), cookie_auth.get_netrc_path(), |
| 2004 git_host, self._gerrit_host, |
| 2005 cookie_auth.get_new_password_message(git_host))) |
| 2006 if not force: |
| 2007 ask_for_data('If you know what you are doing, press Enter to continue, ' |
| 2008 'Ctrl+C to abort.') |
| 2009 return |
| 2010 else: |
| 2011 missing = ( |
| 2012 [] if gerrit_auth else [self._gerrit_host] + |
| 2013 [] if git_auth else [git_host]) |
| 2014 DieWithError('Credentials for the following hosts are required:\n' |
| 2015 ' %s\n' |
| 2016 'These are read from %s (or legacy %s)\n' |
| 2017 '%s' % ( |
| 2018 '\n '.join(missing), |
| 2019 cookie_auth.get_gitcookies_path(), |
| 2020 cookie_auth.get_netrc_path(), |
| 2021 cookie_auth.get_new_password_message(git_host))) |
| 2022 |
1977 | 2023 |
1978 def PatchsetSetting(self): | 2024 def PatchsetSetting(self): |
1979 """Return the git setting that stores this change's most recent patchset.""" | 2025 """Return the git setting that stores this change's most recent patchset.""" |
1980 return 'branch.%s.gerritpatchset' % self.GetBranch() | 2026 return 'branch.%s.gerritpatchset' % self.GetBranch() |
1981 | 2027 |
1982 def GetCodereviewServerSetting(self): | 2028 def GetCodereviewServerSetting(self): |
1983 """Returns the git setting that stores this change's Gerrit server.""" | 2029 """Returns the git setting that stores this change's Gerrit server.""" |
1984 branch = self.GetBranch() | 2030 branch = self.GetBranch() |
1985 if branch: | 2031 if branch: |
1986 return 'branch.%s.gerritserver' % branch | 2032 return 'branch.%s.gerritserver' % branch |
(...skipping 2664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4651 if __name__ == '__main__': | 4697 if __name__ == '__main__': |
4652 # These affect sys.stdout so do it outside of main() to simplify mocks in | 4698 # These affect sys.stdout so do it outside of main() to simplify mocks in |
4653 # unit testing. | 4699 # unit testing. |
4654 fix_encoding.fix_encoding() | 4700 fix_encoding.fix_encoding() |
4655 setup_color.init() | 4701 setup_color.init() |
4656 try: | 4702 try: |
4657 sys.exit(main(sys.argv[1:])) | 4703 sys.exit(main(sys.argv[1:])) |
4658 except KeyboardInterrupt: | 4704 except KeyboardInterrupt: |
4659 sys.stderr.write('interrupted\n') | 4705 sys.stderr.write('interrupted\n') |
4660 sys.exit(1) | 4706 sys.exit(1) |
OLD | NEW |