mirror of https://github.com/ARMmbed/mbed-os.git
226 lines
6.5 KiB
Python
226 lines
6.5 KiB
Python
#!/usr/bin/env python -u
|
|
|
|
import subprocess
|
|
import time
|
|
import sys
|
|
import argparse
|
|
|
|
# == Script configuration ==
|
|
|
|
# TODO: Refactor this into a preferences file
|
|
|
|
# We want to process files with these extensions.
|
|
sourceFileExtensions = [ 'java', 'rb', 'php', 'js', 'scala', 'c', 'cpp', 'h', 'py']
|
|
|
|
|
|
|
|
# == Command line options ==
|
|
|
|
parser = argparse.ArgumentParser(description='Remove trailing whitespaces from source files', formatter_class=argparse.RawTextHelpFormatter)
|
|
|
|
# ==== Generic options ====
|
|
parser.add_argument('--debug', dest='debug', action='store_true',
|
|
help='Enable debug mode')
|
|
parser.add_argument('--ext', '-e', dest='extensions', action='append',
|
|
help='Add an additional file extension that should be processed')
|
|
|
|
|
|
# ==== File mode options ====
|
|
group = parser.add_argument_group('"Specific files"-mode')
|
|
group.add_argument('files', nargs='*', metavar='FILE',
|
|
help='Specifies files to be processed.')
|
|
|
|
# ==== Git mode options ====
|
|
group = parser.add_argument_group('Git-mode', 'NOTE: Always operates recursively due to a limitation in git ls-files!')
|
|
group.add_argument('--force-git', dest='forceGit', action='store_true')
|
|
group.add_argument('--not-only-modified', '-m', dest='onlyModified', action='store_false',
|
|
help='Process only files that have been modified')
|
|
|
|
|
|
# ==== Find mode options ====
|
|
group = parser.add_argument_group('Find-mode', 'Find files to process using the "find"-command')
|
|
group.add_argument('--force-find', dest='forceFind', action='store_true')
|
|
|
|
|
|
group.add_argument('--recursive', '-r', dest='recursive', action='store_true')
|
|
|
|
|
|
|
|
# == Initialization ==
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Used to ignore subprocess output as explained
|
|
# [here](http://mail.python.org/pipermail/python-dev/2006-June/066111.html).
|
|
FNULL = open('/dev/null', 'w')
|
|
|
|
# Are we currently in a directory under Git version control?
|
|
# [(See Stackoverflow)](http://stackoverflow.com/a/2044677/124257)
|
|
gitRevParse = subprocess.Popen(["git", "rev-parse"], stdout=FNULL, stderr=FNULL)
|
|
gitRevParse.wait()
|
|
inGitDir = gitRevParse.returncode == 0
|
|
|
|
|
|
|
|
# == List command generation ==
|
|
|
|
# These functions generate the shell commands that will be used to gather
|
|
# a the list of files that should be processed. Only one of them is called,
|
|
# depending on the mode `mow.py` is running in.
|
|
|
|
def gitLsFilesCommand(wildcards, onlyModified=False):
|
|
command = ["git", "ls-files"]
|
|
|
|
if onlyModified:
|
|
command.append('--modified')
|
|
|
|
for wildcard in wildcards:
|
|
command.append(wildcard)
|
|
|
|
return command
|
|
|
|
|
|
def findFilesCommand(wildcards, paths=['.'], recursive=True):
|
|
command = ["find"]
|
|
command.extend(paths)
|
|
|
|
command.extend(['-type', 'f'])
|
|
|
|
if not recursive:
|
|
command.extend(['-depth', '1'])
|
|
|
|
command.append('(')
|
|
for wildcard in wildcards:
|
|
command.extend(['-name', wildcard, '-or'])
|
|
|
|
command.pop() # Remove the dangling "-or" at the end
|
|
command.append(')')
|
|
|
|
return command
|
|
|
|
|
|
def specificFilesCommand(files):
|
|
command = ['printf']
|
|
|
|
filesString = ""
|
|
for file in files:
|
|
filesString += "%s\n" % file
|
|
|
|
return command
|
|
|
|
|
|
# == Processing functions ==
|
|
|
|
# This is where the actual space trimming happens.
|
|
|
|
def processFiles(files, listFilesCommand, debug=False):
|
|
sed = None
|
|
|
|
if(debug):
|
|
print "Data that would be passed to sed:"
|
|
sed = subprocess.Popen([ 'cat' ], stdin=subprocess.PIPE)
|
|
else:
|
|
sys.stdout.write("Processing files")
|
|
# Don't remove the empty argument after -i
|
|
# [as Mac OS X doesn't allow -i without parameter](http://blog.mpdaugherty.com/2010/05/27/difference-with-sed-in-place-editing-on-mac-os-x-vs-linux/).
|
|
sed = subprocess.Popen([ 'xargs', 'sed', '-i', '', '-e', 's/[[:space:]]*$//' ], stdin=subprocess.PIPE)
|
|
|
|
while len(files) > 0:
|
|
sed.stdin.writelines(files.pop())
|
|
|
|
if not debug:
|
|
sys.stdout.write('.')
|
|
|
|
if not debug:
|
|
print ' Done!'
|
|
|
|
|
|
|
|
# == User interaction functions ==
|
|
|
|
# These functions present the interactive dialogs to the user.
|
|
|
|
def askProcessFiles(files, listFilesCommand):
|
|
options = {
|
|
'y': lambda a, b: processFiles(a, b, args.debug),
|
|
'n': lambda a, b: exit("Bye!"),
|
|
'f': lambda a, b: lambdaPrint(a) or True,
|
|
'c': lambda a, b: lambdaPrint(b) or True,
|
|
'd': lambda a, b: printDebug(a, b) or True,
|
|
'q': lambda a, b: exit("Bye!"),
|
|
# The ? is handled in the eval-loop, and thus doesn't need a callback function.
|
|
'?': None
|
|
}
|
|
|
|
choice = None
|
|
while choice == None:
|
|
sys.stdout.write("\033[1;94m" + "About to process %d files! Continue? [y,n,f,c,q,?] \033[0m" % len(files))
|
|
choice = raw_input()
|
|
|
|
if not choice in options.keys() or choice == '?':
|
|
choice = None
|
|
printProcessHelp()
|
|
else:
|
|
result = options[choice](files, listFilesCommand)
|
|
if result: # We continue the loop if the callback functions returns True.
|
|
choice = None
|
|
|
|
|
|
def lambdaPrint(x):
|
|
print x
|
|
|
|
|
|
def printDebug(files, listFilesCommand):
|
|
print "\nArguments as found by argparse:"
|
|
print args
|
|
|
|
print "\nFiles to be processed:"
|
|
print files
|
|
|
|
print "\nCommand that generated the file list:"
|
|
print listFilesCommand
|
|
|
|
|
|
|
|
def printProcessHelp():
|
|
print "\033[1;91m" + """y - Start processing files
|
|
n - Abort execution, equivalent to "q"
|
|
f - List files to be processed
|
|
c - Show command used to generate the file list
|
|
d - Print debug information
|
|
q - Abort execution
|
|
? - Print help \033[0m"""
|
|
|
|
|
|
|
|
# == Script execution ==
|
|
|
|
# Generate wildcards from the extensions that should be processed
|
|
if args.extensions != None:
|
|
sourceFileExtensions.extend(args.extensions)
|
|
|
|
sourceFileWildcards = [ "*.%s" % x for x in sourceFileExtensions]
|
|
|
|
|
|
# This is where we decide which functions are actually invoked depending on input parameters.
|
|
listFilesCommand = None
|
|
if args.files != None and len(args.files) > 0:
|
|
listFilesCommand = specificFilesCommand(args.files)
|
|
|
|
elif args.forceGit:
|
|
if not args.recursive:
|
|
exit("Git-mode does not currently support non-recursive processing! Exiting.")
|
|
|
|
if not inGitDir:
|
|
exit("Not a git repository (or any of the parent directories)! Exiting.")
|
|
listFilesCommand = gitLsFilesCommand(sourceFileWildcards, onlyModified=args.onlyModified)
|
|
|
|
else:
|
|
listFilesCommand = findFilesCommand(sourceFileWildcards, recursive=args.recursive)
|
|
|
|
|
|
# **Process those files!**
|
|
files = subprocess.Popen(listFilesCommand, stdout=subprocess.PIPE).stdout.readlines()
|
|
askProcessFiles(files, listFilesCommand)
|
|
|