| 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 |