cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#! /usr/bin/python
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# CDDL HEADER START
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# The contents of this file are subject to the terms of the
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Common Development and Distribution License (the "License").
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# You may not use this file except in compliance with the License.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# or http://www.opensolaris.org/os/licensing.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# See the License for the specific language governing permissions
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# and limitations under the License.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# When distributing Covered Code, include this CDDL HEADER in each
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# If applicable, add the following below this CDDL HEADER, with the
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# fields enclosed by brackets "[]" replaced with your own identifying
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# information: Portions Copyright [yyyy] [name of copyright owner]
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# CDDL HEADER END
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
41a5f560d7437bb41abade5dce25dc6875da156aMark J. Nelson# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Use is subject to license terms.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe# Copyright 2007, 2010 Richard Lowe
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Check delta comments:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# - Have the correct form.
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe# - Have a synopsis matching that of the bug
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# - Appear only once.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsonimport re, sys
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowefrom onbld.Checks.DbLookups import BugDB
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowebugre = re.compile(r'^(\d{2,7}) (.*)$')
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsondef isBug(comment):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson return bugre.match(comment)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowedef comchk(comments, check_db=True, output=sys.stderr):
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein '''Validate checkin comments against ON standards.
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein Comments must be a list of one-line comments, with no trailing
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein newline.
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe If check_db is True (the default), validate bug synopses against the
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe databases.
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein Error messages intended for the user are written to output,
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein which defaults to stderr
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein '''
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe bugnospcre = re.compile(r'^(\d{2,7})([^ ].*)')
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe ignorere = re.compile(r'^(' +
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe r'Portions contributed by|' +
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe r'Contributed by|' +
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe r'Reviewed[ -]by|' +
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe r'Approved[ -]by|' +
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe r'back[ -]?out)' +
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe r'[: ]')
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson errors = { 'bugnospc': [],
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson 'mutant': [],
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson 'dup': [],
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson 'nomatch': [],
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson 'nonexistent': [] }
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson bugs = {}
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe ret = 0
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe blanks = False
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson for com in comments:
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein # Our input must be newline-free, comments are line-wise.
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein if com.find('\n') != -1:
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein raise ValueError("newline in comment '%s'" % com)
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Ignore valid comments we can't check
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if ignorere.search(com):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not com or com.isspace():
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe blanks = True
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson match = bugre.search(com)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if match:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if match.group(1) not in bugs:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson bugs[match.group(1)] = []
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson bugs[match.group(1)].append(match.group(2))
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Bugs missing a space after the ID are still bugs
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # for the purposes of the duplicate ID and synopsis
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # checks.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson match = bugnospcre.search(com)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if match:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if match.group(1) not in bugs:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson bugs[match.group(1)] = []
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson bugs[match.group(1)].append(match.group(2))
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson errors['bugnospc'].append(com)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Anything else is bogus
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson errors['mutant'].append(com)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if len(bugs) > 0 and check_db:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson bugdb = BugDB()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson results = bugdb.lookup(bugs.keys())
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson for crid, insts in bugs.iteritems():
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if len(insts) > 1:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson errors['dup'].append(crid)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not check_db:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if crid not in results:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson errors['nonexistent'].append(crid)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe #
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe # For each synopsis, compare the real synopsis with
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe # that in the comments, allowing for possible '(fix
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe # stuff)'-like trailing text
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson for entered in insts:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson synopsis = results[crid]["synopsis"]
ef62fef3e05c4489eec0a36d605736821d778929Richard Lowe if not re.search(r'^' + re.escape(synopsis) +
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein r'( \([^)]+\))?$', entered):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson errors['nomatch'].append([crid, synopsis,
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein entered])
c08a253caa7a003446506d7c1d6da5345e61aebeJohn Sonnenschein
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if blanks:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson output.write("WARNING: Blank line(s) in comments\n")
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if errors['dup']:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson output.write("These IDs appear more than once in your "
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson "comments:\n")
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson for err in errors['dup']:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson output.write(" %s\n" % err)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if errors['bugnospc']:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson output.write("These bugs are missing a single space following "
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson "the ID:\n")
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson for com in errors['bugnospc']:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson output.write(" %s\n" % com)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if errors['mutant']:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe output.write("These comments are not valid bugs:\n")
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson for com in errors['mutant']:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson output.write(" %s\n" % com)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if errors['nonexistent']:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe output.write("These bugs were not found in the databases:\n")
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson for id in errors['nonexistent']:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson output.write(" %s\n" % id)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if errors['nomatch']:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe output.write("These bug synopses don't match "
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson "the database entries:\n")
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson for err in errors['nomatch']:
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe output.write("Synopsis of %s is wrong:\n" % err[0])
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson output.write(" should be: '%s'\n" % err[1])
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson output.write(" is: '%s'\n" % err[2])
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson return ret