Make check-spaces part of the standard "make check" process

To do this, we had to make sure it passes when the changes directory
is empty.  I also tried to improve the quality of the output, and
fix some false-positive cases.  Let's see how this goes!

Closes ticket 23564.
This commit is contained in:
Nick Mathewson 2017-09-19 10:10:38 -04:00
parent f395f41868
commit 3c04c8317f
3 changed files with 51 additions and 17 deletions

View File

@ -96,7 +96,7 @@ doxygen:
test: all test: all
$(top_builddir)/src/test/test $(top_builddir)/src/test/test
check-local: check-spaces check-local: check-spaces check-changes
need-chutney-path: need-chutney-path:
@if test ! -d "$$CHUTNEY_PATH"; then \ @if test ! -d "$$CHUTNEY_PATH"; then \
@ -217,7 +217,7 @@ check-logs:
.PHONY: check-changes .PHONY: check-changes
check-changes: check-changes:
@if test -d "$(top_srcdir)/changes"; then \ @if test -d "$(top_srcdir)/changes"; then \
$(PYTHON) $(top_srcdir)/scripts/maint/lintChanges.py $(top_srcdir)/changes/*; \ $(PYTHON) $(top_srcdir)/scripts/maint/lintChanges.py $(top_srcdir)/changes; \
fi fi
.PHONY: update-versions .PHONY: update-versions

View File

@ -20,8 +20,19 @@ KNOWN_GROUPS = set([
"Testing", "Testing",
"Documentation", "Documentation",
"Code simplification and refactoring", "Code simplification and refactoring",
"Removed features"]) "Removed features",
"Deprecated features"])
NEEDS_SUBCATEGORIES = set([
"Minor bugfix",
"Minor bugfixes",
"Major bugfix",
"Major bugfixes",
"Minor feature",
"Minor features",
"Major feature",
"Major features",
])
def lintfile(fname): def lintfile(fname):
have_warned = [] have_warned = []
@ -46,13 +57,11 @@ def lintfile(fname):
m = re.match(r'^[ ]{2}o ([^\(:]*)([^:]*):', contents) m = re.match(r'^[ ]{2}o ([^\(:]*)([^:]*):', contents)
if not m: 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: elif m.group(1).strip() not in KNOWN_GROUPS:
warn("Weird header: %r" % m.group(1)) warn("Unrecognized header: %r" % m.group(1))
elif (("bugfix" in m.group(1) or "feature" in m.group(1)) and elif (m.group(1) in NEEDS_SUBCATEGORIES and '(' not in m.group(2)):
("Removed" not in m.group(1)) and warn("Missing subcategory on %r" % m.group(1))
'(' not in m.group(2)):
warn("Missing subcategory on %s" % m.group(1))
if m: if m:
isBug = ("bug" in m.group(1).lower() or "fix" in m.group(1).lower()) isBug = ("bug" in m.group(1).lower() or "fix" in m.group(1).lower())
@ -62,25 +71,46 @@ def lintfile(fname):
contents = " ".join(contents.split()) contents = " ".join(contents.split())
if re.search(r'\#\d{2,}', contents): 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): if isBug and not re.search(r'(\d+)', contents):
warn("bugfix does not mention a number") warn("Ticket marked as bugfix, but does not mention a number.")
elif isBug and not re.search(r'Fixes ([a-z ]*)bug (\d+)', contents): 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 say 'Fixes bug XXX'")
if re.search(r'[bB]ug (\d+)', contents): if re.search(r'[bB]ug (\d+)', contents):
if not re.search(r'[Bb]ugfix on ', contents): if not re.search(r'[Bb]ugfix on ', contents):
warn("bugfix does not say 'bugfix on X.Y.Z'") warn("Bugfix does not say 'bugfix on X.Y.Z'")
elif not re.search('[fF]ixes ([a-z ]*)bug (\d+); bugfix on ', elif not re.search('[fF]ixes ([a-z ]*)bug (\d+); bugfix on ',
contents): 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): elif re.search('tor-([0-9]+)', contents):
warn("do not prefix versions with 'tor-'") 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__': if __name__ == '__main__':
for fname in sys.argv[1:]: problems = 0
for fname in files(sys.argv[1:]):
if fname.endswith("~"): if fname.endswith("~"):
continue continue
lintfile(fname) if lintfile(fname):
problems += 1
if problems:
sys.exit(1)
else:
sys.exit(0)

4
ticket23564 Normal file
View File

@ -0,0 +1,4 @@
o Minor features (build):
- The "check-changes" feature is now part of the "make check"
tests; we'll use it to try to prevent misformed changes files
from accumulating. Closes ticket 23564.