|
@@ -12,6 +12,7 @@
|
|
|
import os
|
|
|
import re
|
|
|
import sys
|
|
|
+import optparse
|
|
|
|
|
|
# ==============================
|
|
|
# Oh, look! It's a cruddy approximation to Knuth's elegant text wrapping
|
|
@@ -186,8 +187,49 @@ def body_parser(line):
|
|
|
else:
|
|
|
print "Weird line %r"%line
|
|
|
|
|
|
+def clean_head(head):
|
|
|
+ return head
|
|
|
+
|
|
|
+def head_score(s):
|
|
|
+ m = re.match(r'^ +o (.*)', s)
|
|
|
+ if not m:
|
|
|
+ print >>sys.stderr, "Can't score %r"%s
|
|
|
+ return 99999
|
|
|
+ lw = m.group(1).lower()
|
|
|
+ if lw.startswith("security") and "feature" not in lw:
|
|
|
+ score = -300
|
|
|
+ elif lw.startswith("deprecated versions"):
|
|
|
+ score = -200
|
|
|
+ elif "build require" in lw:
|
|
|
+ score = -100
|
|
|
+ elif lw.startswith("major feature"):
|
|
|
+ score = 00
|
|
|
+ elif lw.startswith("major bug"):
|
|
|
+ score = 50
|
|
|
+ elif lw.startswith("major"):
|
|
|
+ score = 70
|
|
|
+ elif lw.startswith("minor feature"):
|
|
|
+ score = 200
|
|
|
+ elif lw.startswith("minor bug"):
|
|
|
+ score = 250
|
|
|
+ elif lw.startswith("minor"):
|
|
|
+ score = 270
|
|
|
+ else:
|
|
|
+ score = 1000
|
|
|
+
|
|
|
+ if 'secur' in lw:
|
|
|
+ score -= 2
|
|
|
+
|
|
|
+ if "(other)" in lw:
|
|
|
+ score += 2
|
|
|
+
|
|
|
+ if '(' not in lw:
|
|
|
+ score -= 1
|
|
|
+
|
|
|
+ return score
|
|
|
+
|
|
|
class ChangeLog(object):
|
|
|
- def __init__(self):
|
|
|
+ def __init__(self, wrapText=True):
|
|
|
self.prehead = []
|
|
|
self.mainhead = None
|
|
|
self.headtext = []
|
|
@@ -195,6 +237,7 @@ class ChangeLog(object):
|
|
|
self.sections = []
|
|
|
self.cursection = None
|
|
|
self.lineno = 0
|
|
|
+ self.wrapText = wrapText
|
|
|
|
|
|
def addLine(self, tp, line):
|
|
|
self.lineno += 1
|
|
@@ -249,6 +292,11 @@ class ChangeLog(object):
|
|
|
self.lint_item(item_line, grafs, head_type)
|
|
|
|
|
|
def dumpGraf(self,par,indent1,indent2=-1):
|
|
|
+ if not self.wrapText:
|
|
|
+ for line in par:
|
|
|
+ print line
|
|
|
+ return
|
|
|
+
|
|
|
if indent2 == -1:
|
|
|
indent2 = indent1
|
|
|
text = " ".join(re.sub(r'\s+', ' ', line.strip()) for line in par)
|
|
@@ -258,6 +306,22 @@ class ChangeLog(object):
|
|
|
initial_indent=" "*indent1,
|
|
|
subsequent_indent=" "*indent2))
|
|
|
|
|
|
+ def collateAndSortSections(self):
|
|
|
+ heads = []
|
|
|
+ sectionsByHead = { }
|
|
|
+ for _, head, items in self.sections:
|
|
|
+ head = clean_head(head)
|
|
|
+ try:
|
|
|
+ s = sectionsByHead[head]
|
|
|
+ except KeyError:
|
|
|
+ s = sectionsByHead[head] = []
|
|
|
+ heads.append( (head_score(head), head, s) )
|
|
|
+
|
|
|
+ s.extend(items)
|
|
|
+
|
|
|
+ heads.sort()
|
|
|
+ self.sections = [ (0, head, items) for _,head,items in heads ]
|
|
|
+
|
|
|
def dump(self):
|
|
|
if self.prehead:
|
|
|
self.dumpGraf(self.prehead, 0)
|
|
@@ -279,20 +343,36 @@ class ChangeLog(object):
|
|
|
print
|
|
|
print
|
|
|
|
|
|
-CL = ChangeLog()
|
|
|
-parser = head_parser
|
|
|
-
|
|
|
-if len(sys.argv) == 1:
|
|
|
+op = optparse.OptionParser(usage="usage: %prog [options] [filename]")
|
|
|
+op.add_option('-W', '--no-wrap', action='store_false',
|
|
|
+ dest='wrapText', default=True,
|
|
|
+ help='Do not re-wrap paragraphs')
|
|
|
+op.add_option('-S', '--no-sort', action='store_false',
|
|
|
+ dest='sort', default=True,
|
|
|
+ help='Do not sort or collate sections')
|
|
|
+op.add_option('-o', '--output', dest='output',
|
|
|
+ default=None, metavar='FILE', help="write output to FILE")
|
|
|
+
|
|
|
+options,args = op.parse_args()
|
|
|
+
|
|
|
+if len(args) > 1:
|
|
|
+ op.error("Too many arguments")
|
|
|
+elif len(args) == 0:
|
|
|
fname = 'ChangeLog'
|
|
|
else:
|
|
|
- fname = sys.argv[1]
|
|
|
+ fname = args[0]
|
|
|
|
|
|
-fname_new = fname+".new"
|
|
|
+if options.output == None:
|
|
|
+ options.output = fname
|
|
|
|
|
|
-sys.stdin = open(fname, 'r')
|
|
|
+if fname != '-':
|
|
|
+ sys.stdin = open(fname, 'r')
|
|
|
|
|
|
nextline = None
|
|
|
|
|
|
+CL = ChangeLog(wrapText=options.wrapText)
|
|
|
+parser = head_parser
|
|
|
+
|
|
|
for line in sys.stdin:
|
|
|
line = line.rstrip()
|
|
|
tp = parser(line)
|
|
@@ -307,7 +387,15 @@ for line in sys.stdin:
|
|
|
|
|
|
CL.lint()
|
|
|
|
|
|
-sys.stdout = open(fname_new, 'w')
|
|
|
+if options.output != '-':
|
|
|
+ fname_new = options.output+".new"
|
|
|
+ fname_out = options.output
|
|
|
+ sys.stdout = open(fname_new, 'w')
|
|
|
+else:
|
|
|
+ fname_new = fname_out = None
|
|
|
+
|
|
|
+if options.sort:
|
|
|
+ CL.collateAndSortSections()
|
|
|
|
|
|
CL.dump()
|
|
|
|
|
@@ -317,4 +405,5 @@ if nextline is not None:
|
|
|
for line in sys.stdin:
|
|
|
sys.stdout.write(line)
|
|
|
|
|
|
-os.rename(fname_new, fname)
|
|
|
+if fname_new is not None:
|
|
|
+ os.rename(fname_new, fname_out)
|