go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

PRESUBMIT.py (9043B)


      1 # Copyright (c) 2021, Google Inc. All rights reserved.
      2 #
      3 # Redistribution and use in source and binary forms, with or without
      4 # modification, are permitted provided that the following conditions are
      5 # met:
      6 #
      7 #   * Redistributions of source code must retain the above copyright
      8 #     notice, this list of conditions and the following disclaimer.
      9 #
     10 #   * Redistributions in binary form must reproduce the above copyright
     11 #     notice, this list of conditions and the following disclaimer in
     12 #     the documentation and/or other materials provided with the
     13 #     distribution.
     14 #
     15 #   * Neither the name of Google nor the names of its contributors may
     16 #     be used to endorse or promote products derived from this software
     17 #     without specific prior written permission.
     18 #
     19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 """Top-level presubmit script for libwebp.
     31 
     32 See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
     33 details on the presubmit API built into depot_tools.
     34 """
     35 
     36 import re
     37 import subprocess2
     38 
     39 USE_PYTHON3 = True
     40 _BASH_INDENTATION = "2"
     41 _GIT_COMMIT_SUBJECT_LENGTH = 65
     42 _INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"]
     43 _INCLUDE_MAN_FILES_ONLY = [r"man/.+\.1$"]
     44 _INCLUDE_SOURCE_FILES_ONLY = [r".*\.[ch]$"]
     45 _LIBWEBP_MAX_LINE_LENGTH = 80
     46 
     47 
     48 def _CheckCommitSubjectLength(input_api, output_api):
     49   """Ensures commit's subject length is no longer than 65 chars."""
     50   name = "git-commit subject"
     51   cmd = ["git", "log", "-1", "--pretty=%s"]
     52   start = input_api.time.time()
     53   proc = subprocess2.Popen(
     54       cmd,
     55       stderr=subprocess2.PIPE,
     56       stdout=subprocess2.PIPE,
     57       universal_newlines=True)
     58 
     59   stdout, _ = proc.communicate()
     60   duration = input_api.time.time() - start
     61 
     62   if not re.match(r"^Revert",
     63                   stdout) and (len(stdout) - 1) > _GIT_COMMIT_SUBJECT_LENGTH:
     64     failure_msg = (
     65         "The commit subject: %s is too long (%d chars)\n"
     66         "Try to keep this to 50 or less (up to 65 is permitted for "
     67         "non-reverts).\n"
     68         "https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-"
     69         "Project#_commit_guidelines") % (stdout, len(stdout) - 1)
     70     return output_api.PresubmitError("%s\n (%4.2fs) failed\n%s" %
     71                                      (name, duration, failure_msg))
     72 
     73   return output_api.PresubmitResult("%s\n (%4.2fs) success" % (name, duration))
     74 
     75 
     76 def _CheckDuplicateFiles(input_api, output_api):
     77   """Ensures there are not repeated filenames."""
     78   all_files = []
     79   for f in input_api.change.AllFiles():
     80     for include_file in _INCLUDE_SOURCE_FILES_ONLY:
     81       if re.match(include_file, f):
     82         all_files.append(f)
     83         break
     84 
     85   basename_to_path = {}
     86   for f in all_files:
     87     basename_file = input_api.basename(f)
     88     if basename_file in basename_to_path:
     89       basename_to_path[basename_file].append(f)
     90     else:
     91       basename_to_path[basename_file] = [f]
     92 
     93   dupes = []
     94   for files in basename_to_path.values():
     95     if len(files) > 1:
     96       dupes.extend(files)
     97 
     98   if dupes:
     99     return output_api.PresubmitError(
    100         "Duplicate source files, rebase or rename some to make them unique:\n%s"
    101         % dupes)
    102   return output_api.PresubmitResult("No duplicates, success\n")
    103 
    104 
    105 def _GetFilesToSkip(input_api):
    106   return list(input_api.DEFAULT_FILES_TO_SKIP) + [
    107       r"swig/.*\.py$",
    108       r"\.pylintrc$",
    109   ]
    110 
    111 
    112 def _RunManCmd(input_api, output_api, man_file):
    113   """man command wrapper."""
    114   cmd = ["man", "--warnings", "-EUTF-8", "-l", "-Tutf8", "-Z", man_file]
    115   name = "Check %s file." % man_file
    116   start = input_api.time.time()
    117   output, _ = subprocess2.communicate(
    118       cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
    119   duration = input_api.time.time() - start
    120   if output[1]:
    121     return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
    122                                      (name, " ".join(cmd), duration, output[1]))
    123   return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
    124                                     (name, " ".join(cmd), duration))
    125 
    126 
    127 def _RunShellCheckCmd(input_api, output_api, bash_file):
    128   """shellcheck command wrapper."""
    129   cmd = ["shellcheck", "-x", "-oall", "-sbash", bash_file]
    130   name = "Check %s file." % bash_file
    131   start = input_api.time.time()
    132   output, rc = subprocess2.communicate(
    133       cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
    134   duration = input_api.time.time() - start
    135   if rc == 0:
    136     return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
    137                                       (name, " ".join(cmd), duration))
    138   return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
    139                                    (name, " ".join(cmd), duration, output[1]))
    140 
    141 
    142 def _RunShfmtCheckCmd(input_api, output_api, bash_file):
    143   """shfmt command wrapper."""
    144   cmd = [
    145       "shfmt", "-i", _BASH_INDENTATION, "-bn", "-ci", "-sr", "-kp", "-d",
    146       bash_file
    147   ]
    148   name = "Check %s file." % bash_file
    149   start = input_api.time.time()
    150   output, rc = subprocess2.communicate(
    151       cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
    152   duration = input_api.time.time() - start
    153   if rc == 0:
    154     return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
    155                                       (name, " ".join(cmd), duration))
    156   return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
    157                                    (name, " ".join(cmd), duration, output[1]))
    158 
    159 
    160 def _RunCmdOnCheckedFiles(input_api, output_api, run_cmd, files_to_check):
    161   """Ensure that libwebp/ files are clean."""
    162   file_filter = lambda x: input_api.FilterSourceFile(
    163       x, files_to_check=files_to_check, files_to_skip=None)
    164 
    165   affected_files = input_api.change.AffectedFiles(file_filter=file_filter)
    166   results = [
    167       run_cmd(input_api, output_api, f.AbsoluteLocalPath())
    168       for f in affected_files
    169   ]
    170   return results
    171 
    172 
    173 def _CommonChecks(input_api, output_api):
    174   """Ensures this patch does not have trailing spaces, extra EOLs,
    175      or long lines.
    176   """
    177   results = []
    178   results.extend(
    179       input_api.canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol(
    180           input_api, output_api))
    181   results.extend(
    182       input_api.canned_checks.CheckChangeHasNoTabs(input_api, output_api))
    183   results.extend(
    184       input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
    185           input_api, output_api))
    186   results.append(_CheckCommitSubjectLength(input_api, output_api))
    187   results.append(_CheckDuplicateFiles(input_api, output_api))
    188 
    189   source_file_filter = lambda x: input_api.FilterSourceFile(
    190       x, files_to_skip=_GetFilesToSkip(input_api))
    191   results.extend(
    192       input_api.canned_checks.CheckLongLines(
    193           input_api,
    194           output_api,
    195           maxlen=_LIBWEBP_MAX_LINE_LENGTH,
    196           source_file_filter=source_file_filter))
    197 
    198   results.extend(
    199       input_api.canned_checks.CheckPatchFormatted(
    200           input_api,
    201           output_api,
    202           check_clang_format=False,
    203           check_python=True,
    204           result_factory=output_api.PresubmitError))
    205   results.extend(
    206       _RunCmdOnCheckedFiles(input_api, output_api, _RunManCmd,
    207                             _INCLUDE_MAN_FILES_ONLY))
    208   # Run pylint.
    209   results.extend(
    210       input_api.canned_checks.RunPylint(
    211           input_api,
    212           output_api,
    213           files_to_skip=_GetFilesToSkip(input_api),
    214           pylintrc=".pylintrc",
    215           version="2.7"))
    216 
    217   # Binaries shellcheck and shfmt are not installed in depot_tools.
    218   # Installation is needed
    219   try:
    220     subprocess2.communicate(["shellcheck", "--version"])
    221     results.extend(
    222         _RunCmdOnCheckedFiles(input_api, output_api, _RunShellCheckCmd,
    223                               _INCLUDE_BASH_FILES_ONLY))
    224     print("shfmt")
    225     subprocess2.communicate(["shfmt", "-version"])
    226     results.extend(
    227         _RunCmdOnCheckedFiles(input_api, output_api, _RunShfmtCheckCmd,
    228                               _INCLUDE_BASH_FILES_ONLY))
    229   except OSError as os_error:
    230     results.append(
    231         output_api.PresubmitPromptWarning(
    232             "%s\nPlease install missing binaries locally." % os_error.args[0]))
    233   return results
    234 
    235 
    236 def CheckChangeOnUpload(input_api, output_api):
    237   results = []
    238   results.extend(_CommonChecks(input_api, output_api))
    239   return results
    240 
    241 
    242 def CheckChangeOnCommit(input_api, output_api):
    243   results = []
    244   results.extend(_CommonChecks(input_api, output_api))
    245   return results