@ -19,6 +19,7 @@
# MA 02111-1307 USA
#
import collections
import command
import gitutil
import os
@ -57,63 +58,86 @@ def CheckPatch(fname, verbose=False):
""" Run checkpatch.pl on a file.
Returns :
4 - tuple containing :
result : False = failure , True = ok
named tuple containing :
ok : False = failure , True = ok
problems : List of problems , each a dict :
' type ' ; error or warning
' msg ' : text message
' file ' : filename
' line ' : line number
errors : Number of errors
warnings : Number of warnings
checks : Number of checks
lines : Number of lines
stdout : Full output of checkpatch
"""
result = False
error_count , warning_count , lines = 0 , 0 , 0
problems = [ ]
fields = [ ' ok ' , ' problems ' , ' errors ' , ' warnings ' , ' checks ' , ' lines ' ,
' stdout ' ]
result = collections . namedtuple ( ' CheckPatchResult ' , fields )
result . ok = False
result . errors , result . warning , result . checks = 0 , 0 , 0
result . lines = 0
result . problems = [ ]
chk = FindCheckPatch ( )
item = { }
stdout = command . Output ( chk , ' --no-tree ' , fname )
result . stdout = command . Output ( chk , ' --no-tree ' , fname )
#pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE)
#stdout, stderr = pipe.communicate()
# total: 0 errors, 0 warnings, 159 lines checked
# or:
# total: 0 errors, 2 warnings, 7 checks, 473 lines checked
re_stats = re . compile ( ' total: ( \\ d+) errors, ( \ d+) warnings, ( \ d+) ' )
re_stats_full = re . compile ( ' total: ( \\ d+) errors, ( \ d+) warnings, ( \ d+) '
' checks, ( \ d+) ' )
re_ok = re . compile ( ' .*has no obvious style problems ' )
re_bad = re . compile ( ' .*has style problems, please review ' )
re_error = re . compile ( ' ERROR: (.*) ' )
re_warning = re . compile ( ' WARNING: (.*) ' )
re_check = re . compile ( ' CHECK: (.*) ' )
re_file = re . compile ( ' # \ d+: FILE: ([^:]*):( \ d+): ' )
for line in stdout . splitlines ( ) :
for line in result . stdout . splitlines ( ) :
if verbose :
print line
# A blank line indicates the end of a message
if not line and item :
problems . append ( item )
result . problems . append ( item )
item = { }
match = re_stats_full . match ( line )
if not match :
match = re_stats . match ( line )
if match :
error_count = int ( match . group ( 1 ) )
warning_count = int ( match . group ( 2 ) )
lines = int ( match . group ( 3 ) )
result . errors = int ( match . group ( 1 ) )
result . warnings = int ( match . group ( 2 ) )
if len ( match . groups ( ) ) == 4 :
result . checks = int ( match . group ( 3 ) )
result . lines = int ( match . group ( 4 ) )
else :
result . lines = int ( match . group ( 3 ) )
elif re_ok . match ( line ) :
result = True
result . ok = True
elif re_bad . match ( line ) :
result = False
match = re_error . match ( line )
if match :
item [ ' msg ' ] = match . group ( 1 )
result . ok = False
err_match = re_error . match ( line )
warn_match = re_warning . match ( line )
file_match = re_file . match ( line )
check_match = re_check . match ( line )
if err_match :
item [ ' msg ' ] = err_match . group ( 1 )
item [ ' type ' ] = ' error '
match = re_warning . match ( line )
if match :
item [ ' msg ' ] = match . group ( 1 )
elif warn_match :
item [ ' msg ' ] = warn_match . group ( 1 )
item [ ' type ' ] = ' warning '
match = re_file . match ( line )
if match :
item [ ' file ' ] = match . group ( 1 )
item [ ' line ' ] = int ( match . group ( 2 ) )
elif check_match :
item [ ' msg ' ] = check_match . group ( 1 )
item [ ' type ' ] = ' check '
elif file_match :
item [ ' file ' ] = file_match . group ( 1 )
item [ ' line ' ] = int ( file_match . group ( 2 ) )
return result , problems , error_count , warning_count , lines , stdout
return result
def GetWarningMsg ( col , msg_type , fname , line , msg ) :
''' Create a message for a given file/line
@ -128,37 +152,39 @@ def GetWarningMsg(col, msg_type, fname, line, msg):
msg_type = col . Color ( col . YELLOW , msg_type )
elif msg_type == ' error ' :
msg_type = col . Color ( col . RED , msg_type )
elif msg_type == ' check ' :
msg_type = col . Color ( col . MAGENTA , msg_type )
return ' %s : %s , %d : %s ' % ( msg_type , fname , line , msg )
def CheckPatches ( verbose , args ) :
''' Run the checkpatch.pl script on each patch '''
error_count = 0
warning_count = 0
error_count , warning_count , check_count = 0 , 0 , 0
col = terminal . Color ( )
for fname in args :
ok , problems , errors , warnings , lines , stdout = CheckPatch ( fname ,
verbose )
if not ok :
error_count + = errors
warning_count + = warnings
print ' %d errors, %d warnings for %s : ' % ( errors ,
warnings , fname )
if len ( problems ) != error_count + warning_count :
result = CheckPatch ( fname , verbose )
if not result . ok :
error_count + = result . errors
warning_count + = result . warnings
check_count + = result . checks
print ' %d errors, %d warnings, %d checks for %s : ' % ( result . errors ,
result . warnings , result . checks , col . Color ( col . BLUE , fname ) )
if ( len ( result . problems ) != result . errors + result . warnings +
result . checks ) :
print " Internal error: some problems lost "
for item in problems :
print GetWarningMsg ( col , item [ ' type ' ] ,
for item in result . problems :
print GetWarningMsg ( col , item . get ( ' type ' , ' <unknown> ' ) ,
item . get ( ' file ' , ' <unknown> ' ) ,
item . get ( ' line ' , 0 ) , item [ ' msg ' ] )
item . get ( ' line ' , 0 ) , item . get ( ' msg ' , ' message ' ) )
print
#print stdout
if error_count != 0 or warning_count != 0 :
str = ' checkpatch.pl found %d error(s), %d warning(s) ' % (
error_count , warning_count )
if error_count or warning_count or check_count :
str = ' checkpatch.pl found %d error(s), %d warning(s), %d checks(s) '
color = col . GREEN
if warning_count :
color = col . YELLOW
if error_count :
color = col . RED
print col . Color ( color , str )
print col . Color ( color , str % ( error_count , warning_count , check_count ) )
return False
return True