lintChanges.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #!/usr/bin/python
  2. from __future__ import print_function
  3. from __future__ import with_statement
  4. import sys
  5. import re
  6. import os
  7. KNOWN_GROUPS=set([
  8. "Minor bugfix",
  9. "Minor bugfixes",
  10. "Major bugfix",
  11. "Major bugfixes",
  12. "Minor feature",
  13. "Minor features",
  14. "Major feature",
  15. "Major features",
  16. "New system requirements",
  17. "Testing",
  18. "Documentation",
  19. "Code simplification and refactoring",
  20. "Removed features"])
  21. def lintfile(fname):
  22. have_warned = []
  23. def warn(s):
  24. if not have_warned:
  25. have_warned.append(1)
  26. print("{}:".format(fname))
  27. print("\t{}".format(s))
  28. m = re.search(r'(\d{3,})', os.path.basename(fname))
  29. if m:
  30. bugnum = m.group(1)
  31. else:
  32. bugnum = None
  33. with open(fname) as f:
  34. contents = f.read()
  35. if bugnum and bugnum not in contents:
  36. warn("bug number {} does not appear".format(bugnum))
  37. lines = contents.split("\n")
  38. isBug = ("bug" in lines[0] or "fix" in lines[0])
  39. m = re.match(r'^[ ]{2}o ([^\(:]*)([^:]*):', contents)
  40. if not m:
  41. warn("header not in format expected")
  42. elif m.group(1).strip() not in KNOWN_GROUPS:
  43. warn("Weird header: %r"%m.group(1))
  44. elif ( ("bugfix" in m.group(1) or "feature" in m.group(1)) and
  45. ("Removed" not in m.group(1)) and
  46. '(' not in m.group(2)):
  47. warn("Missing subcategory on %s"%m.group(1))
  48. contents = " ".join(contents.split())
  49. if re.search(r'\#\d{2,}', contents):
  50. warn("don't use a # before ticket numbers")
  51. if isBug and not re.search(r'(\d+)', contents):
  52. warn("bugfix does not mention a number")
  53. elif isBug and not re.search(r'Fixes ([a-z ]*)bug (\d+)', contents):
  54. warn("bugfix does not say 'Fixes bug XXX'")
  55. if re.search(r'[bB]ug (\d+)', contents):
  56. if not re.search(r'[Bb]ugfix on ', contents):
  57. warn("bugfix does not say 'bugfix on X.Y.Z'")
  58. elif not re.search('[fF]ixes ([a-z ]*)bug (\d+); bugfix on ',
  59. contents):
  60. warn("bugfix incant is not semicoloned")
  61. if __name__ == '__main__':
  62. for fname in sys.argv[1:]:
  63. if fname.endswith("~"):
  64. continue
  65. lintfile(fname)