@ -67,11 +67,13 @@ def CheckChangeHasDescription(input_api, output_api):
def CheckDoNotSubmitInFiles ( input_api , output_api ) :
def CheckDoNotSubmitInFiles ( input_api , output_api ) :
""" Checks that the user didn ' t add ' DO NOT ' + ' SUBMIT ' to any files. """
""" Checks that the user didn ' t add ' DO NOT ' + ' SUBMIT ' to any files. """
# We want to check every text file, not just source files.
file_filter = lambda x : x
keyword = ' DO NOT ' + ' SUBMIT '
keyword = ' DO NOT ' + ' SUBMIT '
# We want to check every text files, not just source files.
errors = _FindNewViolationsOfRule ( lambda line : keyword not in line ,
for f , line_num , line in input_api . RightHandSideLines ( lambda x : x ) :
input_api , file_filter )
if keyword in line :
text = ' \n ' . join ( ' Found %s in %s ' % ( keyword , loc ) for loc in errors )
text = ' Found ' + keyword + ' in %s , line %s ' % ( f . LocalPath ( ) , line_num )
if text :
return [ output_api . PresubmitError ( text ) ]
return [ output_api . PresubmitError ( text ) ]
return [ ]
return [ ]
@ -213,6 +215,41 @@ def CheckChangeHasNoCrAndHasOnlyOneEol(input_api, output_api,
return outputs
return outputs
def _ReportErrorFileAndLine ( filename , line_num , line ) :
""" Default error formatter for _FindNewViolationsOfRule. """
return ' %s , line %s ' % ( filename , line_num )
def _FindNewViolationsOfRule ( callable_rule , input_api , source_file_filter = None ,
error_formatter = _ReportErrorFileAndLine ) :
""" Find all newly introduced violations of a per-line rule (a callable).
Arguments :
callable_rule : a callable taking a line of input and returning True
if the rule is satisfied and False if there was a problem .
input_api : object to enumerate the affected files .
source_file_filter : a filter to be passed to the input api .
error_formatter : a callable taking ( filename , line_number , line ) and
returning a formatted error string .
Returns :
A list of the newly - introduced violations reported by the rule .
"""
errors = [ ]
for f in input_api . AffectedFiles ( source_file_filter , include_deletes = False ) :
# For speed, we do two passes, checking first the full file. Shelling out
# to the SCM to determine the changed region can be quite expensive on
# Win32. Assuming that most files will be kept problem-free, we can
# skip the SCM operations most of the time.
for line in f . NewContents ( ) :
if not callable_rule ( line ) :
# Violation found in full text; re-run on just the changed contents.
for line_num , line in f . ChangedContents ( ) :
if not callable_rule ( line ) :
errors . append ( error_formatter ( f . LocalPath ( ) , line_num , line ) )
return errors
def CheckChangeHasNoTabs ( input_api , output_api , source_file_filter = None ) :
def CheckChangeHasNoTabs ( input_api , output_api , source_file_filter = None ) :
""" Checks that there are no tab characters in any of the text files to be
""" Checks that there are no tab characters in any of the text files to be
submitted .
submitted .
@ -225,10 +262,10 @@ def CheckChangeHasNoTabs(input_api, output_api, source_file_filter=None):
return ( not input_api . os_path . basename ( affected_file . LocalPath ( ) ) in
return ( not input_api . os_path . basename ( affected_file . LocalPath ( ) ) in
( ' Makefile ' , ' makefile ' ) and
( ' Makefile ' , ' makefile ' ) and
source_file_filter ( affected_file ) )
source_file_filter ( affected_file ) )
tabs = [ ]
for f , line_num , line in input_api . RightHandSideLines ( filter_more ) :
tabs = _FindNewViolationsOfRule ( lambda line : ' \t ' not in line ,
if ' \t ' in line :
input_api , filter_more )
tabs . append ( ' %s , line %s ' % ( f . LocalPath ( ) , line_num ) )
if tabs :
if tabs :
return [ output_api . PresubmitPromptWarning ( ' Found a tab character in: ' ,
return [ output_api . PresubmitPromptWarning ( ' Found a tab character in: ' ,
long_text = ' \n ' . join ( tabs ) ) ]
long_text = ' \n ' . join ( tabs ) ) ]
@ -239,21 +276,19 @@ def CheckChangeTodoHasOwner(input_api, output_api, source_file_filter=None):
""" Checks that the user didn ' t add TODO(name) without an owner. """
""" Checks that the user didn ' t add TODO(name) without an owner. """
unowned_todo = input_api . re . compile ( ' TO ' + ' DO[^(] ' )
unowned_todo = input_api . re . compile ( ' TO ' + ' DO[^(] ' )
for f , line_num , line in input_api . RightHandSideLines ( source_file_filter ) :
errors = _FindNewViolationsOfRule ( lambda x : not unowned_todo . search ( x ) ,
if unowned_todo . search ( line ) :
input_api , source_file_filter )
text = ( ' Found TO ' + ' DO with no owner in %s , line %s ' %
errors = [ ' Found TO ' + ' DO with no owner in ' + x for x in errors ]
( f . LocalPath ( ) , line_num ) )
if errors :
return [ output_api . PresubmitPromptWarning ( text ) ]
return [ output_api . PresubmitPromptWarning ( ' \n ' . join ( errors ) ) ]
return [ ]
return [ ]
def CheckChangeHasNoStrayWhitespace ( input_api , output_api ,
def CheckChangeHasNoStrayWhitespace ( input_api , output_api ,
source_file_filter = None ) :
source_file_filter = None ) :
""" Checks that there is no stray whitespace at source lines end. """
""" Checks that there is no stray whitespace at source lines end. """
errors = [ ]
errors = _FindNewViolationsOfRule ( lambda line : line . rstrip ( ) == line ,
for f , line_num , line in input_api . RightHandSideLines ( source_file_filter ) :
input_api , source_file_filter )
if line . rstrip ( ) != line :
errors . append ( ' %s , line %s ' % ( f . LocalPath ( ) , line_num ) )
if errors :
if errors :
return [ output_api . PresubmitPromptWarning (
return [ output_api . PresubmitPromptWarning (
' Found line ending with white spaces in: ' ,
' Found line ending with white spaces in: ' ,
@ -265,28 +300,23 @@ def CheckLongLines(input_api, output_api, maxlen=80, source_file_filter=None):
""" Checks that there aren ' t any lines longer than maxlen characters in any of
""" Checks that there aren ' t any lines longer than maxlen characters in any of
the text files to be submitted .
the text files to be submitted .
"""
"""
bad = [ ]
def no_long_lines ( line ) :
for f , line_num , line in input_api . RightHandSideLines ( source_file_filter ) :
# Allow lines with http://, https:// and #define/#pragma/#include/#if/#endif
# Allow lines with http://, https:// and #define/#pragma/#include/#if/#endif
# to exceed the maxlen rule.
# to exceed the maxlen rule.
if ( len ( line ) > maxlen and
return ( len ( line ) < = maxlen or
not ' http:// ' in line and
any ( ( url in line ) for url in ( ' http:// ' , ' https:// ' ) ) or
not ' https:// ' in line and
line . startswith ( ( ' #define ' , ' #include ' , ' #import ' , ' #pragma ' ,
not line . startswith ( ' #define ' ) and
' #if ' , ' #endif ' ) ) )
not line . startswith ( ' #include ' ) and
not line . startswith ( ' #import ' ) and
not line . startswith ( ' #pragma ' ) and
not line . startswith ( ' #if ' ) and
not line . startswith ( ' #endif ' ) ) :
bad . append (
' %s , line %s , %s chars ' %
( f . LocalPath ( ) , line_num , len ( line ) ) )
if len ( bad ) == 5 : # Just show the first 5 errors.
break
if bad :
def format_error ( filename , line_num , line ) :
return ' %s , line %s , %s chars ' % ( filename , line_num , len ( line ) )
errors = _FindNewViolationsOfRule ( no_long_lines , input_api ,
source_file_filter ,
error_formatter = format_error )
if errors :
msg = ' Found lines longer than %s characters (first 5 shown). ' % maxlen
msg = ' Found lines longer than %s characters (first 5 shown). ' % maxlen
return [ output_api . PresubmitPromptWarning ( msg , items = bad ) ]
return [ output_api . PresubmitPromptWarning ( msg , items = errors [ : 5 ] ) ]
else :
else :
return [ ]
return [ ]
@ -880,24 +910,45 @@ def PanProjectChecks(input_api, output_api,
text_files = lambda x : input_api . FilterSourceFile ( x , black_list = black_list ,
text_files = lambda x : input_api . FilterSourceFile ( x , black_list = black_list ,
white_list = white_list )
white_list = white_list )
snapshot_memory = [ ]
def snapshot ( msg ) :
""" Measures & prints performance warning if a rule is running slow. """
dt2 = input_api . time . clock ( )
if snapshot_memory :
delta_ms = int ( 1000 * ( dt2 - snapshot_memory [ 0 ] ) )
if delta_ms > 500 :
print " %s took a long time: %d ms " % ( snapshot_memory [ 1 ] , delta_ms )
snapshot_memory [ : ] = ( dt2 , msg )
if owners_check :
if owners_check :
snapshot ( " checking owners " )
results . extend ( input_api . canned_checks . CheckOwners (
results . extend ( input_api . canned_checks . CheckOwners (
input_api , output_api , source_file_filter = sources ) )
input_api , output_api , source_file_filter = sources ) )
snapshot ( " checking long lines " )
results . extend ( input_api . canned_checks . CheckLongLines (
results . extend ( input_api . canned_checks . CheckLongLines (
input_api , output_api , source_file_filter = sources ) )
input_api , output_api , source_file_filter = sources ) )
snapshot ( " checking tabs " )
results . extend ( input_api . canned_checks . CheckChangeHasNoTabs (
results . extend ( input_api . canned_checks . CheckChangeHasNoTabs (
input_api , output_api , source_file_filter = sources ) )
input_api , output_api , source_file_filter = sources ) )
snapshot ( " checking stray whitespace " )
results . extend ( input_api . canned_checks . CheckChangeHasNoStrayWhitespace (
results . extend ( input_api . canned_checks . CheckChangeHasNoStrayWhitespace (
input_api , output_api , source_file_filter = sources ) )
input_api , output_api , source_file_filter = sources ) )
snapshot ( " checking eol style " )
results . extend ( input_api . canned_checks . CheckChangeSvnEolStyle (
results . extend ( input_api . canned_checks . CheckChangeSvnEolStyle (
input_api , output_api , source_file_filter = text_files ) )
input_api , output_api , source_file_filter = text_files ) )
snapshot ( " checking svn mime types " )
results . extend ( input_api . canned_checks . CheckSvnForCommonMimeTypes (
results . extend ( input_api . canned_checks . CheckSvnForCommonMimeTypes (
input_api , output_api ) )
input_api , output_api ) )
snapshot ( " checking license " )
results . extend ( input_api . canned_checks . CheckLicense (
results . extend ( input_api . canned_checks . CheckLicense (
input_api , output_api , license_header , source_file_filter = sources ) )
input_api , output_api , license_header , source_file_filter = sources ) )
snapshot ( " checking nsobjects " )
results . extend ( _CheckConstNSObject (
results . extend ( _CheckConstNSObject (
input_api , output_api , source_file_filter = sources ) )
input_api , output_api , source_file_filter = sources ) )
snapshot ( " checking singletons " )
results . extend ( _CheckSingletonInHeaders (
results . extend ( _CheckSingletonInHeaders (
input_api , output_api , source_file_filter = sources ) )
input_api , output_api , source_file_filter = sources ) )
snapshot ( " done " )
return results
return results