##// END OF EJS Templates
check-code: add --blame switch
Matt Mackall -
r11604:c5d40818 default
parent child Browse files
Show More
@@ -7,7 +7,7 b''
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 import re, glob
10 import re, glob, os
11 import optparse
11 import optparse
12
12
13 def repquote(m):
13 def repquote(m):
@@ -160,7 +160,7 b' class norepeatlogger(object):'
160 def __init__(self):
160 def __init__(self):
161 self._lastseen = None
161 self._lastseen = None
162
162
163 def log(self, fname, lineno, line, msg):
163 def log(self, fname, lineno, line, msg, blame):
164 """print error related a to given line of a given file.
164 """print error related a to given line of a given file.
165
165
166 The faulty line will also be printed but only once in the case
166 The faulty line will also be printed but only once in the case
@@ -173,14 +173,26 b' class norepeatlogger(object):'
173 """
173 """
174 msgid = fname, lineno, line
174 msgid = fname, lineno, line
175 if msgid != self._lastseen:
175 if msgid != self._lastseen:
176 print "%s:%d:" % (fname, lineno)
176 if blame:
177 print "%s:%d (%s):" % (fname, lineno, blame)
178 else:
179 print "%s:%d:" % (fname, lineno)
177 print " > %s" % line
180 print " > %s" % line
178 self._lastseen = msgid
181 self._lastseen = msgid
179 print " " + msg
182 print " " + msg
180
183
181 _defaultlogger = norepeatlogger()
184 _defaultlogger = norepeatlogger()
182
185
183 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False):
186 def getblame(f):
187 lines = []
188 for l in os.popen('hg annotate -un %s' % f):
189 start, line = l.split(':', 1)
190 user, rev = start.split()
191 lines.append((line[1:-1], user, rev))
192 return lines
193
194 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
195 blame=False):
184 """checks style and portability of a given file
196 """checks style and portability of a given file
185
197
186 :f: filepath
198 :f: filepath
@@ -191,6 +203,7 b' def checkfile(f, logfunc=_defaultlogger.'
191
203
192 return True if no error is found, False otherwise.
204 return True if no error is found, False otherwise.
193 """
205 """
206 blamecache = None
194 result = True
207 result = True
195 for name, match, filters, pats in checks:
208 for name, match, filters, pats in checks:
196 fc = 0
209 fc = 0
@@ -210,7 +223,16 b' def checkfile(f, logfunc=_defaultlogger.'
210 if not warnings and msg.startswith("warning"):
223 if not warnings and msg.startswith("warning"):
211 continue
224 continue
212 if re.search(p, l[1]):
225 if re.search(p, l[1]):
213 logfunc(f, n + 1, l[0], msg)
226 bd = ""
227 if blame:
228 bd = 'working directory'
229 if not blamecache:
230 blamecache = getblame(f)
231 if n < len(blamecache):
232 bl, bu, br = blamecache[n]
233 if bl == l[0]:
234 bd = '%s@%s' % (bu, br)
235 logfunc(f, n + 1, l[0], msg, bd)
214 fc += 1
236 fc += 1
215 result = False
237 result = False
216 if maxerr is not None and fc >= maxerr:
238 if maxerr is not None and fc >= maxerr:
@@ -219,15 +241,16 b' def checkfile(f, logfunc=_defaultlogger.'
219 break
241 break
220 return result
242 return result
221
243
222
223 if __name__ == "__main__":
244 if __name__ == "__main__":
224 parser = optparse.OptionParser("%prog [options] [files]")
245 parser = optparse.OptionParser("%prog [options] [files]")
225 parser.add_option("-w", "--warnings", action="store_true",
246 parser.add_option("-w", "--warnings", action="store_true",
226 help="include warning-level checks")
247 help="include warning-level checks")
227 parser.add_option("-p", "--per-file", type="int",
248 parser.add_option("-p", "--per-file", type="int",
228 help="max warnings per file")
249 help="max warnings per file")
250 parser.add_option("-b", "--blame", action="store_true",
251 help="use annotate to generate blame info")
229
252
230 parser.set_defaults(per_file=15, warnings=False)
253 parser.set_defaults(per_file=15, warnings=False, blame=False)
231 (options, args) = parser.parse_args()
254 (options, args) = parser.parse_args()
232
255
233 if len(args) == 0:
256 if len(args) == 0:
@@ -236,4 +259,5 b' if __name__ == "__main__":'
236 check = args
259 check = args
237
260
238 for f in check:
261 for f in check:
239 checkfile(f, maxerr=options.per_file, warnings=options.warnings)
262 checkfile(f, maxerr=options.per_file, warnings=options.warnings,
263 blame=options.blame)
General Comments 0
You need to be logged in to leave comments. Login now