Add file whitelisting capabilities to checkstyle.py

Certain projects might want to enable checkstyle gradually so
we need a way to whitelist which files should be checked.

Test: added test_FilterFiles
Change-Id: I501677ce824f882ccb5f2ad129af8f596d01c6e8
diff --git a/tools/checkstyle/checkstyle.py b/tools/checkstyle/checkstyle.py
index 4ea2c6a..63fd920 100755
--- a/tools/checkstyle/checkstyle.py
+++ b/tools/checkstyle/checkstyle.py
@@ -59,7 +59,9 @@
   return errors, warnings
 
 
-def RunCheckstyleOnACommit(commit, config_xml=CHECKSTYLE_STYLE):
+def RunCheckstyleOnACommit(commit,
+                           config_xml=CHECKSTYLE_STYLE,
+                           file_whitelist=None):
   """Runs Checkstyle checks on a given commit.
 
   It will run Checkstyle on the changed Java files in a specified commit SHA-1
@@ -69,6 +71,7 @@
   Args:
     commit: A full 40 character SHA-1 of a commit to check.
     config_xml: Path of the checkstyle XML configuration file.
+    file_whitelist: A list of whitelisted file paths that should be checked.
 
   Returns:
     A tuple of errors and warnings.
@@ -79,6 +82,7 @@
     commit = git.last_commit()
   print 'Running Checkstyle on %s commit' % commit
   commit_modified_files = _GetModifiedFiles(commit, explicit_commit)
+  commit_modified_files = _FilterFiles(commit_modified_files, file_whitelist)
   if not commit_modified_files.keys():
     print 'No Java files to check'
     return [], []
@@ -230,6 +234,13 @@
   return modified_files
 
 
+def _FilterFiles(files, file_whitelist):
+  if not file_whitelist:
+    return files
+  return {f: files[f] for f in files
+          for whitelist in file_whitelist if whitelist in f}
+
+
 def _GetTempFilesForCommit(file_names, commit):
   """Creates a temporary snapshot of the files in at a commit.
 
@@ -277,6 +288,7 @@
   parser.add_argument('--file', '-f', nargs='+')
   parser.add_argument('--sha', '-s')
   parser.add_argument('--config_xml', '-c')
+  parser.add_argument('--file_whitelist', '-fw', nargs='+')
   args = parser.parse_args()
 
   config_xml = args.config_xml or CHECKSTYLE_STYLE
@@ -288,7 +300,8 @@
     # Files to check were specified via command line.
     (errors, warnings) = RunCheckstyleOnFiles(args.file, config_xml)
   else:
-    (errors, warnings) = RunCheckstyleOnACommit(args.sha, config_xml)
+    (errors, warnings) = RunCheckstyleOnACommit(args.sha, config_xml,
+                                                args.file_whitelist)
 
   if errors or warnings:
     sys.exit(1)
diff --git a/tools/checkstyle/tests.py b/tools/checkstyle/tests.py
index 28e200b..74b325e 100755
--- a/tools/checkstyle/tests.py
+++ b/tools/checkstyle/tests.py
@@ -152,5 +152,16 @@
     output = out.getvalue()
     self.assertEqual(output, '')
 
+  def test_FilterFiles(self):
+    files = {TEST_FILE1: FILE_MODIFIED, TEST_FILE2: FILE_ADDED}
+    output = checkstyle._FilterFiles(files, None)
+    self.assertEqual(files, output)
+    output = checkstyle._FilterFiles(files, ['Blarg2'])
+    self.assertEqual({TEST_FILE2: FILE_ADDED}, output)
+    output = checkstyle._FilterFiles(files, ['Blarg'])
+    self.assertEqual(files, output)
+    output = checkstyle._FilterFiles(files, ['FunkyTown'])
+    self.assertEqual({}, output)
+
 if __name__ == '__main__':
   unittest.main()