2016-05-20 17:30:37 -07:00
#!/usr/bin/env python3
2016-07-12 21:59:09 -07:00
import argparse
import multiprocessing
2016-05-20 17:30:37 -07:00
import os
2016-07-12 21:59:09 -07:00
import queue
2016-07-10 08:33:27 -07:00
import subprocess
2016-05-20 17:30:37 -07:00
import sys
2016-07-12 21:59:09 -07:00
from threading import Lock
from threading import Thread
2016-05-20 17:30:37 -07:00
2016-07-10 08:33:27 -07:00
from clangformat import ClangFormat
from licenseupdate import LicenseUpdate
from newline import Newline
from whitespace import Whitespace
2016-07-12 21:59:09 -07:00
from lint import Lint
2016-07-10 08:33:27 -07:00
from task import Task
# Check that the current directory is part of a Git repository
def inGitRepo ( directory ) :
ret = subprocess . run ( [ " git " , " rev-parse " ] , stderr = subprocess . DEVNULL )
return ret . returncode == 0
2016-07-12 21:59:09 -07:00
def threadFunc ( workQueue , isVerbose , printLock ) :
# Lint is run last since previous tasks can affect its output
tasks = [ ClangFormat ( ) , LicenseUpdate ( ) , Newline ( ) , Whitespace ( ) , Lint ( ) ]
try :
while True :
name = workQueue . get_nowait ( )
if isVerbose :
printLock . acquire ( )
print ( " Processing " , name , )
for task in tasks :
if task . fileMatchesExtension ( name ) :
print ( " with " + type ( task ) . __name__ )
printLock . release ( )
for task in tasks :
if task . fileMatchesExtension ( name ) :
task . run ( name )
except queue . Empty :
pass
2016-07-10 08:33:27 -07:00
def main ( ) :
if not inGitRepo ( " . " ) :
print ( " Error: not invoked within a Git repository " , file = sys . stderr )
sys . exit ( 1 )
# Handle running in either the root or styleguide directories
configPath = " "
if os . getcwd ( ) . rpartition ( os . sep ) [ 2 ] == " styleguide " :
configPath = " .. "
else :
configPath = " . "
2016-07-12 21:59:09 -07:00
# Delete temporary files from previous incomplete run
files = [ os . path . join ( dp , f ) for dp , dn , fn in
os . walk ( os . path . expanduser ( configPath ) ) for f in fn ]
for f in files :
if f . endswith ( " .tmp " ) :
os . remove ( f )
2016-07-10 08:33:27 -07:00
# Recursively create list of files in given directory
files = [ os . path . join ( dp , f ) for dp , dn , fn in
os . walk ( os . path . expanduser ( configPath ) ) for f in fn ]
if not files :
print ( " Error: no files found to format " , file = sys . stderr )
sys . exit ( 1 )
# Don't format generated files
files = [ name for name in files if Task . notGeneratedFile ( name ) ]
2016-07-12 21:59:09 -07:00
# Parse command-line arguments
parser = argparse . ArgumentParser ( description = " Runs all formatting tasks on the code base. This should be invoked from either the styleguide directory or the root directory of the project. " )
parser . add_argument ( " -v " , dest = " verbose " , action = " store_true " ,
help = " enable output verbosity " )
parser . add_argument ( " -j " , dest = " jobs " , type = int ,
default = multiprocessing . cpu_count ( ) ,
help = " number of jobs to run (default is number of cores) " )
args = parser . parse_args ( )
jobs = args . jobs
isVerbose = args . verbose
# Add files to work queue
workQueue = queue . Queue ( )
for file in files :
workQueue . put ( file )
2016-07-10 08:33:27 -07:00
2016-07-12 21:59:09 -07:00
threads = [ ]
printLock = Lock ( )
2016-07-10 08:33:27 -07:00
2016-07-12 21:59:09 -07:00
# Start worker threads
for i in range ( 0 , jobs ) :
thread = Thread ( target = threadFunc ,
args = ( workQueue , isVerbose , printLock ) )
thread . start ( )
threads . append ( thread )
2016-07-10 08:33:27 -07:00
2016-07-12 21:59:09 -07:00
# Wait for worker threads to finish
for i in range ( 0 , jobs ) :
threads [ i ] . join ( )
2016-07-10 08:33:27 -07:00
if __name__ == " __main__ " :
main ( )