1#!/usr/bin/env python 2# Copyright (c) 2012 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Copies test data files or directories into a given output directory.""" 7 8from __future__ import print_function 9 10import optparse 11import os 12import shutil 13import sys 14 15class WrongNumberOfArgumentsException(Exception): 16 pass 17 18def EscapePath(path): 19 """Returns a path with spaces escaped.""" 20 return path.replace(" ", "\\ ") 21 22def ListFilesForPath(path): 23 """Returns a list of all the files under a given path.""" 24 output = [] 25 # Ignore revision control metadata directories. 26 if (os.path.basename(path).startswith('.git') or 27 os.path.basename(path).startswith('.svn')): 28 return output 29 30 # Files get returned without modification. 31 if not os.path.isdir(path): 32 output.append(path) 33 return output 34 35 # Directories get recursively expanded. 36 contents = os.listdir(path) 37 for item in contents: 38 full_path = os.path.join(path, item) 39 output.extend(ListFilesForPath(full_path)) 40 return output 41 42def CalcInputs(inputs): 43 """Computes the full list of input files for a set of command-line arguments. 44 """ 45 # |inputs| is a list of paths, which may be directories. 46 output = [] 47 for input in inputs: 48 output.extend(ListFilesForPath(input)) 49 return output 50 51def CopyFiles(relative_filenames, output_basedir): 52 """Copies files to the given output directory.""" 53 for file in relative_filenames: 54 relative_dirname = os.path.dirname(file) 55 output_dir = os.path.join(output_basedir, relative_dirname) 56 output_filename = os.path.join(output_basedir, file) 57 58 # In cases where a directory has turned into a file or vice versa, delete it 59 # before copying it below. 60 if os.path.exists(output_dir) and not os.path.isdir(output_dir): 61 os.remove(output_dir) 62 if os.path.exists(output_filename) and os.path.isdir(output_filename): 63 shutil.rmtree(output_filename) 64 65 if not os.path.exists(output_dir): 66 os.makedirs(output_dir) 67 shutil.copy(file, output_filename) 68 69def DoMain(argv): 70 parser = optparse.OptionParser() 71 usage = 'Usage: %prog -o <output_dir> [--inputs] [--outputs] <input_files>' 72 parser.set_usage(usage) 73 parser.add_option('-o', dest='output_dir') 74 parser.add_option('--inputs', action='store_true', dest='list_inputs') 75 parser.add_option('--outputs', action='store_true', dest='list_outputs') 76 options, arglist = parser.parse_args(argv) 77 78 if len(arglist) == 0: 79 raise WrongNumberOfArgumentsException('<input_files> required.') 80 81 files_to_copy = CalcInputs(arglist) 82 escaped_files = [EscapePath(x) for x in CalcInputs(arglist)] 83 if options.list_inputs: 84 return '\n'.join(escaped_files) 85 86 if not options.output_dir: 87 raise WrongNumberOfArgumentsException('-o required.') 88 89 if options.list_outputs: 90 outputs = [os.path.join(options.output_dir, x) for x in escaped_files] 91 return '\n'.join(outputs) 92 93 CopyFiles(files_to_copy, options.output_dir) 94 return 95 96def main(argv): 97 try: 98 result = DoMain(argv[1:]) 99 except WrongNumberOfArgumentsException as e: 100 print(e, file=sys.stderr) 101 return 1 102 if result: 103 print(result) 104 return 0 105 106if __name__ == '__main__': 107 sys.exit(main(sys.argv)) 108