Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/python
      2 # -*- coding:utf-8 -*-
      3 # Copyright 2016 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 
     17 """Wrapper to run google-java-format to check for any malformatted changes."""
     18 
     19 from __future__ import print_function
     20 
     21 import argparse
     22 import os
     23 import sys
     24 from distutils.spawn import find_executable
     25 
     26 _path = os.path.realpath(__file__ + '/../..')
     27 if sys.path[0] != _path:
     28     sys.path.insert(0, _path)
     29 del _path
     30 
     31 # We have to import our local modules after the sys.path tweak.  We can't use
     32 # relative imports because this is an executable program, not a module.
     33 # pylint: disable=wrong-import-position
     34 import rh.shell
     35 import rh.utils
     36 
     37 
     38 def get_parser():
     39     """Return a command line parser."""
     40     parser = argparse.ArgumentParser(description=__doc__)
     41     parser.add_argument('--google-java-format', default='google-java-format',
     42                         help='The path of the google-java-format executable.')
     43     parser.add_argument('--google-java-format-diff',
     44                         default='google-java-format-diff.py',
     45                         help='The path of the google-java-format-diff script.')
     46     parser.add_argument('--fix', action='store_true',
     47                         help='Fix any formatting errors automatically.')
     48     parser.add_argument('--commit', type=str, default='HEAD',
     49                         help='Specify the commit to validate.')
     50     # While the formatter defaults to sorting imports, in the Android codebase,
     51     # the standard import order doesn't match the formatter's, so flip the
     52     # default to not sort imports, while letting callers override as desired.
     53     parser.add_argument('--sort-imports', action='store_true',
     54                         help='If true, imports will be sorted.')
     55     parser.add_argument('files', nargs='*',
     56                         help='If specified, only consider differences in '
     57                              'these files.')
     58     return parser
     59 
     60 
     61 def main(argv):
     62     """The main entry."""
     63     parser = get_parser()
     64     opts = parser.parse_args(argv)
     65 
     66     # google-java-format-diff.py looks for google-java-format in $PATH, so find
     67     # the parent dir up front and inject it into $PATH when launching it.
     68     # TODO: Pass the path in directly once this issue is resolved:
     69     # https://github.com/google/google-java-format/issues/108
     70     format_path = find_executable(opts.google_java_format)
     71     if not format_path:
     72         print('Unable to find google-java-format at %s' %
     73               opts.google_java_format)
     74         return 1
     75 
     76     extra_env = {
     77         'PATH': '%s%s%s' % (os.path.dirname(format_path),
     78                             os.pathsep,
     79                             os.environ['PATH'])
     80     }
     81 
     82     # TODO: Delegate to the tool once this issue is resolved:
     83     # https://github.com/google/google-java-format/issues/107
     84     diff_cmd = ['git', 'diff', '--no-ext-diff', '-U0', '%s^!' % opts.commit]
     85     diff_cmd.extend(['--'] + opts.files)
     86     diff = rh.utils.run_command(diff_cmd, capture_output=True).output
     87 
     88     cmd = [opts.google_java_format_diff, '-p1', '--aosp']
     89     if opts.fix:
     90         cmd.extend(['-i'])
     91     if not opts.sort_imports:
     92         cmd.extend(['--skip-sorting-imports'])
     93 
     94     stdout = rh.utils.run_command(cmd,
     95                                   input=diff,
     96                                   capture_output=True,
     97                                   extra_env=extra_env).output
     98     if stdout != '':
     99         print('One or more files in your commit have Java formatting errors.')
    100         print('You can run `%s --fix %s` to fix this' %
    101               (sys.argv[0], rh.shell.cmd_to_str(argv)))
    102         return 1
    103 
    104     return 0
    105 
    106 
    107 if __name__ == '__main__':
    108     sys.exit(main(sys.argv[1:]))
    109