aboutsummaryrefslogtreecommitdiff
path: root/scripts/maint/lintChanges.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/maint/lintChanges.py')
-rwxr-xr-xscripts/maint/lintChanges.py72
1 files changed, 52 insertions, 20 deletions
diff --git a/scripts/maint/lintChanges.py b/scripts/maint/lintChanges.py
index b63a4eb3a1..d5b8fcae5c 100755
--- a/scripts/maint/lintChanges.py
+++ b/scripts/maint/lintChanges.py
@@ -7,7 +7,7 @@ import re
import os
-KNOWN_GROUPS=set([
+KNOWN_GROUPS = set([
"Minor bugfix",
"Minor bugfixes",
"Major bugfix",
@@ -20,7 +20,20 @@ KNOWN_GROUPS=set([
"Testing",
"Documentation",
"Code simplification and refactoring",
- "Removed features"])
+ "Removed features",
+ "Deprecated features",
+ "Directory authority changes"])
+
+NEEDS_SUBCATEGORIES = set([
+ "Minor bugfix",
+ "Minor bugfixes",
+ "Major bugfix",
+ "Major bugfixes",
+ "Minor feature",
+ "Minor features",
+ "Major feature",
+ "Major features",
+ ])
def lintfile(fname):
have_warned = []
@@ -43,17 +56,13 @@ def lintfile(fname):
if bugnum and bugnum not in contents:
warn("bug number {} does not appear".format(bugnum))
- lines = contents.split("\n")
-
m = re.match(r'^[ ]{2}o ([^\(:]*)([^:]*):', contents)
if not m:
- warn("header not in format expected")
+ warn("Header not in format expected. (' o Foo:' or ' o Foo (Bar):')")
elif m.group(1).strip() not in KNOWN_GROUPS:
- warn("Weird header: %r"%m.group(1))
- elif ( ("bugfix" in m.group(1) or "feature" in m.group(1)) and
- ("Removed" not in m.group(1)) and
- '(' not in m.group(2)):
- warn("Missing subcategory on %s"%m.group(1))
+ warn("Unrecognized header: %r" % m.group(1))
+ elif (m.group(1) in NEEDS_SUBCATEGORIES and '(' not in m.group(2)):
+ warn("Missing subcategory on %r" % m.group(1))
if m:
isBug = ("bug" in m.group(1).lower() or "fix" in m.group(1).lower())
@@ -63,23 +72,46 @@ def lintfile(fname):
contents = " ".join(contents.split())
if re.search(r'\#\d{2,}', contents):
- warn("don't use a # before ticket numbers")
+ warn("Don't use a # before ticket numbers. ('bug 1234' not '#1234')")
if isBug and not re.search(r'(\d+)', contents):
- warn("bugfix does not mention a number")
- elif isBug and not re.search(r'Fixes ([a-z ]*)bug (\d+)', contents):
- warn("bugfix does not say 'Fixes bug XXX'")
+ warn("Ticket marked as bugfix, but does not mention a number.")
+ elif isBug and not re.search(r'Fixes ([a-z ]*)bugs? (\d+)', contents):
+ warn("Ticket marked as bugfix, but does not say 'Fixes bug XXX'")
if re.search(r'[bB]ug (\d+)', contents):
if not re.search(r'[Bb]ugfix on ', contents):
- warn("bugfix does not say 'bugfix on X.Y.Z'")
- elif not re.search('[fF]ixes ([a-z ]*)bug (\d+); bugfix on ',
+ warn("Bugfix does not say 'bugfix on X.Y.Z'")
+ elif not re.search('[fF]ixes ([a-z ]*)bugs? (\d+)((, \d+)* and \d+)?; bugfix on ',
contents):
- warn("bugfix incant is not semicoloned")
-
+ warn("Bugfix does not say 'Fixes bug X; bugfix on Y'")
+ elif re.search('tor-([0-9]+)', contents):
+ warn("Do not prefix versions with 'tor-'. ('0.1.2', not 'tor-0.1.2'.)")
+
+ return have_warned != []
+
+def files(args):
+ """Walk through the arguments: for directories, yield their contents;
+ for files, just yield the files. Only search one level deep, because
+ that's how the changes directory is laid out."""
+ for f in args:
+ if os.path.isdir(f):
+ for item in os.listdir(f):
+ if item.startswith("."): #ignore dotfiles
+ continue
+ yield os.path.join(f, item)
+ else:
+ yield f
if __name__ == '__main__':
- for fname in sys.argv[1:]:
+ problems = 0
+ for fname in files(sys.argv[1:]):
if fname.endswith("~"):
continue
- lintfile(fname)
+ if lintfile(fname):
+ problems += 1
+
+ if problems:
+ sys.exit(1)
+ else:
+ sys.exit(0)