1#! /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# 24# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26# 27 28# 29# Check delta comments: 30# - Have the correct form. 31# - Have a synopsis matching that of the CR or ARC case. 32# - Appear only once. 33# 34 35import re, sys 36from onbld.Checks.DbLookups import BugDB, ARC 37 38arcre = re.compile(r'^([A-Z][A-Z]*ARC[/ \t][12]\d{3}/\d{3}) (.*)$') 39bugre = re.compile(r'^(\d{7}) (.*)$') 40def isARC(comment): 41 return arcre.match(comment) 42 43def isBug(comment): 44 return bugre.match(comment) 45 46# 47# Translate any acceptable case number format into "<ARC> <YEAR>/<NUM>" 48# format. 49# 50def normalize_arc(caseid): 51 return re.sub(r'^([A-Z][A-Z]*ARC)[/ \t]', '\\1 ', caseid) 52 53def comchk(comments, check_db=True, output=sys.stderr): 54 bugnospcre = re.compile(r'^(\d{7})([^ ].*)') 55 ignorere = re.compile(r'^(Portions contributed by |Contributed by |back[ -]?out )') 56 57 errors = { 'bugnospc': [], 58 'mutant': [], 59 'dup': [], 60 'nomatch': [], 61 'nonexistent': [] } 62 bugs = {} 63 arcs = {} 64 ret = blanks = 0 65 66 for com in comments: 67 # Ignore valid comments we can't check 68 if ignorere.search(com): 69 continue 70 71 if not com or com.isspace(): 72 blanks += 1 73 continue 74 75 match = bugre.search(com) 76 if match: 77 if match.group(1) not in bugs: 78 bugs[match.group(1)] = [] 79 bugs[match.group(1)].append(match.group(2)) 80 continue 81 82 # 83 # Bugs missing a space after the ID are still bugs 84 # for the purposes of the duplicate ID and synopsis 85 # checks. 86 # 87 match = bugnospcre.search(com) 88 if match: 89 if match.group(1) not in bugs: 90 bugs[match.group(1)] = [] 91 bugs[match.group(1)].append(match.group(2)) 92 errors['bugnospc'].append(com) 93 continue 94 95 # ARC case 96 match = arcre.search(com) 97 if match: 98 case = normalize_arc(match.group(1)) 99 if case not in arcs: arcs[case] = [] 100 arcs[case].append(match.group(2)) 101 continue 102 103 # Anything else is bogus 104 errors['mutant'].append(com) 105 106 if len(bugs) > 0 and check_db: 107 bugdb = BugDB() 108 results = bugdb.lookup(bugs.keys()) 109 110 for crid, insts in bugs.iteritems(): 111 if len(insts) > 1: 112 errors['dup'].append(crid) 113 114 if not check_db: 115 continue 116 117 if crid not in results: 118 errors['nonexistent'].append(crid) 119 continue 120 121 for entered in insts: 122 synopsis = results[crid]["synopsis"] 123 if not re.search(re.escape(synopsis) + 124 r'( \([^)]+\))?$', entered): 125 errors['nomatch'].append([crid, synopsis, 126 entered]) 127 128 for case, insts in arcs.iteritems(): 129 if len(insts) > 1: 130 errors['dup'].append(case) 131 132 if not check_db: 133 continue 134 135 com, id = case.split(' ') 136 arc = ARC(com, id) 137 138 if not arc.valid(): 139 errors['nonexistent'].append(case) 140 continue 141 142 # 143 # The opensolaris.org ARC interfaces only give us the 144 # first 40 characters of the case name, so we must limit 145 # our checking similarly. 146 # 147 # We first try a direct match between the actual case name 148 # and the entered comment. If that fails we remove a possible 149 # trailing (fix nit)-type comment, and re-try. 150 # 151 for entered in insts: 152 if entered[0:40] == arc.name(): 153 continue 154 else: 155 dbcom = re.sub(r' \([^)]+\)$', '', entered) 156 if dbcom[0:40] != arc.name(): 157 errors['nomatch'].append([case, 158 arc.name(), 159 entered]) 160 161 if blanks: 162 output.write("WARNING: Blank line(s) in comments\n") 163 ret = 1 164 165 if errors['dup']: 166 ret = 1 167 output.write("These IDs appear more than once in your " 168 "comments:\n") 169 for err in errors['dup']: 170 output.write(" %s\n" % err) 171 172 if errors['bugnospc']: 173 ret = 1 174 output.write("These bugs are missing a single space following " 175 "the ID:\n") 176 for com in errors['bugnospc']: 177 output.write(" %s\n" % com) 178 179 if errors['mutant']: 180 ret = 1 181 output.write("These comments are neither bug nor ARC case:\n") 182 for com in errors['mutant']: 183 output.write(" %s\n" % com) 184 185 if errors['nonexistent']: 186 ret = 1 187 output.write("These bugs/ARC cases were not found in the " 188 "databases:\n") 189 for id in errors['nonexistent']: 190 output.write(" %s\n" % id) 191 192 if errors['nomatch']: 193 ret = 1 194 output.write("These bugs/ARC case synopsis/names don't match " 195 "the database entries:\n") 196 for err in errors['nomatch']: 197 output.write("Synopsis/name of %s is wrong:\n" % err[0]) 198 output.write(" should be: '%s'\n" % err[1]) 199 output.write(" is: '%s'\n" % err[2]) 200 201 return ret 202