xref: /onnv-gate/usr/src/tools/onbld/Checks/Comments.py (revision 8042:54a2500a85d8)
17078Smjnelson#! /usr/bin/python
27078Smjnelson#
37078Smjnelson# CDDL HEADER START
47078Smjnelson#
57078Smjnelson# The contents of this file are subject to the terms of the
67078Smjnelson# Common Development and Distribution License (the "License").
77078Smjnelson# You may not use this file except in compliance with the License.
87078Smjnelson#
97078Smjnelson# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107078Smjnelson# or http://www.opensolaris.org/os/licensing.
117078Smjnelson# See the License for the specific language governing permissions
127078Smjnelson# and limitations under the License.
137078Smjnelson#
147078Smjnelson# When distributing Covered Code, include this CDDL HEADER in each
157078Smjnelson# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167078Smjnelson# If applicable, add the following below this CDDL HEADER, with the
177078Smjnelson# fields enclosed by brackets "[]" replaced with your own identifying
187078Smjnelson# information: Portions Copyright [yyyy] [name of copyright owner]
197078Smjnelson#
207078Smjnelson# CDDL HEADER END
217078Smjnelson#
227078Smjnelson
237078Smjnelson#
247078Smjnelson# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
257078Smjnelson# Use is subject to license terms.
267078Smjnelson#
277078Smjnelson
287078Smjnelson#
297078Smjnelson# Check delta comments:
307078Smjnelson# 	- Have the correct form.
317078Smjnelson# 	- Have a synopsis matching that of the CR or ARC case.
327078Smjnelson# 	- Appear only once.
337078Smjnelson#
347078Smjnelson
357078Smjnelsonimport re, sys
367078Smjnelsonfrom onbld.Checks.DbLookups import BugDB, ARC
377078Smjnelson
387078Smjnelsonarcre = re.compile(r'^([A-Z][A-Z]*ARC[/ \t][12]\d{3}/\d{3}) (.*)$')
397078Smjnelsonbugre = re.compile(r'^(\d{7}) (.*)$')
407711Srichlowe@richlowe.net
417078Smjnelsondef isARC(comment):
427078Smjnelson	return arcre.match(comment)
437078Smjnelson
447078Smjnelsondef isBug(comment):
457078Smjnelson	return bugre.match(comment)
467078Smjnelson
477078Smjnelson#
487078Smjnelson# Translate any acceptable case number format into "<ARC> <YEAR>/<NUM>"
497078Smjnelson# format.
507078Smjnelson#
517078Smjnelsondef normalize_arc(caseid):
527078Smjnelson	return re.sub(r'^([A-Z][A-Z]*ARC)[/ \t]', '\\1 ', caseid)
537078Smjnelson
547078Smjnelsondef comchk(comments, check_db=True, output=sys.stderr):
55*8042SJohn.Sonnenschein@Sun.COM	'''Validate checkin comments against ON standards.
567711Srichlowe@richlowe.net
57*8042SJohn.Sonnenschein@Sun.COM	Comments must be a list of one-line comments, with no trailing
58*8042SJohn.Sonnenschein@Sun.COM	newline.
59*8042SJohn.Sonnenschein@Sun.COM
60*8042SJohn.Sonnenschein@Sun.COM	If check_db is True (the default), validate CR and ARC
61*8042SJohn.Sonnenschein@Sun.COM	synopses against the databases.
627711Srichlowe@richlowe.net
63*8042SJohn.Sonnenschein@Sun.COM	Error messages intended for the user are written to output,
64*8042SJohn.Sonnenschein@Sun.COM	which defaults to stderr
65*8042SJohn.Sonnenschein@Sun.COM	'''
667078Smjnelson	bugnospcre = re.compile(r'^(\d{7})([^ ].*)')
677321SJohn.Beck@Sun.COM	ignorere = re.compile(r'^(Portions contributed by |Contributed by |back[ -]?out )')
687078Smjnelson
697078Smjnelson	errors = { 'bugnospc': [],
707078Smjnelson		   'mutant': [],
717078Smjnelson		   'dup': [],
727078Smjnelson		   'nomatch': [],
737078Smjnelson		   'nonexistent': [] }
747078Smjnelson	bugs = {}
757078Smjnelson	arcs = {}
767711Srichlowe@richlowe.net	ret = 0
777711Srichlowe@richlowe.net	blanks = False
787078Smjnelson
797078Smjnelson	for com in comments:
80*8042SJohn.Sonnenschein@Sun.COM		# Our input must be newline-free, comments are line-wise.
81*8042SJohn.Sonnenschein@Sun.COM		if com.find('\n') != -1:
82*8042SJohn.Sonnenschein@Sun.COM			raise ValueError("newline in comment '%s'" % com)
83*8042SJohn.Sonnenschein@Sun.COM
847078Smjnelson		# Ignore valid comments we can't check
857078Smjnelson		if ignorere.search(com):
867078Smjnelson			continue
877078Smjnelson
887078Smjnelson		if not com or com.isspace():
897711Srichlowe@richlowe.net			blanks = True
907078Smjnelson			continue
917078Smjnelson
927078Smjnelson		match = bugre.search(com)
937078Smjnelson		if match:
947078Smjnelson			if match.group(1) not in bugs:
957078Smjnelson				bugs[match.group(1)] = []
967078Smjnelson			bugs[match.group(1)].append(match.group(2))
977078Smjnelson			continue
987078Smjnelson
997078Smjnelson		#
1007078Smjnelson		# Bugs missing a space after the ID are still bugs
1017078Smjnelson		# for the purposes of the duplicate ID and synopsis
1027078Smjnelson		# checks.
1037078Smjnelson		#
1047078Smjnelson		match = bugnospcre.search(com)
1057078Smjnelson		if match:
1067078Smjnelson			if match.group(1) not in bugs:
1077078Smjnelson				bugs[match.group(1)] = []
1087078Smjnelson			bugs[match.group(1)].append(match.group(2))
1097078Smjnelson			errors['bugnospc'].append(com)
1107078Smjnelson			continue
1117078Smjnelson
1127078Smjnelson		# ARC case
1137078Smjnelson		match = arcre.search(com)
1147078Smjnelson		if match:
115*8042SJohn.Sonnenschein@Sun.COM			arc, case = re.split('[/ \t]', match.group(1), 1)
116*8042SJohn.Sonnenschein@Sun.COM			arcs.setdefault((arc, case), []).append(match.group(2))
1177078Smjnelson			continue
1187078Smjnelson
1197078Smjnelson		# Anything else is bogus
1207078Smjnelson		errors['mutant'].append(com)
1217078Smjnelson
1227078Smjnelson	if len(bugs) > 0 and check_db:
1237078Smjnelson		bugdb = BugDB()
1247078Smjnelson		results = bugdb.lookup(bugs.keys())
1257078Smjnelson
1267078Smjnelson	for crid, insts in bugs.iteritems():
1277078Smjnelson		if len(insts) > 1:
1287078Smjnelson			errors['dup'].append(crid)
1297078Smjnelson
1307078Smjnelson		if not check_db:
1317078Smjnelson			continue
1327078Smjnelson
1337078Smjnelson		if crid not in results:
1347078Smjnelson			errors['nonexistent'].append(crid)
1357078Smjnelson			continue
1367078Smjnelson
1377711Srichlowe@richlowe.net		#
1387711Srichlowe@richlowe.net		# For each synopsis, compare the real synopsis with
1397711Srichlowe@richlowe.net		# that in the comments, allowing for possible '(fix
1407711Srichlowe@richlowe.net		# stuff)'-like trailing text
1417711Srichlowe@richlowe.net		#
1427078Smjnelson		for entered in insts:
1437078Smjnelson			synopsis = results[crid]["synopsis"]
1447711Srichlowe@richlowe.net			if not re.search(r'^' + re.escape(synopsis) +
145*8042SJohn.Sonnenschein@Sun.COM					r'( \([^)]+\))?$', entered):
1467078Smjnelson				errors['nomatch'].append([crid, synopsis,
147*8042SJohn.Sonnenschein@Sun.COM							entered])
148*8042SJohn.Sonnenschein@Sun.COM
149*8042SJohn.Sonnenschein@Sun.COM	if check_db:
150*8042SJohn.Sonnenschein@Sun.COM		valid = ARC(arcs.keys())
1517078Smjnelson
1527078Smjnelson	for case, insts in arcs.iteritems():
1537078Smjnelson		if len(insts) > 1:
154*8042SJohn.Sonnenschein@Sun.COM			errors['dup'].append(' '.join(case))
1557078Smjnelson
156*8042SJohn.Sonnenschein@Sun.COM 		if not check_db:
1577078Smjnelson			continue
158*8042SJohn.Sonnenschein@Sun.COM
159*8042SJohn.Sonnenschein@Sun.COM		if not case in valid:
160*8042SJohn.Sonnenschein@Sun.COM			errors['nonexistent'].append(' '.join(case))
161*8042SJohn.Sonnenschein@Sun.COM			continue
1627078Smjnelson		#
1637078Smjnelson		# The opensolaris.org ARC interfaces only give us the
1647078Smjnelson		# first 40 characters of the case name, so we must limit
1657078Smjnelson		# our checking similarly.
1667078Smjnelson		#
1677078Smjnelson		# We first try a direct match between the actual case name
1687078Smjnelson		# and the entered comment.  If that fails we remove a possible
1697078Smjnelson		# trailing (fix nit)-type comment, and re-try.
1707078Smjnelson		#
1717078Smjnelson		for entered in insts:
172*8042SJohn.Sonnenschein@Sun.COM			if entered[0:40] == valid[case]:
173*8042SJohn.Sonnenschein@Sun.COM				break
1747078Smjnelson			else:
1757711Srichlowe@richlowe.net				# Try again with trailing (fix ...) removed.
1767078Smjnelson				dbcom = re.sub(r' \([^)]+\)$', '', entered)
177*8042SJohn.Sonnenschein@Sun.COM				if dbcom[0:40] != valid[case]:
178*8042SJohn.Sonnenschein@Sun.COM					errors['nomatch'].append(
179*8042SJohn.Sonnenschein@Sun.COM						[' '.join(case), valid[case],
180*8042SJohn.Sonnenschein@Sun.COM						 entered])
1817078Smjnelson
1827078Smjnelson	if blanks:
1837078Smjnelson		output.write("WARNING: Blank line(s) in comments\n")
1847078Smjnelson		ret = 1
1857078Smjnelson
1867078Smjnelson	if errors['dup']:
1877078Smjnelson		ret = 1
1887078Smjnelson		output.write("These IDs appear more than once in your "
1897078Smjnelson			     "comments:\n")
1907078Smjnelson		for err in errors['dup']:
1917078Smjnelson			output.write("  %s\n" % err)
1927078Smjnelson
1937078Smjnelson	if errors['bugnospc']:
1947078Smjnelson		ret = 1
1957078Smjnelson		output.write("These bugs are missing a single space following "
1967078Smjnelson			     "the ID:\n")
1977078Smjnelson		for com in errors['bugnospc']:
1987078Smjnelson			output.write("  %s\n" % com)
1997078Smjnelson
2007078Smjnelson	if errors['mutant']:
2017078Smjnelson		ret = 1
2027078Smjnelson		output.write("These comments are neither bug nor ARC case:\n")
2037078Smjnelson		for com in errors['mutant']:
2047078Smjnelson			output.write("  %s\n" % com)
2057078Smjnelson
2067078Smjnelson	if errors['nonexistent']:
2077078Smjnelson		ret = 1
2087078Smjnelson		output.write("These bugs/ARC cases were not found in the "
2097078Smjnelson			     "databases:\n")
2107078Smjnelson		for id in errors['nonexistent']:
2117078Smjnelson			output.write("  %s\n" % id)
2127078Smjnelson
2137078Smjnelson	if errors['nomatch']:
2147078Smjnelson		ret = 1
2157078Smjnelson		output.write("These bugs/ARC case synopsis/names don't match "
2167078Smjnelson			     "the database entries:\n")
2177078Smjnelson		for err in errors['nomatch']:
2187078Smjnelson			output.write("Synopsis/name of %s is wrong:\n" % err[0])
2197078Smjnelson			output.write("  should be: '%s'\n" % err[1])
2207078Smjnelson			output.write("         is: '%s'\n" % err[2])
2217078Smjnelson
2227078Smjnelson	return ret
223