blob: 4b4706618b7d8fa89bebb7d420a19fd90010b1f0 [file] [log] [blame]
mjnelsoncdf0c1d2008-07-10 19:11:48 -07001#! /usr/bin/python
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23#
Mark J. Nelson41a5f562009-06-20 12:12:10 -060024# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
mjnelsoncdf0c1d2008-07-10 19:11:48 -070025# Use is subject to license terms.
26#
mjnelsoncdf0c1d2008-07-10 19:11:48 -070027
Richard Lowe2f54b712010-08-23 22:22:42 -040028# Copyright 2007, 2010 Richard Lowe
Andy Fiddamanb9219c82018-11-15 10:17:46 +000029# Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
Richard Lowe2f54b712010-08-23 22:22:42 -040030
mjnelsoncdf0c1d2008-07-10 19:11:48 -070031#
32# Check delta comments:
Andy Fiddamanb9219c82018-11-15 10:17:46 +000033# - Have the correct form.
34# - Have a synopsis matching that of the bug
35# - Appear only once.
mjnelsoncdf0c1d2008-07-10 19:11:48 -070036#
37
38import re, sys
Richard Lowe2f54b712010-08-23 22:22:42 -040039from onbld.Checks.DbLookups import BugDB
mjnelsoncdf0c1d2008-07-10 19:11:48 -070040
Richard Loweef62fef2008-09-26 14:35:44 -070041
Richard Lowe2f54b712010-08-23 22:22:42 -040042bugre = re.compile(r'^(\d{2,7}) (.*)$')
43
mjnelsoncdf0c1d2008-07-10 19:11:48 -070044
45def isBug(comment):
46 return bugre.match(comment)
47
mjnelsoncdf0c1d2008-07-10 19:11:48 -070048
Richard Lowe2f54b712010-08-23 22:22:42 -040049def comchk(comments, check_db=True, output=sys.stderr):
John Sonnenscheinc08a2532008-11-07 15:51:59 -080050 '''Validate checkin comments against ON standards.
Richard Loweef62fef2008-09-26 14:35:44 -070051
John Sonnenscheinc08a2532008-11-07 15:51:59 -080052 Comments must be a list of one-line comments, with no trailing
53 newline.
Richard Lowe2f54b712010-08-23 22:22:42 -040054
55 If check_db is True (the default), validate bug synopses against the
56 databases.
Richard Loweef62fef2008-09-26 14:35:44 -070057
John Sonnenscheinc08a2532008-11-07 15:51:59 -080058 Error messages intended for the user are written to output,
59 which defaults to stderr
60 '''
Richard Lowe2f54b712010-08-23 22:22:42 -040061 bugnospcre = re.compile(r'^(\d{2,7})([^ ].*)')
62 ignorere = re.compile(r'^(' +
63 r'Portions contributed by|' +
64 r'Contributed by|' +
65 r'Reviewed[ -]by|' +
66 r'Approved[ -]by|' +
67 r'back[ -]?out)' +
68 r'[: ]')
mjnelsoncdf0c1d2008-07-10 19:11:48 -070069
70 errors = { 'bugnospc': [],
71 'mutant': [],
72 'dup': [],
73 'nomatch': [],
74 'nonexistent': [] }
75 bugs = {}
Richard Loweef62fef2008-09-26 14:35:44 -070076 ret = 0
77 blanks = False
mjnelsoncdf0c1d2008-07-10 19:11:48 -070078
79 for com in comments:
John Sonnenscheinc08a2532008-11-07 15:51:59 -080080 # Our input must be newline-free, comments are line-wise.
81 if com.find('\n') != -1:
82 raise ValueError("newline in comment '%s'" % com)
83
mjnelsoncdf0c1d2008-07-10 19:11:48 -070084 # Ignore valid comments we can't check
85 if ignorere.search(com):
86 continue
87
88 if not com or com.isspace():
Richard Loweef62fef2008-09-26 14:35:44 -070089 blanks = True
mjnelsoncdf0c1d2008-07-10 19:11:48 -070090 continue
91
92 match = bugre.search(com)
93 if match:
94 if match.group(1) not in bugs:
95 bugs[match.group(1)] = []
96 bugs[match.group(1)].append(match.group(2))
97 continue
98
99 #
100 # Bugs missing a space after the ID are still bugs
101 # for the purposes of the duplicate ID and synopsis
102 # checks.
103 #
104 match = bugnospcre.search(com)
105 if match:
106 if match.group(1) not in bugs:
107 bugs[match.group(1)] = []
108 bugs[match.group(1)].append(match.group(2))
109 errors['bugnospc'].append(com)
110 continue
111
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700112 # Anything else is bogus
113 errors['mutant'].append(com)
114
115 if len(bugs) > 0 and check_db:
116 bugdb = BugDB()
Andy Fiddamanb9219c82018-11-15 10:17:46 +0000117 results = bugdb.lookup(list(bugs.keys()))
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700118
Andy Fiddamanb9219c82018-11-15 10:17:46 +0000119 for crid, insts in bugs.items():
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700120 if len(insts) > 1:
121 errors['dup'].append(crid)
122
123 if not check_db:
124 continue
125
126 if crid not in results:
127 errors['nonexistent'].append(crid)
128 continue
129
Richard Loweef62fef2008-09-26 14:35:44 -0700130 #
131 # For each synopsis, compare the real synopsis with
132 # that in the comments, allowing for possible '(fix
133 # stuff)'-like trailing text
134 #
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700135 for entered in insts:
136 synopsis = results[crid]["synopsis"]
Richard Loweef62fef2008-09-26 14:35:44 -0700137 if not re.search(r'^' + re.escape(synopsis) +
John Sonnenscheinc08a2532008-11-07 15:51:59 -0800138 r'( \([^)]+\))?$', entered):
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700139 errors['nomatch'].append([crid, synopsis,
John Sonnenscheinc08a2532008-11-07 15:51:59 -0800140 entered])
141
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700142
143 if blanks:
144 output.write("WARNING: Blank line(s) in comments\n")
145 ret = 1
146
147 if errors['dup']:
148 ret = 1
149 output.write("These IDs appear more than once in your "
150 "comments:\n")
151 for err in errors['dup']:
152 output.write(" %s\n" % err)
153
154 if errors['bugnospc']:
155 ret = 1
156 output.write("These bugs are missing a single space following "
157 "the ID:\n")
158 for com in errors['bugnospc']:
159 output.write(" %s\n" % com)
160
161 if errors['mutant']:
162 ret = 1
Richard Lowe2f54b712010-08-23 22:22:42 -0400163 output.write("These comments are not valid bugs:\n")
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700164 for com in errors['mutant']:
165 output.write(" %s\n" % com)
166
167 if errors['nonexistent']:
168 ret = 1
Richard Lowe2f54b712010-08-23 22:22:42 -0400169 output.write("These bugs were not found in the databases:\n")
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700170 for id in errors['nonexistent']:
171 output.write(" %s\n" % id)
172
173 if errors['nomatch']:
174 ret = 1
Richard Lowe2f54b712010-08-23 22:22:42 -0400175 output.write("These bug synopses don't match "
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700176 "the database entries:\n")
177 for err in errors['nomatch']:
Richard Lowe2f54b712010-08-23 22:22:42 -0400178 output.write("Synopsis of %s is wrong:\n" % err[0])
mjnelsoncdf0c1d2008-07-10 19:11:48 -0700179 output.write(" should be: '%s'\n" % err[1])
180 output.write(" is: '%s'\n" % err[2])
181
182 return ret