check-package 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #!/usr/bin/env python
  2. # See utils/checkpackagelib/readme.txt before editing this file.
  3. from __future__ import print_function
  4. import argparse
  5. import inspect
  6. import re
  7. import sys
  8. import checkpackagelib.lib_config
  9. import checkpackagelib.lib_hash
  10. import checkpackagelib.lib_mk
  11. import checkpackagelib.lib_patch
  12. VERBOSE_LEVEL_TO_SHOW_IGNORED_FILES = 3
  13. flags = None # Command line arguments.
  14. def parse_args():
  15. parser = argparse.ArgumentParser()
  16. # Do not use argparse.FileType("r") here because only files with known
  17. # format will be open based on the filename.
  18. parser.add_argument("files", metavar="F", type=str, nargs="*",
  19. help="list of files")
  20. parser.add_argument("--manual-url", action="store",
  21. default="http://nightly.buildroot.org/",
  22. help="default: %(default)s")
  23. parser.add_argument("--verbose", "-v", action="count", default=0)
  24. # Now the debug options in the order they are processed.
  25. parser.add_argument("--include-only", dest="include_list", action="append",
  26. help="run only the specified functions (debug)")
  27. parser.add_argument("--exclude", dest="exclude_list", action="append",
  28. help="do not run the specified functions (debug)")
  29. parser.add_argument("--dry-run", action="store_true", help="print the "
  30. "functions that would be called for each file (debug)")
  31. return parser.parse_args()
  32. CONFIG_IN_FILENAME = re.compile("/Config\.\S*$")
  33. FILE_IS_FROM_A_PACKAGE = re.compile("package/[^/]*/")
  34. def get_lib_from_filename(fname):
  35. if FILE_IS_FROM_A_PACKAGE.search(fname) is None:
  36. return None
  37. if CONFIG_IN_FILENAME.search(fname):
  38. return checkpackagelib.lib_config
  39. if fname.endswith(".hash"):
  40. return checkpackagelib.lib_hash
  41. if fname.endswith(".mk"):
  42. return checkpackagelib.lib_mk
  43. if fname.endswith(".patch"):
  44. return checkpackagelib.lib_patch
  45. return None
  46. def is_a_check_function(m):
  47. if not inspect.isclass(m):
  48. return False
  49. # do not call the base class
  50. if m.__name__.startswith("_"):
  51. return False
  52. if flags.include_list and m.__name__ not in flags.include_list:
  53. return False
  54. if flags.exclude_list and m.__name__ in flags.exclude_list:
  55. return False
  56. return True
  57. def print_warnings(warnings):
  58. # Avoid the need to use 'return []' at the end of every check function.
  59. if warnings is None:
  60. return 0 # No warning generated.
  61. for level, message in enumerate(warnings):
  62. if flags.verbose >= level:
  63. print(message.replace("\t", "< tab >").rstrip())
  64. return 1 # One more warning to count.
  65. def check_file_using_lib(fname):
  66. # Count number of warnings generated and lines processed.
  67. nwarnings = 0
  68. nlines = 0
  69. lib = get_lib_from_filename(fname)
  70. if not lib:
  71. if flags.verbose >= VERBOSE_LEVEL_TO_SHOW_IGNORED_FILES:
  72. print("{}: ignored".format(fname))
  73. return nwarnings, nlines
  74. classes = inspect.getmembers(lib, is_a_check_function)
  75. if flags.dry_run:
  76. functions_to_run = [c[0] for c in classes]
  77. print("{}: would run: {}".format(fname, functions_to_run))
  78. return nwarnings, nlines
  79. objects = [c[1](fname, flags.manual_url) for c in classes]
  80. for cf in objects:
  81. nwarnings += print_warnings(cf.before())
  82. for lineno, text in enumerate(open(fname, "r").readlines()):
  83. nlines += 1
  84. for cf in objects:
  85. nwarnings += print_warnings(cf.check_line(lineno + 1, text))
  86. for cf in objects:
  87. nwarnings += print_warnings(cf.after())
  88. return nwarnings, nlines
  89. def __main__():
  90. global flags
  91. flags = parse_args()
  92. if len(flags.files) == 0:
  93. print("No files to check style")
  94. sys.exit(1)
  95. # Accumulate number of warnings generated and lines processed.
  96. total_warnings = 0
  97. total_lines = 0
  98. for fname in flags.files:
  99. nwarnings, nlines = check_file_using_lib(fname)
  100. total_warnings += nwarnings
  101. total_lines += nlines
  102. # The warning messages are printed to stdout and can be post-processed
  103. # (e.g. counted by 'wc'), so for stats use stderr. Wait all warnings are
  104. # printed, for the case there are many of them, before printing stats.
  105. sys.stdout.flush()
  106. print("{} lines processed".format(total_lines), file=sys.stderr)
  107. print("{} warnings generated".format(total_warnings), file=sys.stderr)
  108. if total_warnings > 0:
  109. sys.exit(1)
  110. __main__()