| 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 """\ |     6 """\ | 
|     7 Wrapper script around Rietveld's upload.py that simplifies working with groups |     7 Wrapper script around Rietveld's upload.py that simplifies working with groups | 
|     8 of files. |     8 of files. | 
|     9 """ |     9 """ | 
|    10  |    10  | 
|    11 import getpass |  | 
|    12 import optparse |    11 import optparse | 
|    13 import os |    12 import os | 
|    14 import random |    13 import random | 
|    15 import re |    14 import re | 
|    16 import string |    15 import string | 
|    17 import subprocess |    16 import subprocess | 
|    18 import sys |    17 import sys | 
|    19 import tempfile |    18 import tempfile | 
|    20 import time |    19 import time | 
|    21 from third_party import upload |    20 from third_party import upload | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|    32     import simplejson as json  # pylint: disable=F0401 |    31     import simplejson as json  # pylint: disable=F0401 | 
|    33  |    32  | 
|    34 import breakpad  # pylint: disable=W0611 |    33 import breakpad  # pylint: disable=W0611 | 
|    35  |    34  | 
|    36 # gcl now depends on gclient. |    35 # gcl now depends on gclient. | 
|    37 from scm import SVN |    36 from scm import SVN | 
|    38  |    37  | 
|    39 import fix_encoding |    38 import fix_encoding | 
|    40 import gclient_utils |    39 import gclient_utils | 
|    41 import presubmit_support |    40 import presubmit_support | 
 |    41 import rietveld | 
|    42 import subprocess2 |    42 import subprocess2 | 
|    43  |    43  | 
|    44 __version__ = '1.2' |    44 __version__ = '1.2.1' | 
|    45  |    45  | 
|    46  |    46  | 
|    47 CODEREVIEW_SETTINGS = { |    47 CODEREVIEW_SETTINGS = { | 
|    48   # To make gcl send reviews to a server, check in a file named |    48   # To make gcl send reviews to a server, check in a file named | 
|    49   # "codereview.settings" (see |CODEREVIEW_SETTINGS_FILE| below) to your |    49   # "codereview.settings" (see |CODEREVIEW_SETTINGS_FILE| below) to your | 
|    50   # project's base directory and add the following line to codereview.settings: |    50   # project's base directory and add the following line to codereview.settings: | 
|    51   # CODE_REVIEW_SERVER: codereview.yourserver.org |    51   # CODE_REVIEW_SERVER: codereview.yourserver.org | 
|    52 } |    52 } | 
|    53  |    53  | 
|    54 # globals that store the root of the current repository and the directory where |    54 # globals that store the root of the current repository and the directory where | 
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   276     description: the description. |   276     description: the description. | 
|   277     files: a list of 2 tuple containing (status, filename) of changed files, |   277     files: a list of 2 tuple containing (status, filename) of changed files, | 
|   278            with paths being relative to the top repository directory. |   278            with paths being relative to the top repository directory. | 
|   279     local_root: Local root directory |   279     local_root: Local root directory | 
|   280     rietveld: rietveld server for this change |   280     rietveld: rietveld server for this change | 
|   281   """ |   281   """ | 
|   282   # Kept for unit test support. This is for the old format, it's deprecated. |   282   # Kept for unit test support. This is for the old format, it's deprecated. | 
|   283   _SEPARATOR = "\n-----\n" |   283   _SEPARATOR = "\n-----\n" | 
|   284  |   284  | 
|   285   def __init__(self, name, issue, patchset, description, files, local_root, |   285   def __init__(self, name, issue, patchset, description, files, local_root, | 
|   286                rietveld, needs_upload=False): |   286                rietveld_url, needs_upload=False): | 
|   287     self.name = name |   287     self.name = name | 
|   288     self.issue = int(issue) |   288     self.issue = int(issue) | 
|   289     self.patchset = int(patchset) |   289     self.patchset = int(patchset) | 
|   290     self._description = None |   290     self._description = None | 
|   291     self._subject = None |   291     self._subject = None | 
|   292     self._reviewers = None |   292     self._reviewers = None | 
|   293     self._set_description(description) |   293     self._set_description(description) | 
|   294     if files is None: |   294     if files is None: | 
|   295       files = [] |   295       files = [] | 
|   296     self._files = files |   296     self._files = files | 
|   297     self.patch = None |   297     self.patch = None | 
|   298     self._local_root = local_root |   298     self._local_root = local_root | 
|   299     self.needs_upload = needs_upload |   299     self.needs_upload = needs_upload | 
|   300     self.rietveld = rietveld |   300     self.rietveld = rietveld_url | 
|   301     if not self.rietveld: |   301     if not self.rietveld: | 
|   302       # Set the default value. |   302       # Set the default value. | 
|   303       self.rietveld = GetCodeReviewSetting('CODE_REVIEW_SERVER') |   303       self.rietveld = GetCodeReviewSetting('CODE_REVIEW_SERVER') | 
 |   304     self._rpc_server = None | 
