| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 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 |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 class ChangeInfo(object): | 267 class ChangeInfo(object): |
| 268 """Holds information about a changelist. | 268 """Holds information about a changelist. |
| 269 | 269 |
| 270 name: change name. | 270 name: change name. |
| 271 issue: the Rietveld issue number or 0 if it hasn't been uploaded yet. | 271 issue: the Rietveld issue number or 0 if it hasn't been uploaded yet. |
| 272 patchset: the Rietveld latest patchset number or 0. | 272 patchset: the Rietveld latest patchset number or 0. |
| 273 description: the description. | 273 description: the description. |
| 274 files: a list of 2 tuple containing (status, filename) of changed files, | 274 files: a list of 2 tuple containing (status, filename) of changed files, |
| 275 with paths being relative to the top repository directory. | 275 with paths being relative to the top repository directory. |
| 276 local_root: Local root directory | 276 local_root: Local root directory |
| 277 rietveld: rietveld server for this change |
| 277 """ | 278 """ |
| 278 | 279 # Kept for unit test support. This is for the old format, it's deprecated. |
| 279 _SEPARATOR = "\n-----\n" | 280 _SEPARATOR = "\n-----\n" |
| 280 # The info files have the following format: | |
| 281 # issue_id, patchset\n (, patchset is optional) | |
| 282 # _SEPARATOR\n | |
| 283 # filepath1\n | |
| 284 # filepath2\n | |
| 285 # . | |
| 286 # . | |
| 287 # filepathn\n | |
| 288 # _SEPARATOR\n | |
| 289 # description | |
| 290 | 281 |
| 291 def __init__(self, name, issue, patchset, description, files, local_root, | 282 def __init__(self, name, issue, patchset, description, files, local_root, |
| 292 needs_upload=False): | 283 rietveld, needs_upload=False): |
| 293 self.name = name | 284 self.name = name |
| 294 self.issue = int(issue) | 285 self.issue = int(issue) |
| 295 self.patchset = int(patchset) | 286 self.patchset = int(patchset) |
| 296 self.description = description | 287 self.description = description |
| 297 if files is None: | 288 if files is None: |
| 298 files = [] | 289 files = [] |
| 299 self._files = files | 290 self._files = files |
| 300 self.patch = None | 291 self.patch = None |
| 301 self._local_root = local_root | 292 self._local_root = local_root |
| 302 self.needs_upload = needs_upload | 293 self.needs_upload = needs_upload |
| 294 self.rietveld = rietveld |
| 295 if not self.rietveld: |
| 296 # Set the default value. |
| 297 self.rietveld = GetCodeReviewSetting('CODE_REVIEW_SERVER') |
| 303 | 298 |
| 304 def NeedsUpload(self): | 299 def NeedsUpload(self): |
| 305 return self.needs_upload | 300 return self.needs_upload |
| 306 | 301 |
| 307 def GetFileNames(self): | 302 def GetFileNames(self): |
| 308 """Returns the list of file names included in this change.""" | 303 """Returns the list of file names included in this change.""" |
| 309 return [f[1] for f in self._files] | 304 return [f[1] for f in self._files] |
| 310 | 305 |
| 311 def GetFiles(self): | 306 def GetFiles(self): |
| 312 """Returns the list of files included in this change with their status.""" | 307 """Returns the list of files included in this change with their status.""" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 330 return [f[1] for f in self.GetFiles() if f[0].startswith("A")] | 325 return [f[1] for f in self.GetFiles() if f[0].startswith("A")] |
| 331 | 326 |
| 332 def Save(self): | 327 def Save(self): |
| 333 """Writes the changelist information to disk.""" | 328 """Writes the changelist information to disk.""" |
| 334 data = json.dumps({ | 329 data = json.dumps({ |
| 335 'issue': self.issue, | 330 'issue': self.issue, |
| 336 'patchset': self.patchset, | 331 'patchset': self.patchset, |
| 337 'needs_upload': self.NeedsUpload(), | 332 'needs_upload': self.NeedsUpload(), |
| 338 'files': self.GetFiles(), | 333 'files': self.GetFiles(), |
| 339 'description': self.description, | 334 'description': self.description, |
| 335 'rietveld': self.rietveld, |
| 340 }, sort_keys=True, indent=2) | 336 }, sort_keys=True, indent=2) |
| 341 gclient_utils.FileWrite(GetChangelistInfoFile(self.name), data) | 337 gclient_utils.FileWrite(GetChangelistInfoFile(self.name), data) |
| 342 | 338 |
| 343 def Delete(self): | 339 def Delete(self): |
| 344 """Removes the changelist information from disk.""" | 340 """Removes the changelist information from disk.""" |
| 345 os.remove(GetChangelistInfoFile(self.name)) | 341 os.remove(GetChangelistInfoFile(self.name)) |
| 346 | 342 |
| 347 def CloseIssue(self): | 343 def CloseIssue(self): |
| 348 """Closes the Rietveld issue for this changelist.""" | 344 """Closes the Rietveld issue for this changelist.""" |
| 349 data = [("description", self.description),] | 345 data = [("description", self.description),] |
| 350 ctype, body = upload.EncodeMultipartFormData(data, []) | 346 ctype, body = upload.EncodeMultipartFormData(data, []) |
| 351 SendToRietveld("/%d/close" % self.issue, body, ctype) | 347 self.SendToRietveld('/%d/close' % self.issue, body, ctype) |
| 352 | 348 |
| 353 def UpdateRietveldDescription(self): | 349 def UpdateRietveldDescription(self): |
| 354 """Sets the description for an issue on Rietveld.""" | 350 """Sets the description for an issue on Rietveld.""" |
| 355 data = [("description", self.description),] | 351 data = [("description", self.description),] |
| 356 ctype, body = upload.EncodeMultipartFormData(data, []) | 352 ctype, body = upload.EncodeMultipartFormData(data, []) |
| 357 SendToRietveld("/%d/description" % self.issue, body, ctype) | 353 self.SendToRietveld('/%d/description' % self.issue, body, ctype) |
| 354 |
| 355 def GetIssueDescription(self): |
| 356 """Returns the issue description from Rietveld.""" |
| 357 return self.SendToRietveld('/%d/description' % self.issue) |
| 358 |
| 359 def PrimeLint(self): |
| 360 """Do background work on Rietveld to lint the file so that the results are |
| 361 ready when the issue is viewed.""" |
| 362 if self.issue and self.patchset: |
| 363 self.SendToRietveld('/lint/issue%s_%s' % (self.issue, self.patchset), |
| 364 timeout=1) |
| 365 |
| 366 def SendToRietveld(self, request_path, payload=None, |
| 367 content_type="application/octet-stream", timeout=None): |
| 368 """Send a POST/GET to Rietveld. Returns the response body.""" |
| 369 if not self.rietveld: |
| 370 ErrorExit(CODEREVIEW_SETTINGS_FILE_NOT_FOUND) |
| 371 def GetUserCredentials(): |
| 372 """Prompts the user for a username and password.""" |
| 373 email = upload.GetEmail('Email (login for uploading to %s)' % |
| 374 self.rietveld) |
| 375 password = getpass.getpass('Password for %s: ' % email) |
| 376 return email, password |
| 377 rpc_server = upload.HttpRpcServer(self.rietveld, |
| 378 GetUserCredentials, |
| 379 save_cookies=True) |
| 380 try: |
| 381 return rpc_server.Send(request_path, payload, content_type, timeout) |
| 382 except urllib2.URLError: |
| 383 if timeout is None: |
| 384 ErrorExit('Error accessing url %s' % request_path) |
| 385 else: |
| 386 return None |
| 358 | 387 |
| 359 def MissingTests(self): | 388 def MissingTests(self): |
| 360 """Returns True if the change looks like it needs unit tests but has none. | 389 """Returns True if the change looks like it needs unit tests but has none. |
| 361 | 390 |
| 362 A change needs unit tests if it contains any new source files or methods. | 391 A change needs unit tests if it contains any new source files or methods. |
| 363 """ | 392 """ |
| 364 SOURCE_SUFFIXES = [".cc", ".cpp", ".c", ".m", ".mm"] | 393 SOURCE_SUFFIXES = [".cc", ".cpp", ".c", ".m", ".mm"] |
| 365 # Ignore third_party entirely. | 394 # Ignore third_party entirely. |
| 366 files = [f for f in self._NonDeletedFileList() | 395 files = [f for f in self._NonDeletedFileList() |
| 367 if f.find("third_party") == -1] | 396 if f.find("third_party") == -1] |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 changelist doesn't exist. | 475 changelist doesn't exist. |
| 447 update_status: if True, the svn status will be updated for all the files | 476 update_status: if True, the svn status will be updated for all the files |
| 448 and unchanged files will be removed. | 477 and unchanged files will be removed. |
| 449 | 478 |
| 450 Returns: a ChangeInfo object. | 479 Returns: a ChangeInfo object. |
| 451 """ | 480 """ |
| 452 info_file = GetChangelistInfoFile(changename) | 481 info_file = GetChangelistInfoFile(changename) |
| 453 if not os.path.exists(info_file): | 482 if not os.path.exists(info_file): |
| 454 if fail_on_not_found: | 483 if fail_on_not_found: |
| 455 ErrorExit("Changelist " + changename + " not found.") | 484 ErrorExit("Changelist " + changename + " not found.") |
| 456 return ChangeInfo(changename, 0, 0, '', None, local_root, | 485 return ChangeInfo(changename, 0, 0, '', None, local_root, rietveld=None, |
| 457 needs_upload=False) | 486 needs_upload=False) |
| 458 content = gclient_utils.FileRead(info_file, 'r') | 487 content = gclient_utils.FileRead(info_file, 'r') |
| 459 save = False | 488 save = False |
| 460 try: | 489 try: |
| 461 values = ChangeInfo._LoadNewFormat(content) | 490 values = ChangeInfo._LoadNewFormat(content) |
| 462 except ValueError: | 491 except ValueError: |
| 463 try: | 492 try: |
| 464 values = ChangeInfo._LoadOldFormat(content) | 493 values = ChangeInfo._LoadOldFormat(content) |
| 465 save = True | 494 save = True |
| 466 except ValueError: | 495 except ValueError: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 477 # File has been reverted. | 506 # File has been reverted. |
| 478 save = True | 507 save = True |
| 479 files.remove(item) | 508 files.remove(item) |
| 480 continue | 509 continue |
| 481 status = status_result[0][0] | 510 status = status_result[0][0] |
| 482 if status != item[0]: | 511 if status != item[0]: |
| 483 save = True | 512 save = True |
| 484 files[files.index(item)] = (status, item[1]) | 513 files[files.index(item)] = (status, item[1]) |
| 485 change_info = ChangeInfo(changename, values['issue'], values['patchset'], | 514 change_info = ChangeInfo(changename, values['issue'], values['patchset'], |
| 486 values['description'], files, | 515 values['description'], files, |
| 487 local_root, values['needs_upload']) | 516 local_root, values.get('rietveld'), |
| 517 values['needs_upload']) |
| 488 if save: | 518 if save: |
| 489 change_info.Save() | 519 change_info.Save() |
| 490 return change_info | 520 return change_info |
| 491 | 521 |
| 492 @staticmethod | 522 @staticmethod |
| 493 def _LoadOldFormat(content): | 523 def _LoadOldFormat(content): |
| 524 # The info files have the following format: |
| 525 # issue_id, patchset\n (, patchset is optional) |
| 526 # _SEPARATOR\n |
| 527 # filepath1\n |
| 528 # filepath2\n |
| 529 # . |
| 530 # . |
| 531 # filepathn\n |
| 532 # _SEPARATOR\n |
| 533 # description |
| 494 split_data = content.split(ChangeInfo._SEPARATOR, 2) | 534 split_data = content.split(ChangeInfo._SEPARATOR, 2) |
| 495 if len(split_data) != 3: | 535 if len(split_data) != 3: |
| 496 raise ValueError('Bad change format') | 536 raise ValueError('Bad change format') |
| 497 values = { | 537 values = { |
| 498 'issue': 0, | 538 'issue': 0, |
| 499 'patchset': 0, | 539 'patchset': 0, |
| 500 'needs_upload': False, | 540 'needs_upload': False, |
| 501 'files': [], | 541 'files': [], |
| 502 } | 542 } |
| 503 items = split_data[0].split(', ') | 543 items = split_data[0].split(', ') |
| (...skipping 23 matching lines...) Expand all Loading... |
| 527 | 567 |
| 528 | 568 |
| 529 def LoadChangelistInfoForMultiple(changenames, local_root, fail_on_not_found, | 569 def LoadChangelistInfoForMultiple(changenames, local_root, fail_on_not_found, |
| 530 update_status): | 570 update_status): |
| 531 """Loads many changes and merge their files list into one pseudo change. | 571 """Loads many changes and merge their files list into one pseudo change. |
| 532 | 572 |
| 533 This is mainly usefull to concatenate many changes into one for a 'gcl try'. | 573 This is mainly usefull to concatenate many changes into one for a 'gcl try'. |
| 534 """ | 574 """ |
| 535 changes = changenames.split(',') | 575 changes = changenames.split(',') |
| 536 aggregate_change_info = ChangeInfo(changenames, 0, 0, '', None, local_root, | 576 aggregate_change_info = ChangeInfo(changenames, 0, 0, '', None, local_root, |
| 537 needs_upload=False) | 577 rietveld=None, needs_upload=False) |
| 538 for change in changes: | 578 for change in changes: |
| 539 aggregate_change_info._files += ChangeInfo.Load(change, | 579 aggregate_change_info._files += ChangeInfo.Load(change, |
| 540 local_root, | 580 local_root, |
| 541 fail_on_not_found, | 581 fail_on_not_found, |
| 542 update_status).GetFiles() | 582 update_status).GetFiles() |
| 543 return aggregate_change_info | 583 return aggregate_change_info |
| 544 | 584 |
| 545 | 585 |
| 546 def GetCLs(): | 586 def GetCLs(): |
| 547 """Returns a list of all the changelists in this repository.""" | 587 """Returns a list of all the changelists in this repository.""" |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 | 648 |
| 609 See docstring of GetModifiedFiles for information about path of files and | 649 See docstring of GetModifiedFiles for information about path of files and |
| 610 which directories are scanned. | 650 which directories are scanned. |
| 611 """ | 651 """ |
| 612 modified_files = GetModifiedFiles() | 652 modified_files = GetModifiedFiles() |
| 613 if "" not in modified_files: | 653 if "" not in modified_files: |
| 614 return [] | 654 return [] |
| 615 return modified_files[""] | 655 return modified_files[""] |
| 616 | 656 |
| 617 | 657 |
| 618 def SendToRietveld(request_path, payload=None, | |
| 619 content_type="application/octet-stream", timeout=None): | |
| 620 """Send a POST/GET to Rietveld. Returns the response body.""" | |
| 621 server = GetCodeReviewSetting("CODE_REVIEW_SERVER") | |
| 622 if not server: | |
| 623 ErrorExit(CODEREVIEW_SETTINGS_FILE_NOT_FOUND) | |
| 624 def GetUserCredentials(): | |
| 625 """Prompts the user for a username and password.""" | |
| 626 email = upload.GetEmail("Email (login for uploading to %s)" % server) | |
| 627 password = getpass.getpass("Password for %s: " % email) | |
| 628 return email, password | |
| 629 rpc_server = upload.HttpRpcServer(server, | |
| 630 GetUserCredentials, | |
| 631 save_cookies=True) | |
| 632 try: | |
| 633 return rpc_server.Send(request_path, payload, content_type, timeout) | |
| 634 except urllib2.URLError: | |
| 635 if timeout is None: | |
| 636 ErrorExit("Error accessing url %s" % request_path) | |
| 637 else: | |
| 638 return None | |
| 639 | |
| 640 | |
| 641 def GetIssueDescription(issue): | |
| 642 """Returns the issue description from Rietveld.""" | |
| 643 return SendToRietveld("/%d/description" % issue) | |
| 644 | |
| 645 | |
| 646 def ListFiles(show_unknown_files): | 658 def ListFiles(show_unknown_files): |
| 647 files = GetModifiedFiles() | 659 files = GetModifiedFiles() |
| 648 cl_keys = files.keys() | 660 cl_keys = files.keys() |
| 649 cl_keys.sort() | 661 cl_keys.sort() |
| 650 for cl_name in cl_keys: | 662 for cl_name in cl_keys: |
| 651 if not cl_name: | 663 if not cl_name: |
| 652 continue | 664 continue |
| 653 note = "" | 665 note = "" |
| 654 change_info = ChangeInfo.Load(cl_name, GetRepositoryRoot(), | 666 change_info = ChangeInfo.Load(cl_name, GetRepositoryRoot(), |
| 655 fail_on_not_found=True, update_status=False) | 667 fail_on_not_found=True, update_status=False) |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 if not OptionallyDoPresubmitChecks(change_info, False, args): | 788 if not OptionallyDoPresubmitChecks(change_info, False, args): |
| 777 return 1 | 789 return 1 |
| 778 no_watchlists = (FilterFlag(args, "--no_watchlists") or | 790 no_watchlists = (FilterFlag(args, "--no_watchlists") or |
| 779 FilterFlag(args, "--no-watchlists")) | 791 FilterFlag(args, "--no-watchlists")) |
| 780 | 792 |
| 781 # Map --send-mail to --send_mail | 793 # Map --send-mail to --send_mail |
| 782 if FilterFlag(args, "--send-mail"): | 794 if FilterFlag(args, "--send-mail"): |
| 783 args.append("--send_mail") | 795 args.append("--send_mail") |
| 784 | 796 |
| 785 upload_arg = ["upload.py", "-y"] | 797 upload_arg = ["upload.py", "-y"] |
| 786 server = GetCodeReviewSetting("CODE_REVIEW_SERVER") | 798 upload_arg.append("--server=%s" % change_info.rietveld) |
| 787 if not server: | |
| 788 ErrorExit(CODEREVIEW_SETTINGS_FILE_NOT_FOUND) | |
| 789 upload_arg.append("--server=%s" % server) | |
| 790 upload_arg.extend(args) | 799 upload_arg.extend(args) |
| 791 | 800 |
| 792 desc_file = "" | 801 desc_file = "" |
| 793 if change_info.issue: # Uploading a new patchset. | 802 if change_info.issue: # Uploading a new patchset. |
| 794 found_message = False | 803 found_message = False |
| 795 for arg in args: | 804 for arg in args: |
| 796 if arg.startswith("--message") or arg.startswith("-m"): | 805 if arg.startswith("--message") or arg.startswith("-m"): |
| 797 found_message = True | 806 found_message = True |
| 798 break | 807 break |
| 799 | 808 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 830 subject = subject + "..." | 839 subject = subject + "..." |
| 831 upload_arg.append("--message=" + subject) | 840 upload_arg.append("--message=" + subject) |
| 832 | 841 |
| 833 if GetCodeReviewSetting("PRIVATE") == "True": | 842 if GetCodeReviewSetting("PRIVATE") == "True": |
| 834 upload_arg.append("--private") | 843 upload_arg.append("--private") |
| 835 | 844 |
| 836 # Change the current working directory before calling upload.py so that it | 845 # Change the current working directory before calling upload.py so that it |
| 837 # shows the correct base. | 846 # shows the correct base. |
| 838 previous_cwd = os.getcwd() | 847 previous_cwd = os.getcwd() |
| 839 os.chdir(change_info.GetLocalRoot()) | 848 os.chdir(change_info.GetLocalRoot()) |
| 840 | |
| 841 # If we have a lot of files with long paths, then we won't be able to fit | 849 # If we have a lot of files with long paths, then we won't be able to fit |
| 842 # the command to "svn diff". Instead, we generate the diff manually for | 850 # the command to "svn diff". Instead, we generate the diff manually for |
| 843 # each file and concatenate them before passing it to upload.py. | 851 # each file and concatenate them before passing it to upload.py. |
| 844 if change_info.patch is None: | 852 if change_info.patch is None: |
| 845 change_info.patch = GenerateDiff(change_info.GetFileNames()) | 853 change_info.patch = GenerateDiff(change_info.GetFileNames()) |
| 846 issue, patchset = upload.RealMain(upload_arg, change_info.patch) | 854 issue, patchset = upload.RealMain(upload_arg, change_info.patch) |
| 847 if issue and patchset: | 855 if issue and patchset: |
| 848 change_info.issue = int(issue) | 856 change_info.issue = int(issue) |
| 849 change_info.patchset = int(patchset) | 857 change_info.patchset = int(patchset) |
| 850 change_info.Save() | 858 change_info.Save() |
| 851 | 859 |
| 852 if desc_file: | 860 if desc_file: |
| 853 os.remove(desc_file) | 861 os.remove(desc_file) |
| 854 | 862 change_info.PrimeLint() |
| 855 # Do background work on Rietveld to lint the file so that the results are | |
| 856 # ready when the issue is viewed. | |
| 857 SendToRietveld("/lint/issue%s_%s" % (issue, patchset), timeout=0.5) | |
| 858 | |
| 859 # Move back before considering try, so GetCodeReviewSettings is | |
| 860 # consistent. | |
| 861 os.chdir(previous_cwd) | 863 os.chdir(previous_cwd) |
| 862 | |
| 863 print "*** Upload does not submit a try; use gcl try to submit a try. ***" | 864 print "*** Upload does not submit a try; use gcl try to submit a try. ***" |
| 864 | |
| 865 return 0 | 865 return 0 |
| 866 | 866 |
| 867 | 867 |
| 868 @need_change | 868 @need_change |
| 869 def CMDpresubmit(change_info): | 869 def CMDpresubmit(change_info): |
| 870 """Runs presubmit checks on the change. | 870 """Runs presubmit checks on the change. |
| 871 | 871 |
| 872 The actual presubmit code is implemented in presubmit_support.py and looks | 872 The actual presubmit code is implemented in presubmit_support.py and looks |
| 873 for PRESUBMIT.py files.""" | 873 for PRESUBMIT.py files.""" |
| 874 if not change_info.GetFiles(): | 874 if not change_info.GetFiles(): |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 # We face a problem with svn here: Let's say change 'bleh' modifies | 926 # We face a problem with svn here: Let's say change 'bleh' modifies |
| 927 # svn:ignore on dir1\. but another unrelated change 'pouet' modifies | 927 # svn:ignore on dir1\. but another unrelated change 'pouet' modifies |
| 928 # dir1\foo.cc. When the user `gcl commit bleh`, foo.cc is *also committed*. | 928 # dir1\foo.cc. When the user `gcl commit bleh`, foo.cc is *also committed*. |
| 929 # The only fix is to use --non-recursive but that has its issues too: | 929 # The only fix is to use --non-recursive but that has its issues too: |
| 930 # Let's say if dir1 is deleted, --non-recursive must *not* be used otherwise | 930 # Let's say if dir1 is deleted, --non-recursive must *not* be used otherwise |
| 931 # you'll get "svn: Cannot non-recursively commit a directory deletion of a | 931 # you'll get "svn: Cannot non-recursively commit a directory deletion of a |
| 932 # directory with child nodes". Yay... | 932 # directory with child nodes". Yay... |
| 933 commit_cmd = ["svn", "commit"] | 933 commit_cmd = ["svn", "commit"] |
| 934 if change_info.issue: | 934 if change_info.issue: |
| 935 # Get the latest description from Rietveld. | 935 # Get the latest description from Rietveld. |
| 936 change_info.description = GetIssueDescription(change_info.issue) | 936 change_info.description = change_info.GetIssueDescription() |
| 937 | 937 |
| 938 commit_message = change_info.description.replace('\r\n', '\n') | 938 commit_message = change_info.description.replace('\r\n', '\n') |
| 939 if change_info.issue: | 939 if change_info.issue: |
| 940 server = GetCodeReviewSetting("CODE_REVIEW_SERVER") | 940 server = change_info.rietveld |
| 941 if not server: | |
| 942 ErrorExit(CODEREVIEW_SETTINGS_FILE_NOT_FOUND) | |
| 943 if not server.startswith("http://") and not server.startswith("https://"): | 941 if not server.startswith("http://") and not server.startswith("https://"): |
| 944 server = "http://" + server | 942 server = "http://" + server |
| 945 commit_message += ('\nReview URL: %s/%d' % (server, change_info.issue)) | 943 commit_message += ('\nReview URL: %s/%d' % (server, change_info.issue)) |
| 946 | 944 |
| 947 handle, commit_filename = tempfile.mkstemp(text=True) | 945 handle, commit_filename = tempfile.mkstemp(text=True) |
| 948 os.write(handle, commit_message) | 946 os.write(handle, commit_message) |
| 949 os.close(handle) | 947 os.close(handle) |
| 950 | 948 |
| 951 handle, targets_filename = tempfile.mkstemp(text=True) | 949 handle, targets_filename = tempfile.mkstemp(text=True) |
| 952 os.write(handle, "\n".join(change_info.GetFileNames())) | 950 os.write(handle, "\n".join(change_info.GetFileNames())) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 if not os.path.isfile(args[1]): | 997 if not os.path.isfile(args[1]): |
| 1000 ErrorExit('The change "%s" doesn\'t exist.' % args[1]) | 998 ErrorExit('The change "%s" doesn\'t exist.' % args[1]) |
| 1001 f = open(args[1], 'rU') | 999 f = open(args[1], 'rU') |
| 1002 override_description = f.read() | 1000 override_description = f.read() |
| 1003 f.close() | 1001 f.close() |
| 1004 else: | 1002 else: |
| 1005 override_description = None | 1003 override_description = None |
| 1006 | 1004 |
| 1007 if change_info.issue and not change_info.NeedsUpload(): | 1005 if change_info.issue and not change_info.NeedsUpload(): |
| 1008 try: | 1006 try: |
| 1009 description = GetIssueDescription(change_info.issue) | 1007 description = change_info.GetIssueDescription() |
| 1010 except urllib2.HTTPError, err: | 1008 except urllib2.HTTPError, err: |
| 1011 if err.code == 404: | 1009 if err.code == 404: |
| 1012 # The user deleted the issue in Rietveld, so forget the old issue id. | 1010 # The user deleted the issue in Rietveld, so forget the old issue id. |
| 1013 description = change_info.description | 1011 description = change_info.description |
| 1014 change_info.issue = 0 | 1012 change_info.issue = 0 |
| 1015 change_info.Save() | 1013 change_info.Save() |
| 1016 else: | 1014 else: |
| 1017 ErrorExit("Error getting the description from Rietveld: " + err) | 1015 ErrorExit("Error getting the description from Rietveld: " + err) |
| 1018 else: | 1016 else: |
| 1019 if override_description: | 1017 if override_description: |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1107 Checks all the files in the changelist for possible style violations. | 1105 Checks all the files in the changelist for possible style violations. |
| 1108 """ | 1106 """ |
| 1109 try: | 1107 try: |
| 1110 import cpplint | 1108 import cpplint |
| 1111 except ImportError: | 1109 except ImportError: |
| 1112 ErrorExit("You need to install cpplint.py to lint C++ files.") | 1110 ErrorExit("You need to install cpplint.py to lint C++ files.") |
| 1113 # Change the current working directory before calling lint so that it | 1111 # Change the current working directory before calling lint so that it |
| 1114 # shows the correct base. | 1112 # shows the correct base. |
| 1115 previous_cwd = os.getcwd() | 1113 previous_cwd = os.getcwd() |
| 1116 os.chdir(change_info.GetLocalRoot()) | 1114 os.chdir(change_info.GetLocalRoot()) |
| 1117 | |
| 1118 # Process cpplints arguments if any. | 1115 # Process cpplints arguments if any. |
| 1119 filenames = cpplint.ParseArguments(args + change_info.GetFileNames()) | 1116 filenames = cpplint.ParseArguments(args + change_info.GetFileNames()) |
| 1120 | 1117 |
| 1121 white_list = GetCodeReviewSetting("LINT_REGEX") | 1118 white_list = GetCodeReviewSetting("LINT_REGEX") |
| 1122 if not white_list: | 1119 if not white_list: |
| 1123 white_list = DEFAULT_LINT_REGEX | 1120 white_list = DEFAULT_LINT_REGEX |
| 1124 white_regex = re.compile(white_list) | 1121 white_regex = re.compile(white_list) |
| 1125 black_list = GetCodeReviewSetting("LINT_IGNORE_REGEX") | 1122 black_list = GetCodeReviewSetting("LINT_IGNORE_REGEX") |
| 1126 if not black_list: | 1123 if not black_list: |
| 1127 black_list = DEFAULT_LINT_IGNORE_REGEX | 1124 black_list = DEFAULT_LINT_IGNORE_REGEX |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1374 if e.code != 500: | 1371 if e.code != 500: |
| 1375 raise | 1372 raise |
| 1376 print >> sys.stderr, ( | 1373 print >> sys.stderr, ( |
| 1377 'AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 1374 'AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |
| 1378 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)) | 1375 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)) |
| 1379 return 1 | 1376 return 1 |
| 1380 | 1377 |
| 1381 | 1378 |
| 1382 if __name__ == "__main__": | 1379 if __name__ == "__main__": |
| 1383 sys.exit(main(sys.argv[1:])) | 1380 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |