Allow include/exclude options in several checks.
check_no_long_lines, check_no_stray_whitespace, check_no_tabs,
check_tabbed_indents will accept options to include/exclude
specific files from checking.
We can often run better checks (e.g. pylint) than those naive
checks. In such cases, it is a good idea to exclude files from
checks partially (e.g. *.py only), rather than totally opting
out.
BUG=None
TEST=pre-upload_unittest.py
Change-Id: Ie3015e1d30064e3335d677657b7613f0315e4df0
Reviewed-on: https://chromium-review.googlesource.com/564925
Commit-Ready: Prathmesh Prabhu <pprabhu@chromium.org>
Tested-by: Shuhei Takahashi <nya@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
diff --git a/pre-upload.py b/pre-upload.py
index a8c4240..c061f4f 100755
--- a/pre-upload.py
+++ b/pre-upload.py
@@ -423,10 +423,28 @@
return HookFailure(error_description, errors)
+def _parse_common_inclusion_options(options):
+ """Parses common hook options for including/excluding files.
+
+ Args:
+ options: Option string list.
+
+ Returns:
+ (included, excluded) where each one is a list of regex strings.
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--exclude_regex', action='append')
+ parser.add_argument('--include_regex', action='append')
+ opts = parser.parse_args(options)
+ included = opts.include_regex or []
+ excluded = opts.exclude_regex or []
+ return included, excluded
+
+
# Common Hooks
-def _check_no_long_lines(_project, commit):
+def _check_no_long_lines(_project, commit, options=()):
"""Checks there are no lines longer than MAX_LEN in any of the text files."""
MAX_LEN = 80
@@ -434,11 +452,12 @@
r'https?://',
r'^#\s*(define|include|import|pragma|if|endif)\b']))
- errors = []
+ included, excluded = _parse_common_inclusion_options(options)
files = _filter_files(_get_affected_files(commit),
- COMMON_INCLUDED_PATHS,
- COMMON_EXCLUDED_PATHS)
+ included + COMMON_INCLUDED_PATHS,
+ excluded + COMMON_EXCLUDED_PATHS)
+ errors = []
for afile in files:
for line_num, line in _get_file_diff(afile, commit):
# Allow certain lines to exceed the maxlen rule.
@@ -454,17 +473,18 @@
return HookFailure(msg, errors)
-def _check_no_stray_whitespace(_project, commit):
+def _check_no_stray_whitespace(_project, commit, options=()):
"""Checks that there is no stray whitespace at source lines end."""
+ included, excluded = _parse_common_inclusion_options(options)
files = _filter_files(_get_affected_files(commit),
- COMMON_INCLUDED_PATHS,
- COMMON_EXCLUDED_PATHS)
+ included + COMMON_INCLUDED_PATHS,
+ excluded + COMMON_EXCLUDED_PATHS)
return _check_lines_in_diff(commit, files,
lambda line: line.rstrip() != line,
'Found line ending with white space in:')
-def _check_no_tabs(_project, commit):
+def _check_no_tabs(_project, commit, options=()):
"""Checks there are no unexpanded tabs."""
TAB_OK_PATHS = [
r"/src/third_party/u-boot/",
@@ -475,15 +495,16 @@
r".*\.mk$"
]
+ included, excluded = _parse_common_inclusion_options(options)
files = _filter_files(_get_affected_files(commit),
- COMMON_INCLUDED_PATHS,
- COMMON_EXCLUDED_PATHS + TAB_OK_PATHS)
+ included + COMMON_INCLUDED_PATHS,
+ excluded + COMMON_EXCLUDED_PATHS + TAB_OK_PATHS)
return _check_lines_in_diff(commit, files,
lambda line: '\t' in line,
'Found a tab character in:')
-def _check_tabbed_indents(_project, commit):
+def _check_tabbed_indents(_project, commit, options=()):
"""Checks that indents use tabs only."""
TABS_REQUIRED_PATHS = [
r".*\.ebuild$",
@@ -491,9 +512,10 @@
]
LEADING_SPACE_RE = re.compile('[\t]* ')
+ included, excluded = _parse_common_inclusion_options(options)
files = _filter_files(_get_affected_files(commit),
- TABS_REQUIRED_PATHS,
- COMMON_EXCLUDED_PATHS)
+ included + TABS_REQUIRED_PATHS,
+ excluded + COMMON_EXCLUDED_PATHS)
return _check_lines_in_diff(
commit, files,
lambda line: LEADING_SPACE_RE.match(line) is not None,
@@ -1009,12 +1031,7 @@
)
copyright_re = re.compile(COPYRIGHT_LINE)
- parser = argparse.ArgumentParser()
- parser.add_argument('--exclude_regex', action='append')
- parser.add_argument('--include_regex', action='append')
- opts = parser.parse_args(options)
- included = opts.include_regex or []
- excluded = opts.exclude_regex or []
+ included, excluded = _parse_common_inclusion_options(options)
bad_files = []
bad_copyright_files = []
diff --git a/pre-upload_unittest.py b/pre-upload_unittest.py
index bc03c27..6e517d2 100755
--- a/pre-upload_unittest.py
+++ b/pre-upload_unittest.py
@@ -54,11 +54,10 @@
"""Tests for _check_no_long_lines."""
def setUp(self):
- self.PatchObject(pre_upload, '_get_affected_files', return_value=['x.py'])
- self.PatchObject(pre_upload, '_filter_files', return_value=['x.py'])
self.diff_mock = self.PatchObject(pre_upload, '_get_file_diff')
- def runTest(self):
+ def testCheck(self):
+ self.PatchObject(pre_upload, '_get_affected_files', return_value=['x.py'])
self.diff_mock.return_value = [
(1, u"x" * 80), # OK
(2, "\x80" * 80), # OK
@@ -77,12 +76,33 @@
for line in [3, 4, 8]],
failure.items)
+ def testIncludeOptions(self):
+ self.PatchObject(pre_upload,
+ '_get_affected_files',
+ return_value=['foo.txt'])
+ self.diff_mock.return_value = [(1, u"x" * 81)]
+ self.assertFalse(pre_upload._check_no_long_lines(
+ ProjectNamed('PROJECT'), 'COMMIT'))
+ self.assertTrue(pre_upload._check_no_long_lines(
+ ProjectNamed('PROJECT'), 'COMMIT', options=['--include_regex=foo']))
+
+ def testExcludeOptions(self):
+ self.PatchObject(pre_upload,
+ '_get_affected_files',
+ return_value=['foo.py'])
+ self.diff_mock.return_value = [(1, u"x" * 81)]
+ self.assertTrue(pre_upload._check_no_long_lines(
+ ProjectNamed('PROJECT'), 'COMMIT'))
+ self.assertFalse(pre_upload._check_no_long_lines(
+ ProjectNamed('PROJECT'), 'COMMIT', options=['--exclude_regex=foo']))
+
class CheckTabbedIndentsTest(cros_test_lib.MockTestCase):
"""Tests for _check_tabbed_indents."""
def setUp(self):
- self.PatchObject(pre_upload, '_get_affected_files', return_value=['x.py'])
- self.PatchObject(pre_upload, '_filter_files', return_value=['x.py'])
+ self.PatchObject(pre_upload,
+ '_get_affected_files',
+ return_value=['x.ebuild'])
self.diff_mock = self.PatchObject(pre_upload, '_get_file_diff')
def test_good_cases(self):
@@ -110,7 +130,7 @@
self.assertTrue(failure)
self.assertEquals('Found a space in indentation (must be all tabs):',
failure.msg)
- self.assertEquals(['x.py, line %d' % line for line in xrange(1, 6)],
+ self.assertEquals(['x.ebuild, line %d' % line for line in xrange(1, 6)],
failure.items)