#!/usr/bin/python # Copyright 2017 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Command line tool to pack audio related modules into a zip file.""" import argparse import logging import os import subprocess MODULES = ['audio_quality_measurement.py', 'audio_data.py', 'audio_analysis.py'] ENTRY = '__main__.py' ENTRY_TARGET = 'check_quality.py' def add_args(parser): """Adds command line arguments.""" parser.add_argument('-d', '--debug', action='store_true', default=False, help='Show debug message.') parser.add_argument('-o', '--out', type=str, default='audio_quality.zip', help='Output file name. Default is audio_quality.zip.') parser.add_argument('-s', '--skip-cleanup', action='store_true', default=False, help='Skip cleaning up temporary files. Default is False') def parse_args(parser): """Parses args. @param parser: An argparse.ArgumentParser. @returns: The namespace parsed from command line arguments. """ args = parser.parse_args() return args def create_link(): """Creates a symbolic link from ENTRY to ENTRY_TARGET. With this symlink, python can execute the zip file directly to execute ENTRY_TARGET. """ command = ['ln', '-sf', ENTRY_TARGET, ENTRY] logging.debug('Link command: %s', command) subprocess.check_call(command) def pack_files(out_file): """Packs audio related modules into a zip file. Packs audio related modules in MODULES into a zip file. Packs the symlink pointing to ENTRY_TARGET. @param out_file: Zip file name. """ command = ['zip'] command.append(out_file) command += MODULES command.append(ENTRY) command.append(ENTRY_TARGET) logging.debug('Zip command: %s', command) subprocess.check_call(command) def check_packed_file(out_file): """Checks the packed file can be executed by python. @param out_file: Zip file name. """ command = ['python', out_file, '--help'] logging.debug('Check command: %s', command) output = subprocess.check_output(command) logging.debug('output: %s', output) def cleanup(): """Cleans up the symobolic link.""" if os.path.exists(ENTRY): os.unlink(ENTRY) def repo_is_dirty(): """Checks if a repo is dirty by git diff command. @returns: True if there are uncommitted changes. False otherwise. """ try: subprocess.check_call(['git', 'diff', '--quiet']) subprocess.check_call(['git', 'diff', '--cached', '--quiet']) except subprocess.CalledProcessError: return True return False def get_git_sha1(): """Returns git SHA-1 hash of HEAD. @returns: git SHA-1 has of HEAD with minimum length 9. """ return subprocess.check_output( ['git', 'rev-parse', '--short', 'HEAD']).strip() def append_name_with_git_hash(out_file): """Append the file with git SHA-1 hash. For out_file like ABC.xyz, append the name ABC with git SHA-1 of HEAD, like ABC_f4610bdd3.xyz. If current repo contains uncommitted changes, it will be ABC_f4610bdd3_dirty.xyz. """ basename, ext = os.path.splitext(out_file) basename += '_' basename += get_git_sha1() if repo_is_dirty(): basename += '_dirty' return basename + ext if __name__ == '__main__': parser = argparse.ArgumentParser( description='Pack audio related modules into a zip file.') add_args(parser) args = parse_args(parser) level = logging.DEBUG if args.debug else logging.INFO format = '%(asctime)-15s:%(levelname)s:%(pathname)s:%(lineno)d: %(message)s' logging.basicConfig(format=format, level=level) out_file = append_name_with_git_hash(args.out) try: create_link() pack_files(out_file) check_packed_file(out_file) finally: if not args.skip_cleanup: cleanup() logging.info('Packed file: %s', out_file)