|   304  |   305  | 
|   305   def _get_description(self): |   306   def _get_description(self): | 
|   306     return self._description |   307     return self._description | 
|   307  |   308  | 
|   308   def _set_description(self, description): |   309   def _set_description(self, description): | 
|   309     # TODO(dpranke): Cloned from git_cl.py. These should be shared. |   310     # TODO(dpranke): Cloned from git_cl.py. These should be shared. | 
|   310     if not description: |   311     if not description: | 
|   311       self._description = description |   312       self._description = description | 
|   312       return |   313       return | 
|   313  |   314  | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   377           'files': self.GetFiles(), |   378           'files': self.GetFiles(), | 
|   378           'description': self.description, |   379           'description': self.description, | 
|   379           'rietveld': self.rietveld, |   380           'rietveld': self.rietveld, | 
|   380         }, sort_keys=True, indent=2) |   381         }, sort_keys=True, indent=2) | 
|   381     gclient_utils.FileWrite(GetChangelistInfoFile(self.name), data) |   382     gclient_utils.FileWrite(GetChangelistInfoFile(self.name), data) | 
|   382  |   383  | 
|   383   def Delete(self): |   384   def Delete(self): | 
|   384     """Removes the changelist information from disk.""" |   385     """Removes the changelist information from disk.""" | 
|   385     os.remove(GetChangelistInfoFile(self.name)) |   386     os.remove(GetChangelistInfoFile(self.name)) | 
|   386  |   387  | 
 |   388   def RpcServer(self): | 
 |   389     if not self._rpc_server: | 
 |   390       if not self.rietveld: | 
 |   391         ErrorExit(CODEREVIEW_SETTINGS_FILE_NOT_FOUND) | 
 |   392       self._rpc_server = rietveld.Rietveld(self.rietveld, None, None) | 
 |   393     return self._rpc_server | 
 |   394  | 
