sortChanges.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #!/usr/bin/env python
  2. # Copyright (c) 2014-2019, The Tor Project, Inc.
  3. # See LICENSE for licensing information
  4. """This script sorts a bunch of changes files listed on its command
  5. line into roughly the order in which they should appear in the
  6. changelog.
  7. """
  8. # Future imports for Python 2.7, mandatory in 3.0
  9. from __future__ import division
  10. from __future__ import print_function
  11. from __future__ import unicode_literals
  12. import re
  13. import sys
  14. def fetch(fn):
  15. with open(fn) as f:
  16. s = f.read()
  17. s = "%s\n" % s.rstrip()
  18. return s
  19. CSR='Code simplification and refactoring'
  20. REPLACEMENTS = {
  21. # plurals
  22. 'Minor bugfix' : 'Minor bugfixes',
  23. 'Major bugfix' : 'Major bugfixes',
  24. 'Minor feature' : 'Minor features',
  25. 'Major feature' : 'Major features',
  26. 'Removed feature' : 'Removed features',
  27. 'Code simplification and refactorings' : CSR,
  28. 'Code simplifications and refactoring' : CSR,
  29. 'Code simplifications and refactorings' : CSR,
  30. # wrong words
  31. 'Minor fix' : 'Minor bugfixes',
  32. 'Major fix' : 'Major bugfixes',
  33. 'Minor fixes' : 'Minor bugfixes',
  34. 'Major fixes' : 'Major bugfixes',
  35. 'Minor enhancement' : 'Minor features',
  36. 'Minor enhancements' : 'Minor features',
  37. 'Major enhancement' : 'Major features',
  38. 'Major enhancements' : 'Major features',
  39. }
  40. def score(s,fname=None):
  41. m = re.match(r'^ +o ([^\n]*)\n(.*)', s, re.M|re.S)
  42. if not m:
  43. print("Can't score %r from %s"%(s,fname), file=sys.stderr)
  44. heading = m.group(1)
  45. heading = REPLACEMENTS.get(heading, heading)
  46. lw = m.group(1).lower()
  47. if lw.startswith("major feature"):
  48. score = 0
  49. elif lw.startswith("major bug"):
  50. score = 1
  51. elif lw.startswith("major"):
  52. score = 2
  53. elif lw.startswith("minor feature"):
  54. score = 10
  55. elif lw.startswith("minor bug"):
  56. score = 11
  57. elif lw.startswith("minor"):
  58. score = 12
  59. else:
  60. score = 100
  61. return (score, lw, heading, m.group(2))
  62. def splitChanges(s):
  63. this_entry = []
  64. for line in s.split("\n"):
  65. if line.strip() == "":
  66. continue
  67. if re.match(r" +o ", line):
  68. if len(this_entry) > 2:
  69. yield "".join(this_entry)
  70. curHeader = line
  71. this_entry = [ curHeader, "\n" ]
  72. continue
  73. elif re.match(r" +- ", line):
  74. if len(this_entry) > 2:
  75. yield "".join(this_entry)
  76. this_entry = [ curHeader, "\n" ]
  77. this_entry.append(line)
  78. this_entry.append("\n")
  79. if len(this_entry) > 2:
  80. yield "".join(this_entry)
  81. changes = []
  82. for fn in sys.argv[1:]:
  83. if fn.endswith('~'):
  84. continue
  85. for change in splitChanges(fetch(fn)):
  86. changes.append(score(change,fn))
  87. changes.sort()
  88. last_lw = "this is not a header"
  89. for _, lw, header, rest in changes:
  90. if lw == last_lw:
  91. print(rest, end="")
  92. else:
  93. print()
  94. print(" o",header)
  95. print(rest, end="")
  96. last_lw = lw