diff options
author | Steve Fung <stevefung@google.com> | 2016-05-04 17:39:53 -0700 |
---|---|---|
committer | Steve Fung <stevefung@google.com> | 2016-05-12 20:13:12 +0000 |
commit | 4e6af545dba4eb518bbdf1fd587c065621bd3a62 (patch) | |
tree | 74293d046adf4d47ad329d5e840ee47dcdc06420 | |
parent | 0a1e8462677c5aafcb0c867b398691c9d63855df (diff) | |
download | bdk-4e6af545dba4eb518bbdf1fd587c065621bd3a62.tar.gz |
Add script to clean up orphaned .pyc files.
Whenever we refactor file names, it often leaves behind a .pyc file.
These files still get discovered when running commands and unit
tests, and can lead to accidental failures.
Also add this script to run on PREUPLOAD. Since repo currently does
not provide a method of running hooks on a sync, this is the best
we can do at the moment.
Bug: 28053765
Test: `./tools/cleanup.py` lists my orphaned .pyc files.
Does not delete them unless inputting 'y' at the prompt.
Test: `./tools/cleanup.py --quiet --yes` automatically cleans
up all orphaned .pyc files.
Test: Orphaned .pyc files are cleaned up when uploading this CL.
Change-Id: I5c1cada450b448938d285c5802499a3a890fe215
-rw-r--r-- | PREUPLOAD.cfg | 1 | ||||
-rwxr-xr-x | tools/cleanup.py | 111 |
2 files changed, 112 insertions, 0 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 999d59d..2265f3b 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -1,4 +1,5 @@ [Hook Scripts] +cleanup = tools/cleanup.py --quiet --yes cli/lib/ unit_tests = python cli/lib/test_runner.py [Builtin Hooks] diff --git a/tools/cleanup.py b/tools/cleanup.py new file mode 100755 index 0000000..0fcb119 --- /dev/null +++ b/tools/cleanup.py @@ -0,0 +1,111 @@ +#!/usr/bin/python + +# +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +"""Cleans up any orphaned .pyc files in the tree.""" + + +from __future__ import print_function +import argparse +import fnmatch +import os +import sys + + +def get_user_input(prompt): + """Prompt a user for input and return the result.""" + print(prompt) + sys.stdout.flush() + result = sys.stdin.readline() + return result + + +def parse_args(argv): + """Parse the command line arguments. + + Args: + argv: The list of command line arguments to parse. + + Returns: + The populated namespace object returned from argparse.parse_args(..). + """ + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--quiet', action='store_true', + help='Do not print any output.') + parser.add_argument('--yes', action='store_true', + help='Do not prompt for confirmation.') + parser.add_argument('directory', nargs='?', + default=os.path.dirname( + os.path.dirname(os.path.realpath(__file__))), + help='The base directory to search.') + args = parser.parse_args(argv) + + if args.quiet and not args.yes: + parser.error( + 'Using the --quiet flag requires also using the --yes flag.') + + return args + + +def main(argv): + args = parse_args(argv) + + if args.quiet: + sys.stdout = open('/dev/null', 'w') + + matches = [] + failures = [] + for dirpath, _, filenames in os.walk(args.directory): + for filename in fnmatch.filter(filenames, '*.pyc'): + filepath = os.path.join(dirpath, filename) + # If a .pyc file does not have a corresponding .py file, add it + # to the list of matches. + if not os.path.isfile(filepath[:-1]): + matches.append(filepath) + + if not matches: + print('No orphaned .pyc files found.') + else: + print('Found the following orphaned .pyc files:') + print('\n'.join(' ' + f for f in matches)) + + if args.yes: + choice = 'Y' + else: + choice = get_user_input('Remove these files? (y/N)').strip().upper() + if choice == 'Y': + # Remove the matched files. Under certain circumstances, an + # OSError may be raised, so keep track of how many files have been + # successfully deleted. + count = 0 + for f in matches: + try: + os.remove(f) + count += 1 + except OSError: + failures.append(f) + if failures: + print('Could not remove:') + print('\n'.join(' ' + f for f in failures)) + print('{} files removed.'.format(count)) + + else: + print('Files not removed.') + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) |