Chromium Code Reviews| 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 """Enables directory-specific presubmit checks to run at upload and/or commit. | 6 """Enables directory-specific presubmit checks to run at upload and/or commit. |
| 7 """ | 7 """ |
| 8 | 8 |
| 9 __version__ = '1.3.5' | 9 __version__ = '1.3.5' |
| 10 | 10 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 | 79 |
| 80 def PromptYesNo(input_stream, output_stream, prompt): | 80 def PromptYesNo(input_stream, output_stream, prompt): |
| 81 output_stream.write(prompt) | 81 output_stream.write(prompt) |
| 82 response = input_stream.readline().strip().lower() | 82 response = input_stream.readline().strip().lower() |
| 83 return response == 'y' or response == 'yes' | 83 return response == 'y' or response == 'yes' |
| 84 | 84 |
| 85 | 85 |
| 86 def _RightHandSideLinesImpl(affected_files): | 86 def _RightHandSideLinesImpl(affected_files): |
| 87 """Implements RightHandSideLines for InputApi and GclChange.""" | 87 """Implements RightHandSideLines for InputApi and GclChange.""" |
| 88 for af in affected_files: | 88 for af in affected_files: |
| 89 lines = af.NewContents() | 89 lines = af.ChangedContents() |
| 90 line_number = 0 | |
| 91 for line in lines: | 90 for line in lines: |
| 92 line_number += 1 | 91 yield (af, line[0], line[1]) |
| 93 yield (af, line_number, line) | |
| 94 | 92 |
| 95 | 93 |
| 96 class OutputApi(object): | 94 class OutputApi(object): |
| 97 """This class (more like a module) gets passed to presubmit scripts so that | 95 """This class (more like a module) gets passed to presubmit scripts so that |
| 98 they can specify various types of results. | 96 they can specify various types of results. |
| 99 """ | 97 """ |
| 100 # Method could be a function | 98 # Method could be a function |
| 101 # pylint: disable=R0201 | 99 # pylint: disable=R0201 |
| 102 class PresubmitResult(object): | 100 class PresubmitResult(object): |
| 103 """Base class for result objects.""" | 101 """Base class for result objects.""" |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 474 | 472 |
| 475 def OldFileTempPath(self): | 473 def OldFileTempPath(self): |
| 476 """Returns the path on local disk where the old contents resides. | 474 """Returns the path on local disk where the old contents resides. |
| 477 | 475 |
| 478 The old version is the file in depot, i.e. the "left hand side". | 476 The old version is the file in depot, i.e. the "left hand side". |
| 479 This is a read-only cached copy of the old contents. *DO NOT* try to | 477 This is a read-only cached copy of the old contents. *DO NOT* try to |
| 480 modify this file. | 478 modify this file. |
| 481 """ | 479 """ |
| 482 raise NotImplementedError() # Implement if/when needed. | 480 raise NotImplementedError() # Implement if/when needed. |
| 483 | 481 |
| 482 def ChangedContents(self): | |
| 483 # Return a list of tuples (line number, line text) of all new lines in the | |
|
M-A Ruel
2011/02/09 18:30:26
I think it should be a docstring.
"""Returns a li
vb
2011/02/09 18:54:11
Done.
| |
| 484 # file. This relies on the scm diff output describing each changed code | |
| 485 # section with a line of the form | |
| 486 # | |
| 487 # ^@@ <old line num>,<old size> <new line num>,<new size> @@$ | |
| 488 # | |
| 489 new_lines = [] | |
| 490 line_num = 0 | |
| 491 diff_text = self.GenerateScmDiff() | |
| 492 for line in diff_text.splitlines(): | |
|
M-A Ruel
2011/02/09 18:30:26
You didn't merge lines 491 and 492. You prefer to
vb
2011/02/09 18:54:11
good point, it was a leftover of previous code, no
| |
| 493 m = re.match(r'^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@', line) | |
| 494 if m: | |
| 495 line_num = int(m.groups(1)[0]) | |
| 496 continue | |
| 497 if re.search(r'^\+[^\+]', line): | |
|
M-A Ruel
2011/02/09 18:30:26
Actually, this regexp is wrong:
what if the line
vb
2011/02/09 18:54:11
Yes, a good catch. Did away with regexp here, I th
| |
| 498 new_lines.append((line_num, line[1:])) | |
| 499 if not re.search(r'^\-[^\-]', line): | |
| 500 line_num += 1 | |
| 501 return new_lines | |
| 502 | |
| 484 def __str__(self): | 503 def __str__(self): |
| 485 return self.LocalPath() | 504 return self.LocalPath() |
| 486 | 505 |
| 487 | 506 |
| 488 class SvnAffectedFile(AffectedFile): | 507 class SvnAffectedFile(AffectedFile): |
| 489 """Representation of a file in a change out of a Subversion checkout.""" | 508 """Representation of a file in a change out of a Subversion checkout.""" |
| 490 # Method 'NNN' is abstract in class 'NNN' but is not overridden | 509 # Method 'NNN' is abstract in class 'NNN' but is not overridden |
| 491 # pylint: disable=W0223 | 510 # pylint: disable=W0223 |
| 492 | 511 |
| 493 def __init__(self, *args, **kwargs): | 512 def __init__(self, *args, **kwargs): |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 # A deleted file is not a text file. | 544 # A deleted file is not a text file. |
| 526 self._is_text_file = False | 545 self._is_text_file = False |
| 527 elif self.IsDirectory(): | 546 elif self.IsDirectory(): |
| 528 self._is_text_file = False | 547 self._is_text_file = False |
| 529 else: | 548 else: |
| 530 mime_type = scm.SVN.GetFileProperty(self.AbsoluteLocalPath(), | 549 mime_type = scm.SVN.GetFileProperty(self.AbsoluteLocalPath(), |
| 531 'svn:mime-type') | 550 'svn:mime-type') |
| 532 self._is_text_file = (not mime_type or mime_type.startswith('text/')) | 551 self._is_text_file = (not mime_type or mime_type.startswith('text/')) |
| 533 return self._is_text_file | 552 return self._is_text_file |
| 534 | 553 |
| 554 def GenerateScmDiff(self): | |
| 555 return scm.SVN.GenerateDiff(self.AbsoluteLocalPath()) | |
| 535 | 556 |
| 536 class GitAffectedFile(AffectedFile): | 557 class GitAffectedFile(AffectedFile): |
| 537 """Representation of a file in a change out of a git checkout.""" | 558 """Representation of a file in a change out of a git checkout.""" |
| 538 # Method 'NNN' is abstract in class 'NNN' but is not overridden | 559 # Method 'NNN' is abstract in class 'NNN' but is not overridden |
| 539 # pylint: disable=W0223 | 560 # pylint: disable=W0223 |
| 540 | 561 |
| 541 def __init__(self, *args, **kwargs): | 562 def __init__(self, *args, **kwargs): |
| 542 AffectedFile.__init__(self, *args, **kwargs) | 563 AffectedFile.__init__(self, *args, **kwargs) |
| 543 self._server_path = None | 564 self._server_path = None |
| 544 self._is_text_file = None | 565 self._is_text_file = None |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 570 if self.Action() == 'D': | 591 if self.Action() == 'D': |
| 571 # A deleted file is not a text file. | 592 # A deleted file is not a text file. |
| 572 self._is_text_file = False | 593 self._is_text_file = False |
| 573 elif self.IsDirectory(): | 594 elif self.IsDirectory(): |
| 574 self._is_text_file = False | 595 self._is_text_file = False |
| 575 else: | 596 else: |
| 576 # raise NotImplementedException() # TODO(maruel) Implement. | 597 # raise NotImplementedException() # TODO(maruel) Implement. |
| 577 self._is_text_file = os.path.isfile(self.AbsoluteLocalPath()) | 598 self._is_text_file = os.path.isfile(self.AbsoluteLocalPath()) |
| 578 return self._is_text_file | 599 return self._is_text_file |
| 579 | 600 |
| 601 def GenerateScmDiff(self): | |
| 602 return scm.GIT.GenerateDiff( | |
| 603 os.path.dirname(self.AbsoluteLocalPath()), | |
| 604 files=[os.path.basename(self.AbsoluteLocalPath()),]) | |
| 580 | 605 |
| 581 class Change(object): | 606 class Change(object): |
| 582 """Describe a change. | 607 """Describe a change. |
| 583 | 608 |
| 584 Used directly by the presubmit scripts to query the current change being | 609 Used directly by the presubmit scripts to query the current change being |
| 585 tested. | 610 tested. |
| 586 | 611 |
| 587 Instance members: | 612 Instance members: |
| 588 tags: Dictionnary of KEY=VALUE pairs found in the change description. | 613 tags: Dictionnary of KEY=VALUE pairs found in the change description. |
| 589 self.KEY: equivalent to tags['KEY'] | 614 self.KEY: equivalent to tags['KEY'] |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1128 options.commit, | 1153 options.commit, |
| 1129 options.verbose, | 1154 options.verbose, |
| 1130 sys.stdout, | 1155 sys.stdout, |
| 1131 sys.stdin, | 1156 sys.stdin, |
| 1132 options.default_presubmit, | 1157 options.default_presubmit, |
| 1133 options.may_prompt) | 1158 options.may_prompt) |
| 1134 | 1159 |
| 1135 | 1160 |
| 1136 if __name__ == '__main__': | 1161 if __name__ == '__main__': |
| 1137 sys.exit(Main(sys.argv)) | 1162 sys.exit(Main(sys.argv)) |
| OLD | NEW |