xref: /titanic_53/usr/src/tools/onbld/Checks/Comments.py (revision cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0)
1*cdf0c1d5Smjnelson#! /usr/bin/python
2*cdf0c1d5Smjnelson#
3*cdf0c1d5Smjnelson# CDDL HEADER START
4*cdf0c1d5Smjnelson#
5*cdf0c1d5Smjnelson# The contents of this file are subject to the terms of the
6*cdf0c1d5Smjnelson# Common Development and Distribution License (the "License").
7*cdf0c1d5Smjnelson# You may not use this file except in compliance with the License.
8*cdf0c1d5Smjnelson#
9*cdf0c1d5Smjnelson# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*cdf0c1d5Smjnelson# or http://www.opensolaris.org/os/licensing.
11*cdf0c1d5Smjnelson# See the License for the specific language governing permissions
12*cdf0c1d5Smjnelson# and limitations under the License.
13*cdf0c1d5Smjnelson#
14*cdf0c1d5Smjnelson# When distributing Covered Code, include this CDDL HEADER in each
15*cdf0c1d5Smjnelson# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*cdf0c1d5Smjnelson# If applicable, add the following below this CDDL HEADER, with the
17*cdf0c1d5Smjnelson# fields enclosed by brackets "[]" replaced with your own identifying
18*cdf0c1d5Smjnelson# information: Portions Copyright [yyyy] [name of copyright owner]
19*cdf0c1d5Smjnelson#
20*cdf0c1d5Smjnelson# CDDL HEADER END
21*cdf0c1d5Smjnelson#
22*cdf0c1d5Smjnelson
23*cdf0c1d5Smjnelson#
24*cdf0c1d5Smjnelson# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
25*cdf0c1d5Smjnelson# Use is subject to license terms.
26*cdf0c1d5Smjnelson#
27*cdf0c1d5Smjnelson# ident	"%Z%%M%	%I%	%E% SMI"
28*cdf0c1d5Smjnelson#
29*cdf0c1d5Smjnelson
30*cdf0c1d5Smjnelson#
31*cdf0c1d5Smjnelson# Check delta comments:
32*cdf0c1d5Smjnelson# 	- Have the correct form.
33*cdf0c1d5Smjnelson# 	- Have a synopsis matching that of the CR or ARC case.
34*cdf0c1d5Smjnelson# 	- Appear only once.
35*cdf0c1d5Smjnelson#
36*cdf0c1d5Smjnelson
37*cdf0c1d5Smjnelsonimport re, sys
38*cdf0c1d5Smjnelsonfrom onbld.Checks.DbLookups import BugDB, ARC
39*cdf0c1d5Smjnelson
40*cdf0c1d5Smjnelsonarcre = re.compile(r'^([A-Z][A-Z]*ARC[/ \t][12]\d{3}/\d{3}) (.*)$')
41*cdf0c1d5Smjnelsonbugre = re.compile(r'^(\d{7}) (.*)$')
42*cdf0c1d5Smjnelsondef isARC(comment):
43*cdf0c1d5Smjnelson	return arcre.match(comment)
44*cdf0c1d5Smjnelson
45*cdf0c1d5Smjnelsondef isBug(comment):
46*cdf0c1d5Smjnelson	return bugre.match(comment)
47*cdf0c1d5Smjnelson
48*cdf0c1d5Smjnelson#
49*cdf0c1d5Smjnelson# Translate any acceptable case number format into "<ARC> <YEAR>/<NUM>"
50*cdf0c1d5Smjnelson# format.
51*cdf0c1d5Smjnelson#
52*cdf0c1d5Smjnelsondef normalize_arc(caseid):
53*cdf0c1d5Smjnelson	return re.sub(r'^([A-Z][A-Z]*ARC)[/ \t]', '\\1 ', caseid)
54*cdf0c1d5Smjnelson
55*cdf0c1d5Smjnelsondef comchk(comments, check_db=True, output=sys.stderr):
56*cdf0c1d5Smjnelson	bugnospcre = re.compile(r'^(\d{7})([^ ].*)')
57*cdf0c1d5Smjnelson	ignorere = re.compile(r'^(Contributed by .*|backout \d{7})')
58*cdf0c1d5Smjnelson
59*cdf0c1d5Smjnelson	errors = { 'bugnospc': [],
60*cdf0c1d5Smjnelson		   'mutant': [],
61*cdf0c1d5Smjnelson		   'dup': [],
62*cdf0c1d5Smjnelson		   'nomatch': [],
63*cdf0c1d5Smjnelson		   'nonexistent': [] }
64*cdf0c1d5Smjnelson	bugs = {}
65*cdf0c1d5Smjnelson	arcs = {}
66*cdf0c1d5Smjnelson	ret = blanks = 0
67*cdf0c1d5Smjnelson
68*cdf0c1d5Smjnelson	for com in comments:
69*cdf0c1d5Smjnelson		# Ignore valid comments we can't check
70*cdf0c1d5Smjnelson		if ignorere.search(com):
71*cdf0c1d5Smjnelson			continue
72*cdf0c1d5Smjnelson
73*cdf0c1d5Smjnelson		if not com or com.isspace():
74*cdf0c1d5Smjnelson			blanks += 1
75*cdf0c1d5Smjnelson			continue
76*cdf0c1d5Smjnelson
77*cdf0c1d5Smjnelson		match = bugre.search(com)
78*cdf0c1d5Smjnelson		if match:
79*cdf0c1d5Smjnelson			if match.group(1) not in bugs:
80*cdf0c1d5Smjnelson				bugs[match.group(1)] = []
81*cdf0c1d5Smjnelson			bugs[match.group(1)].append(match.group(2))
82*cdf0c1d5Smjnelson			continue
83*cdf0c1d5Smjnelson
84*cdf0c1d5Smjnelson		#
85*cdf0c1d5Smjnelson		# Bugs missing a space after the ID are still bugs
86*cdf0c1d5Smjnelson		# for the purposes of the duplicate ID and synopsis
87*cdf0c1d5Smjnelson		# checks.
88*cdf0c1d5Smjnelson		#
89*cdf0c1d5Smjnelson		match = bugnospcre.search(com)
90*cdf0c1d5Smjnelson		if match:
91*cdf0c1d5Smjnelson			if match.group(1) not in bugs:
92*cdf0c1d5Smjnelson				bugs[match.group(1)] = []
93*cdf0c1d5Smjnelson			bugs[match.group(1)].append(match.group(2))
94*cdf0c1d5Smjnelson			errors['bugnospc'].append(com)
95*cdf0c1d5Smjnelson			continue
96*cdf0c1d5Smjnelson
97*cdf0c1d5Smjnelson		# ARC case
98*cdf0c1d5Smjnelson		match = arcre.search(com)
99*cdf0c1d5Smjnelson		if match:
100*cdf0c1d5Smjnelson			case = normalize_arc(match.group(1))
101*cdf0c1d5Smjnelson			if case not in arcs: arcs[case] = []
102*cdf0c1d5Smjnelson			arcs[case].append(match.group(2))
103*cdf0c1d5Smjnelson			continue
104*cdf0c1d5Smjnelson
105*cdf0c1d5Smjnelson		# Anything else is bogus
106*cdf0c1d5Smjnelson		errors['mutant'].append(com)
107*cdf0c1d5Smjnelson
108*cdf0c1d5Smjnelson	if len(bugs) > 0 and check_db:
109*cdf0c1d5Smjnelson		bugdb = BugDB()
110*cdf0c1d5Smjnelson		results = bugdb.lookup(bugs.keys())
111*cdf0c1d5Smjnelson
112*cdf0c1d5Smjnelson	for crid, insts in bugs.iteritems():
113*cdf0c1d5Smjnelson		if len(insts) > 1:
114*cdf0c1d5Smjnelson			errors['dup'].append(crid)
115*cdf0c1d5Smjnelson
116*cdf0c1d5Smjnelson		if not check_db:
117*cdf0c1d5Smjnelson			continue
118*cdf0c1d5Smjnelson
119*cdf0c1d5Smjnelson		if crid not in results:
120*cdf0c1d5Smjnelson			errors['nonexistent'].append(crid)
121*cdf0c1d5Smjnelson			continue
122*cdf0c1d5Smjnelson
123*cdf0c1d5Smjnelson		for entered in insts:
124*cdf0c1d5Smjnelson			synopsis = results[crid]["synopsis"]
125*cdf0c1d5Smjnelson			if not re.search(re.escape(synopsis) +
126*cdf0c1d5Smjnelson					 r'( \([^)]+\))?$', entered):
127*cdf0c1d5Smjnelson				errors['nomatch'].append([crid, synopsis,
128*cdf0c1d5Smjnelson							  entered])
129*cdf0c1d5Smjnelson
130*cdf0c1d5Smjnelson	for case, insts in arcs.iteritems():
131*cdf0c1d5Smjnelson		if len(insts) > 1:
132*cdf0c1d5Smjnelson			errors['dup'].append(case)
133*cdf0c1d5Smjnelson
134*cdf0c1d5Smjnelson		if not check_db:
135*cdf0c1d5Smjnelson			continue
136*cdf0c1d5Smjnelson
137*cdf0c1d5Smjnelson		com, id = case.split(' ')
138*cdf0c1d5Smjnelson		arc = ARC(com, id)
139*cdf0c1d5Smjnelson
140*cdf0c1d5Smjnelson		if not arc.valid():
141*cdf0c1d5Smjnelson			errors['nonexistent'].append(case)
142*cdf0c1d5Smjnelson			continue
143*cdf0c1d5Smjnelson
144*cdf0c1d5Smjnelson		#
145*cdf0c1d5Smjnelson		# The opensolaris.org ARC interfaces only give us the
146*cdf0c1d5Smjnelson		# first 40 characters of the case name, so we must limit
147*cdf0c1d5Smjnelson		# our checking similarly.
148*cdf0c1d5Smjnelson		#
149*cdf0c1d5Smjnelson		# We first try a direct match between the actual case name
150*cdf0c1d5Smjnelson		# and the entered comment.  If that fails we remove a possible
151*cdf0c1d5Smjnelson		# trailing (fix nit)-type comment, and re-try.
152*cdf0c1d5Smjnelson		#
153*cdf0c1d5Smjnelson		for entered in insts:
154*cdf0c1d5Smjnelson			if entered[0:40] == arc.name():
155*cdf0c1d5Smjnelson				continue
156*cdf0c1d5Smjnelson			else:
157*cdf0c1d5Smjnelson				dbcom = re.sub(r' \([^)]+\)$', '', entered)
158*cdf0c1d5Smjnelson				if dbcom[0:40] != arc.name():
159*cdf0c1d5Smjnelson					errors['nomatch'].append([case,
160*cdf0c1d5Smjnelson								  arc.name(),
161*cdf0c1d5Smjnelson								  entered])
162*cdf0c1d5Smjnelson
163*cdf0c1d5Smjnelson	if blanks:
164*cdf0c1d5Smjnelson		output.write("WARNING: Blank line(s) in comments\n")
165*cdf0c1d5Smjnelson		ret = 1
166*cdf0c1d5Smjnelson
167*cdf0c1d5Smjnelson	if errors['dup']:
168*cdf0c1d5Smjnelson		ret = 1
169*cdf0c1d5Smjnelson		output.write("These IDs appear more than once in your "
170*cdf0c1d5Smjnelson			     "comments:\n")
171*cdf0c1d5Smjnelson		for err in errors['dup']:
172*cdf0c1d5Smjnelson			output.write("  %s\n" % err)
173*cdf0c1d5Smjnelson
174*cdf0c1d5Smjnelson	if errors['bugnospc']:
175*cdf0c1d5Smjnelson		ret = 1
176*cdf0c1d5Smjnelson		output.write("These bugs are missing a single space following "
177*cdf0c1d5Smjnelson			     "the ID:\n")
178*cdf0c1d5Smjnelson		for com in errors['bugnospc']:
179*cdf0c1d5Smjnelson			output.write("  %s\n" % com)
180*cdf0c1d5Smjnelson
181*cdf0c1d5Smjnelson	if errors['mutant']:
182*cdf0c1d5Smjnelson		ret = 1
183*cdf0c1d5Smjnelson		output.write("These comments are neither bug nor ARC case:\n")
184*cdf0c1d5Smjnelson		for com in errors['mutant']:
185*cdf0c1d5Smjnelson			output.write("  %s\n" % com)
186*cdf0c1d5Smjnelson
187*cdf0c1d5Smjnelson	if errors['nonexistent']:
188*cdf0c1d5Smjnelson		ret = 1
189*cdf0c1d5Smjnelson		output.write("These bugs/ARC cases were not found in the "
190*cdf0c1d5Smjnelson			     "databases:\n")
191*cdf0c1d5Smjnelson		for id in errors['nonexistent']:
192*cdf0c1d5Smjnelson			output.write("  %s\n" % id)
193*cdf0c1d5Smjnelson
194*cdf0c1d5Smjnelson	if errors['nomatch']:
195*cdf0c1d5Smjnelson		ret = 1
196*cdf0c1d5Smjnelson		output.write("These bugs/ARC case synopsis/names don't match "
197*cdf0c1d5Smjnelson			     "the database entries:\n")
198*cdf0c1d5Smjnelson		for err in errors['nomatch']:
199*cdf0c1d5Smjnelson			output.write("Synopsis/name of %s is wrong:\n" % err[0])
200*cdf0c1d5Smjnelson			output.write("  should be: '%s'\n" % err[1])
201*cdf0c1d5Smjnelson			output.write("         is: '%s'\n" % err[2])
202*cdf0c1d5Smjnelson
203*cdf0c1d5Smjnelson	return ret
204