|   387   def CloseIssue(self): |   395   def CloseIssue(self): | 
|   388     """Closes the Rietveld issue for this changelist.""" |   396     """Closes the Rietveld issue for this changelist.""" | 
|   389     # Newer versions of Rietveld require us to pass an XSRF token to POST, so |   397     # Newer versions of Rietveld require us to pass an XSRF token to POST, so | 
|   390     # we fetch it from the server. |   398     # we fetch it from the server. | 
|   391     xsrf_token = self.SendToRietveld( |   399     xsrf_token = self.SendToRietveld( | 
|   392         '/xsrf_token', |   400         '/xsrf_token', | 
|   393         extra_headers={'X-Requesting-XSRF-Token': '1'}) |   401         extra_headers={'X-Requesting-XSRF-Token': '1'}) | 
|   394  |   402  | 
|   395     # You cannot close an issue with a GET. |   403     # You cannot close an issue with a GET. | 
|   396     # We pass an empty string for the data so it is a POST rather than a GET. |   404     # We pass an empty string for the data so it is a POST rather than a GET. | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
|   413  |   421  | 
|   414   def PrimeLint(self): |   422   def PrimeLint(self): | 
|   415     """Do background work on Rietveld to lint the file so that the results are |   423     """Do background work on Rietveld to lint the file so that the results are | 
|   416     ready when the issue is viewed.""" |   424     ready when the issue is viewed.""" | 
|   417     if self.issue and self.patchset: |   425     if self.issue and self.patchset: | 
|   418       self.SendToRietveld('/lint/issue%s_%s' % (self.issue, self.patchset), |   426       self.SendToRietveld('/lint/issue%s_%s' % (self.issue, self.patchset), | 
|   419           timeout=1) |   427           timeout=1) | 
|   420  |   428  | 
|   421   def SendToRietveld(self, request_path, timeout=None, **kwargs): |   429   def SendToRietveld(self, request_path, timeout=None, **kwargs): | 
|   422     """Send a POST/GET to Rietveld.  Returns the response body.""" |   430     """Send a POST/GET to Rietveld.  Returns the response body.""" | 
|   423     if not self.rietveld: |  | 
|   424       ErrorExit(CODEREVIEW_SETTINGS_FILE_NOT_FOUND) |  | 
|   425     def GetUserCredentials(): |  | 
|   426       """Prompts the user for a username and password.""" |  | 
|   427       email = upload.GetEmail('Email (login for uploading to %s)' % |  | 
|   428           self.rietveld) |  | 
|   429       password = getpass.getpass('Password for %s: ' % email) |  | 
|   430       return email, password |  | 
|   431     rpc_server = upload.HttpRpcServer(self.rietveld, |  | 
|   432                                       GetUserCredentials, |  | 
|   433                                       save_cookies=True) |  | 
|   434     try: |   431     try: | 
|   435       return rpc_server.Send(request_path, timeout=timeout, **kwargs) |   432       return self.RpcServer().Send(request_path, timeout=timeout, **kwargs) | 
|   436     except urllib2.URLError: |   433     except urllib2.URLError: | 
|   437       if timeout is None: |   434       if timeout is None: | 
|   438         ErrorExit('Error accessing url %s' % request_path) |   435         ErrorExit('Error accessing url %s' % request_path) | 
|   439       else: |   436       else: | 
|   440         return None |   437         return None | 
|   441  |   438  | 
|   442   def MissingTests(self): |   439   def MissingTests(self): | 
|   443     """Returns True if the change looks like it needs unit tests but has none. |   440     """Returns True if the change looks like it needs unit tests but has none. | 
|   444  |   441  | 
|   445     A change needs unit tests if it contains any new source files or methods. |   442     A change needs unit tests if it contains any new source files or methods. | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   529         changelist doesn't exist. |   526         changelist doesn't exist. | 
|   530       update_status: if True, the svn status will be updated for all the files |   527       update_status: if True, the svn status will be updated for all the files | 
|   531         and unchanged files will be removed. |   528         and unchanged files will be removed. | 
|   532  |   529  | 
|   533     Returns: a ChangeInfo object. |   530     Returns: a ChangeInfo object. | 
|   534     """ |   531     """ | 
|   535     info_file = GetChangelistInfoFile(changename) |   532     info_file = GetChangelistInfoFile(changename) | 
|   536     if not os.path.exists(info_file): |   533     if not os.path.exists(info_file): | 
|   537       if fail_on_not_found: |   534       if fail_on_not_found: | 
|   538         ErrorExit("Changelist " + changename + " not found.") |   535         ErrorExit("Changelist " + changename + " not found.") | 
|   539       return ChangeInfo(changename, 0, 0, '', None, local_root, rietveld=None, |   536       return ChangeInfo( | 
|   540                         needs_upload=False) |   537           changename, 0, 0, '', None, local_root, rietveld_url=None, | 
 |   538           needs_upload=False) | 
