tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

sortChanges.py (3030B)


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