repohooks: allow java file to contain 100 chars

Java files are allowed to contain 100 chars, not 80 chars.

Chromium Java style guide
https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md
It says "Chromium follows the Android Open Source style guide unless an
exception is listed below."

According to AOSP Java Code Style for Contributors,
https://source.android.com/setup/contribute/code-style#limit-line-length
"Each line of text in your code should be at most 100 characters long."

This CL allows Java files to contain over 80 chars under 100 chars.

BUG=None
TEST=pre-upload_unittest.py

Change-Id: I89143ea40316725a4c874be3ca545cb396a2bf61
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/repohooks/+/2004310
Tested-by: Ayato Tokubi <tokubi@google.com>
Commit-Queue: Ayato Tokubi <tokubi@google.com>
Reviewed-by: Will Bradley <wbbradley@chromium.org>
Reviewed-by: Tatsuhisa Yamaguchi <yamaguchi@chromium.org>
Reviewed-by: Shuhei Takahashi <nya@chromium.org>
diff --git a/pre-upload.py b/pre-upload.py
index 9628730..a2ab332 100755
--- a/pre-upload.py
+++ b/pre-upload.py
@@ -495,6 +495,12 @@
       r'.*\.go$',
   ]
 
+  DEFAULT_MAX_LENGTHS = [
+      # Java's line length limit is 100 chars.
+      # https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md
+      (r'.*\.java$', 100),
+  ]
+
   MAX_LEN = 80
 
   included, excluded = _parse_common_inclusion_options(options)
@@ -509,6 +515,13 @@
         r'^#\s*(define|include|import|pragma|if|ifndef|endif)\b',
     )
 
+    max_len = MAX_LEN
+
+    for expr, length in DEFAULT_MAX_LENGTHS:
+      if re.search(expr, afile):
+        max_len = length
+        break
+
     if os.path.basename(afile).startswith('OWNERS'):
       # File paths can get long, and there's no way to break them up into
       # multiple lines.
@@ -520,15 +533,16 @@
     skip_regexps = [re.compile(x) for x in skip_regexps]
     for line_num, line in _get_file_diff(afile, commit):
       # Allow certain lines to exceed the maxlen rule.
-      if len(line) <= MAX_LEN or any(x.search(line) for x in skip_regexps):
+      if len(line) <= max_len or any(x.search(line) for x in skip_regexps):
         continue
 
-      errors.append('%s, line %s, %s chars' % (afile, line_num, len(line)))
+      errors.append('%s, line %s, %s chars, over %s chars' %
+                    (afile, line_num, len(line), max_len))
       if len(errors) == 5:  # Just show the first 5 errors.
         break
 
   if errors:
-    msg = 'Found lines longer than %s characters (first 5 shown):' % MAX_LEN
+    msg = 'Found lines longer than the limit (first 5 shown):'
     return HookFailure(msg, errors)
   return None
 
diff --git a/pre-upload_unittest.py b/pre-upload_unittest.py
index e1cbcb5..ac21185 100755
--- a/pre-upload_unittest.py
+++ b/pre-upload_unittest.py
@@ -109,9 +109,10 @@
     ]
     failure = pre_upload._check_no_long_lines(ProjectNamed('PROJECT'), 'COMMIT')
     self.assertTrue(failure)
-    self.assertEqual('Found lines longer than 80 characters (first 5 shown):',
+    self.assertEqual('Found lines longer than the limit (first 5 shown):',
                      failure.msg)
-    self.assertEqual(['x.py, line %d, 81 chars' % x for x in [3, 4, 8]],
+    self.assertEqual(['x.py, line %d, 81 chars, over 80 chars' %
+                      x for x in [3, 4, 8]],
                      failure.items)
 
   def testCheckTreatsOwnersFilesSpecially(self):
@@ -143,7 +144,7 @@
           self.assertFalse(failure, assert_msg)
         else:
           self.assertTrue(failure, assert_msg)
-          self.assertIn('Found lines longer than 80 characters', failure.msg,
+          self.assertIn('Found lines longer than the limit', failure.msg,
                         assert_msg)
 
   def testIncludeOptions(self):
@@ -166,6 +167,25 @@
     self.assertFalse(pre_upload._check_no_long_lines(
         ProjectNamed('PROJECT'), 'COMMIT', options=['--exclude_regex=foo']))
 
+  def testSpecialLineLength(self):
+    mock_lines = (
+        (u'x' * 101, True),
+        (u'x' * 100, False),
+        (u'x' * 81, False),
+        (u'x' * 80, False),
+    )
+    self.PatchObject(pre_upload,
+                     '_get_affected_files',
+                     return_value=['foo.java'])
+    for line, is_ok in mock_lines:
+      self.diff_mock.return_value = [(1, line)]
+      if is_ok:
+        self.assertTrue(pre_upload._check_no_long_lines(
+            ProjectNamed('PROJECT'), 'COMMIT'))
+      else:
+        self.assertFalse(pre_upload._check_no_long_lines(
+            ProjectNamed('PROJECT'), 'COMMIT'))
+
 
 class CheckTabbedIndentsTest(PreUploadTestCase):
   """Tests for _check_tabbed_indents."""