|   541     content = gclient_utils.FileRead(info_file, 'r') |   539     content = gclient_utils.FileRead(info_file, 'r') | 
|   542     save = False |   540     save = False | 
|   543     try: |   541     try: | 
|   544       values = ChangeInfo._LoadNewFormat(content) |   542       values = ChangeInfo._LoadNewFormat(content) | 
|   545     except ValueError: |   543     except ValueError: | 
|   546       try: |   544       try: | 
|   547         values = ChangeInfo._LoadOldFormat(content) |   545         values = ChangeInfo._LoadOldFormat(content) | 
|   548         save = True |   546         save = True | 
|   549       except ValueError: |   547       except ValueError: | 
|   550         ErrorExit( |   548         ErrorExit( | 
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1215  |  1213  | 
|  1216 def DoPresubmitChecks(change_info, committing, may_prompt): |  1214 def DoPresubmitChecks(change_info, committing, may_prompt): | 
|  1217   """Imports presubmit, then calls presubmit.DoPresubmitChecks.""" |  1215   """Imports presubmit, then calls presubmit.DoPresubmitChecks.""" | 
|  1218   root_presubmit = GetCachedFile('PRESUBMIT.py', use_root=True) |  1216   root_presubmit = GetCachedFile('PRESUBMIT.py', use_root=True) | 
|  1219   change = presubmit_support.SvnChange(change_info.name, |  1217   change = presubmit_support.SvnChange(change_info.name, | 
|  1220                                        change_info.description, |  1218                                        change_info.description, | 
|  1221                                        change_info.GetLocalRoot(), |  1219                                        change_info.GetLocalRoot(), | 
|  1222                                        change_info.GetFiles(), |  1220                                        change_info.GetFiles(), | 
|  1223                                        change_info.issue, |  1221                                        change_info.issue, | 
|  1224                                        change_info.patchset) |  1222                                        change_info.patchset) | 
|  1225   output = presubmit_support.DoPresubmitChecks(change=change, |  1223   output = presubmit_support.DoPresubmitChecks( | 
|  1226                                                committing=committing, |  1224       change=change, | 
|  1227                                                verbose=False, |  1225       committing=committing, | 
|  1228                                                output_stream=sys.stdout, |  1226       verbose=False, | 
|  1229                                                input_stream=sys.stdin, |  1227       output_stream=sys.stdout, | 
|  1230                                                default_presubmit=root_presubmit, |  1228       input_stream=sys.stdin, | 
|  1231                                                may_prompt=may_prompt, |  1229       default_presubmit=root_presubmit, | 
|  1232                                                tbr=False, |  1230       may_prompt=may_prompt, | 
|  1233                                                host_url=change_info.rietveld) |  1231       tbr=False, | 
 |  1232       rietveld=change_info.RpcServer()) | 
|  1234   if not output.should_continue() and may_prompt: |  1233   if not output.should_continue() and may_prompt: | 
|  1235     # TODO(dpranke): move into DoPresubmitChecks(), unify cmd line args. |  1234     # TODO(dpranke): move into DoPresubmitChecks(), unify cmd line args. | 
|  1236     print "\nPresubmit errors, can't continue (use --no_presubmit to bypass)" |  1235     print "\nPresubmit errors, can't continue (use --no_presubmit to bypass)" | 
|  1237  |  1236  | 
|  1238   return output |  1237   return output | 
|  1239  |  1238  | 
|  1240  |  1239  | 
|  1241 @no_args |  1240 @no_args | 
|  1242 def CMDchanges(): |  1241 def CMDchanges(): | 
|  1243   """Lists all the changelists and their files.""" |  1242   """Lists all the changelists and their files.""" | 
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1456       raise |  1455       raise | 
|  1457     print >> sys.stderr, ( |  1456     print >> sys.stderr, ( | 
|  1458         'AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |  1457         'AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 
|  1459         'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)) |  1458         'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)) | 
|  1460     return 1 |  1459     return 1 | 
|  1461  |  1460  | 
|  1462  |  1461  | 
|  1463 if __name__ == "__main__": |  1462 if __name__ == "__main__": | 
|  1464   fix_encoding.fix_encoding() |  1463   fix_encoding.fix_encoding() | 
|  1465   sys.exit(main(sys.argv[1:])) |  1464   sys.exit(main(sys.argv[1:])) | 
| OLD | NEW |