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