Add --include-dirs for google-java-format

Test: updated
Bug: 342445502
Change-Id: I984ec36b89d07bf8d193257cd0adf5fe71a365c1
diff --git a/README.md b/README.md
index 5b8ffce..7befb53 100644
--- a/README.md
+++ b/README.md
@@ -195,7 +195,9 @@
 * `cpplint`: Run through the cpplint tool (for C++ code).
 * `gofmt`: Run Go code through `gofmt`.
 * `google_java_format`: Run Java code through
-  [`google-java-format`](https://github.com/google/google-java-format)
+  [`google-java-format`](https://github.com/google/google-java-format).
+  Supports an additional option --include-dirs, which if specified will limit
+  enforcement to only files under the specified directories.
 * `jsonlint`: Verify JSON code is sane.
 * `ktfmt`: Run Kotlin code through `ktfmt`. Supports an additional option
   --include-dirs, which if specified will limit enforcement to only files under
diff --git a/rh/hooks.py b/rh/hooks.py
index 6cb92a0..7f62713 100644
--- a/rh/hooks.py
+++ b/rh/hooks.py
@@ -390,17 +390,35 @@
 
 def check_google_java_format(project, commit, _desc, _diff, options=None):
     """Run google-java-format on the commit."""
+    include_dir_args = [x for x in options.args()
+                        if x.startswith('--include-dirs=')]
+    include_dirs = [x[len('--include-dirs='):].split(',')
+                    for x in include_dir_args]
+    patterns = [fr'^{x}/.*\.java$' for dir_list in include_dirs
+                for x in dir_list]
+    if not patterns:
+        patterns = [r'\.java$']
+
+    filtered = _filter_diff(_diff, patterns)
+
+    if not filtered:
+        return None
+
+    args = [x for x in options.args() if x not in include_dir_args]
 
     tool = get_helper_path('google-java-format.py')
     google_java_format = options.tool_path('google-java-format')
     google_java_format_diff = options.tool_path('google-java-format-diff')
     tool_args = ['--google-java-format', google_java_format,
                  '--google-java-format-diff', google_java_format_diff,
-                 '--commit', commit] + options.args()
-    cmd = [tool] + tool_args
+                 '--commit', commit] + args
+    cmd = [tool] + tool_args + HookOptions.expand_vars(
+                   ('${PREUPLOAD_FILES}',), filtered)
     fixup_cmd = [tool, '--fix'] + tool_args
-    return _check_cmd('google-java-format', project, commit, cmd,
-                      fixup_cmd=fixup_cmd)
+    return [rh.results.HookCommandResult('google-java-format', project, commit,
+                                         _run(cmd),
+                                         files=[x.file for x in filtered],
+                                         fixup_cmd=fixup_cmd)]
 
 
 def check_ktfmt(project, commit, _desc, diff, options=None):
diff --git a/rh/hooks_unittest.py b/rh/hooks_unittest.py
index 003057e..0bb7726 100755
--- a/rh/hooks_unittest.py
+++ b/rh/hooks_unittest.py
@@ -393,9 +393,26 @@
 
     def test_google_java_format(self, mock_check, _mock_run):
         """Verify the google_java_format builtin hook."""
+        # First call should do nothing as there are no files to check.
         ret = rh.hooks.check_google_java_format(
             self.project, 'commit', 'desc', (), options=self.options)
-        self.assertEqual(ret, mock_check.return_value)
+        self.assertIsNone(ret)
+        self.assertFalse(mock_check.called)
+        # Check that .java files are included by default.
+        diff = [rh.git.RawDiffEntry(file='foo.java'),
+                rh.git.RawDiffEntry(file='bar.kt'),
+                rh.git.RawDiffEntry(file='baz/blah.java')]
+        ret = rh.hooks.check_google_java_format(
+            self.project, 'commit', 'desc', diff, options=self.options)
+        self.assertListEqual(ret[0].files, ['foo.java', 'baz/blah.java'])
+        diff = [rh.git.RawDiffEntry(file='foo/f1.java'),
+                rh.git.RawDiffEntry(file='bar/f2.java'),
+                rh.git.RawDiffEntry(file='baz/f2.java')]
+        ret = rh.hooks.check_google_java_format(
+            self.project, 'commit', 'desc', diff,
+            options=rh.hooks.HookOptions('hook name',
+            ['--include-dirs=foo,baz'], {}))
+        self.assertListEqual(ret[0].files, ['foo/f1.java', 'baz/f2.java'])
 
     def test_commit_msg_bug_field(self, _mock_check, _mock_run):
         """Verify the commit_msg_bug_field builtin hook."""