diff options
-rwxr-xr-x | PRESUBMIT.py | 10 | ||||
-rwxr-xr-x | PRESUBMIT_unittest.py | 12 |
2 files changed, 16 insertions, 6 deletions
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 1b33adf..6809548 100755 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py @@ -60,10 +60,12 @@ def LocalChecks(input_api, output_api, max_cols=80): - contains a TAB - has a line that ends with whitespace - contains a line >|max_cols| cols unless |max_cols| is 0. + - File does not end in a newline, or ends in more than one. Note that the whole file is checked, not only the changes. """ cr_files = [] + eof_files = [] results = [] excluded_paths = [input_api.re.compile(x) for x in EXCLUDED_PATHS] files = input_api.AffectedFiles() @@ -88,6 +90,10 @@ def LocalChecks(input_api, output_api, max_cols=80): if '\r' in contents: cr_files.append(path) + # Check that the file ends in one and only one newline character. + if len(contents) > 0 and (contents[-1:] != "\n" or contents[-2:-1] == "\n"): + eof_files.append(path) + local_errors = [] # Remove EOL character. lines = contents.splitlines() @@ -118,4 +124,8 @@ def LocalChecks(input_api, output_api, max_cols=80): results.append(output_api.PresubmitError( 'Found CR (or CRLF) line ending in these files, please use only LF:', items=cr_files)) + if eof_files: + results.append(output_api.PresubmitError( + 'These files should end in one (and only one) newline character:', + items=eof_files)) return results diff --git a/PRESUBMIT_unittest.py b/PRESUBMIT_unittest.py index b8183c2..6f2ff00 100755 --- a/PRESUBMIT_unittest.py +++ b/PRESUBMIT_unittest.py @@ -62,24 +62,24 @@ class PresubmitUnittest(unittest.TestCase): MockAffectedFile('foo/blat/source.py'), ] self.file_contents = 'file with \n\terror\nhere\r\nyes there' - # 3 source files, 2 errors by file + 1 global CR error. - self.failUnless(len(PRESUBMIT.LocalChecks(api, MockOutputApi)) == 7) + # 3 source files, 2 errors by file + 1 global CR + 1 global EOF error. + self.failUnless(len(PRESUBMIT.LocalChecks(api, MockOutputApi)) == 8) - self.file_contents = 'file\twith\ttabs' + self.file_contents = 'file\twith\ttabs\n' # 3 source files, 1 error by file. self.failUnless(len(PRESUBMIT.LocalChecks(api, MockOutputApi)) == 3) - self.file_contents = 'file\rusing\rCRs' + self.file_contents = 'file\rusing\rCRs\n' # One global CR error. self.failUnless(len(PRESUBMIT.LocalChecks(api, MockOutputApi)) == 1) self.failUnless( len(PRESUBMIT.LocalChecks(api, MockOutputApi)[0].items) == 3) - self.file_contents = 'both\ttabs and\r\nCRLF' + self.file_contents = 'both\ttabs and\r\nCRLF\n' # 3 source files, 1 error by file + 1 global CR error. self.failUnless(len(PRESUBMIT.LocalChecks(api, MockOutputApi)) == 4) - self.file_contents = 'file with\nzero \\t errors \\r\\n' + self.file_contents = 'file with\nzero \\t errors \\r\\n\n' self.failIf(PRESUBMIT.LocalChecks(api, MockOutputApi)) |