| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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.""" | 8 """A git-command for integrating reviews on Rietveld.""" |
| 9 | 9 |
| 10 import errno | 10 import errno |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 except ImportError: | 32 except ImportError: |
| 33 # Fall back to the packaged version. | 33 # Fall back to the packaged version. |
| 34 sys.path.append(os.path.join(os.path.dirname(__file__), 'third_party')) | 34 sys.path.append(os.path.join(os.path.dirname(__file__), 'third_party')) |
| 35 import simplejson as json # pylint: disable=F0401 | 35 import simplejson as json # pylint: disable=F0401 |
| 36 | 36 |
| 37 | 37 |
| 38 from third_party import upload | 38 from third_party import upload |
| 39 import breakpad # pylint: disable=W0611 | 39 import breakpad # pylint: disable=W0611 |
| 40 import fix_encoding | 40 import fix_encoding |
| 41 import presubmit_support | 41 import presubmit_support |
| 42 import rietveld |
| 42 import scm | 43 import scm |
| 43 import watchlists | 44 import watchlists |
| 44 | 45 |
| 45 | 46 |
| 46 | 47 |
| 47 DEFAULT_SERVER = 'http://codereview.appspot.com' | 48 DEFAULT_SERVER = 'http://codereview.appspot.com' |
| 48 POSTUPSTREAM_HOOK_PATTERN = '.git/hooks/post-cl-%s' | 49 POSTUPSTREAM_HOOK_PATTERN = '.git/hooks/post-cl-%s' |
| 49 DESCRIPTION_BACKUP_FILE = '~/.git_cl_description_backup' | 50 DESCRIPTION_BACKUP_FILE = '~/.git_cl_description_backup' |
| 50 | 51 |
| 51 | 52 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 return self.rietveld_server | 457 return self.rietveld_server |
| 457 | 458 |
| 458 def GetIssueURL(self): | 459 def GetIssueURL(self): |
| 459 """Get the URL for a particular issue.""" | 460 """Get the URL for a particular issue.""" |
| 460 return '%s/%s' % (self.GetRietveldServer(), self.GetIssue()) | 461 return '%s/%s' % (self.GetRietveldServer(), self.GetIssue()) |
| 461 | 462 |
| 462 def GetDescription(self, pretty=False): | 463 def GetDescription(self, pretty=False): |
| 463 if not self.has_description: | 464 if not self.has_description: |
| 464 if self.GetIssue(): | 465 if self.GetIssue(): |
| 465 path = '/' + self.GetIssue() + '/description' | 466 path = '/' + self.GetIssue() + '/description' |
| 466 rpc_server = self._RpcServer() | 467 rpc_server = self.RpcServer() |
| 467 self.description = rpc_server.Send(path).strip() | 468 self.description = rpc_server.Send(path).strip() |
| 468 self.has_description = True | 469 self.has_description = True |
| 469 if pretty: | 470 if pretty: |
| 470 wrapper = textwrap.TextWrapper() | 471 wrapper = textwrap.TextWrapper() |
| 471 wrapper.initial_indent = wrapper.subsequent_indent = ' ' | 472 wrapper.initial_indent = wrapper.subsequent_indent = ' ' |
| 472 return wrapper.fill(self.description) | 473 return wrapper.fill(self.description) |
| 473 return self.description | 474 return self.description |
| 474 | 475 |
| 475 def GetPatchset(self): | 476 def GetPatchset(self): |
| 476 if not self.has_patchset: | 477 if not self.has_patchset: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 487 """Set this branch's patchset. If patchset=0, clears the patchset.""" | 488 """Set this branch's patchset. If patchset=0, clears the patchset.""" |
| 488 if patchset: | 489 if patchset: |
| 489 RunGit(['config', self._PatchsetSetting(), str(patchset)]) | 490 RunGit(['config', self._PatchsetSetting(), str(patchset)]) |
| 490 else: | 491 else: |
| 491 RunGit(['config', '--unset', self._PatchsetSetting()], | 492 RunGit(['config', '--unset', self._PatchsetSetting()], |
| 492 swallow_stderr=True, error_ok=True) | 493 swallow_stderr=True, error_ok=True) |
| 493 self.has_patchset = False | 494 self.has_patchset = False |
| 494 | 495 |
| 495 def GetPatchSetDiff(self, issue): | 496 def GetPatchSetDiff(self, issue): |
| 496 # Grab the last patchset of the issue first. | 497 # Grab the last patchset of the issue first. |
| 497 data = json.loads(self._RpcServer().Send('/api/%s' % issue)) | 498 data = json.loads(self.RpcServer().Send('/api/%s' % issue)) |
| 498 patchset = data['patchsets'][-1] | 499 patchset = data['patchsets'][-1] |
| 499 return self._RpcServer().Send( | 500 return self.RpcServer().Send( |
| 500 '/download/issue%s_%s.diff' % (issue, patchset)) | 501 '/download/issue%s_%s.diff' % (issue, patchset)) |
| 501 | 502 |
| 502 def SetIssue(self, issue): | 503 def SetIssue(self, issue): |
| 503 """Set this branch's issue. If issue=0, clears the issue.""" | 504 """Set this branch's issue. If issue=0, clears the issue.""" |
| 504 if issue: | 505 if issue: |
| 505 RunGit(['config', self._IssueSetting(), str(issue)]) | 506 RunGit(['config', self._IssueSetting(), str(issue)]) |
| 506 if self.rietveld_server: | 507 if self.rietveld_server: |
| 507 RunGit(['config', self._RietveldServer(), self.rietveld_server]) | 508 RunGit(['config', self._RietveldServer(), self.rietveld_server]) |
| 508 else: | 509 else: |
| 509 RunGit(['config', '--unset', self._IssueSetting()]) | 510 RunGit(['config', '--unset', self._IssueSetting()]) |
| 510 self.SetPatchset(0) | 511 self.SetPatchset(0) |
| 511 self.has_issue = False | 512 self.has_issue = False |
| 512 | 513 |
| 513 def CloseIssue(self): | 514 def CloseIssue(self): |
| 514 rpc_server = self._RpcServer() | 515 rpc_server = self.RpcServer() |
| 515 # Newer versions of Rietveld require us to pass an XSRF token to POST, so | 516 # Newer versions of Rietveld require us to pass an XSRF token to POST, so |
| 516 # we fetch it from the server. (The version used by Chromium has been | 517 # we fetch it from the server. (The version used by Chromium has been |
| 517 # modified so the token isn't required when closing an issue.) | 518 # modified so the token isn't required when closing an issue.) |
| 518 xsrf_token = rpc_server.Send('/xsrf_token', | 519 xsrf_token = rpc_server.Send('/xsrf_token', |
| 519 extra_headers={'X-Requesting-XSRF-Token': '1'}) | 520 extra_headers={'X-Requesting-XSRF-Token': '1'}) |
| 520 | 521 |
| 521 # You cannot close an issue with a GET. | 522 # You cannot close an issue with a GET. |
| 522 # We pass an empty string for the data so it is a POST rather than a GET. | 523 # We pass an empty string for the data so it is a POST rather than a GET. |
| 523 data = [("description", self.description), | 524 data = [("description", self.description), |
| 524 ("xsrf_token", xsrf_token)] | 525 ("xsrf_token", xsrf_token)] |
| 525 ctype, body = upload.EncodeMultipartFormData(data, []) | 526 ctype, body = upload.EncodeMultipartFormData(data, []) |
| 526 rpc_server.Send('/' + self.GetIssue() + '/close', body, ctype) | 527 rpc_server.Send( |
| 528 '/' + self.GetIssue() + '/close', payload=body, content_type=ctype) |
| 527 | 529 |
| 528 def _RpcServer(self): | 530 def RpcServer(self): |
| 529 """Returns an upload.RpcServer() to access this review's rietveld instance. | 531 """Returns an upload.RpcServer() to access this review's rietveld instance. |
| 530 """ | 532 """ |
| 531 if not self._rpc_server: | 533 if not self._rpc_server: |
| 532 server = self.GetRietveldServer() | 534 self.GetIssue() |
| 533 self._rpc_server = upload.GetRpcServer(server, save_cookies=True) | 535 self._rpc_server = rietveld.Rietveld(self.rietveld_server, None, None) |
| 534 return self._rpc_server | 536 return self._rpc_server |
| 535 | 537 |
| 536 def _IssueSetting(self): | 538 def _IssueSetting(self): |
| 537 """Return the git setting that stores this change's issue.""" | 539 """Return the git setting that stores this change's issue.""" |
| 538 return 'branch.%s.rietveldissue' % self.GetBranch() | 540 return 'branch.%s.rietveldissue' % self.GetBranch() |
| 539 | 541 |
| 540 def _PatchsetSetting(self): | 542 def _PatchsetSetting(self): |
| 541 """Return the git setting that stores this change's most recent patchset.""" | 543 """Return the git setting that stores this change's most recent patchset.""" |
| 542 return 'branch.%s.rietveldpatchset' % self.GetBranch() | 544 return 'branch.%s.rietveldpatchset' % self.GetBranch() |
| 543 | 545 |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 # Apply watchlists on upload. | 843 # Apply watchlists on upload. |
| 842 if not committing: | 844 if not committing: |
| 843 watchlist = watchlists.Watchlists(change.RepositoryRoot()) | 845 watchlist = watchlists.Watchlists(change.RepositoryRoot()) |
| 844 files = [f.LocalPath() for f in change.AffectedFiles()] | 846 files = [f.LocalPath() for f in change.AffectedFiles()] |
| 845 cl.SetWatchers(watchlist.GetWatchersForPaths(files)) | 847 cl.SetWatchers(watchlist.GetWatchersForPaths(files)) |
| 846 | 848 |
| 847 try: | 849 try: |
| 848 output = presubmit_support.DoPresubmitChecks(change, committing, | 850 output = presubmit_support.DoPresubmitChecks(change, committing, |
| 849 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, | 851 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, |
| 850 default_presubmit=None, may_prompt=may_prompt, tbr=tbr, | 852 default_presubmit=None, may_prompt=may_prompt, tbr=tbr, |
| 851 host_url=cl.GetRietveldServer()) | 853 rietveld=cl.RpcServer()) |
| 852 except presubmit_support.PresubmitFailure, e: | 854 except presubmit_support.PresubmitFailure, e: |
| 853 DieWithError( | 855 DieWithError( |
| 854 ('%s\nMaybe your depot_tools is out of date?\n' | 856 ('%s\nMaybe your depot_tools is out of date?\n' |
| 855 'If all fails, contact maruel@') % e) | 857 'If all fails, contact maruel@') % e) |
| 856 | 858 |
| 857 # TODO(dpranke): We should propagate the error out instead of calling exit(). | 859 # TODO(dpranke): We should propagate the error out instead of calling exit(). |
| 858 if not output.should_continue(): | 860 if not output.should_continue(): |
| 859 sys.exit(1) | 861 sys.exit(1) |
| 860 | 862 |
| 861 return output | 863 return output |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1443 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1445 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
| 1444 | 1446 |
| 1445 # Not a known command. Default to help. | 1447 # Not a known command. Default to help. |
| 1446 GenUsage(parser, 'help') | 1448 GenUsage(parser, 'help') |
| 1447 return CMDhelp(parser, argv) | 1449 return CMDhelp(parser, argv) |
| 1448 | 1450 |
| 1449 | 1451 |
| 1450 if __name__ == '__main__': | 1452 if __name__ == '__main__': |
| 1451 fix_encoding.fix_encoding() | 1453 fix_encoding.fix_encoding() |
| 1452 sys.exit(main(sys.argv[1:])) | 1454 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |