|
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 |
|
8 import optparse |
|
9 import os |
|
10 import shutil |
|
11 import sys |
|
12 |
|
13 class WrongNumberOfArgumentsException(Exception): |
|
14 pass |
|
15 |
|
16 def ListFilesForPath(path): |
|
17 """Returns a list of all the files under a given path.""" |
|
18 output = [] |
|
19 # Ignore dotfiles and dot directories. |
|
20 # TODO(rohitrao): This will fail to exclude cases where the initial argument |
|
21 # is a relative path that starts with a dot. |
|
22 if os.path.basename(path).startswith('.'): |
|
23 return output |
|
24 |
|
25 # Files get returned without modification. |
|
26 if not os.path.isdir(path): |
|
27 output.append(path) |
|
28 return output |
|
29 |
|
30 # Directories get recursively expanded. |
|
31 contents = os.listdir(path) |
|
32 for item in contents: |
|
33 full_path = os.path.join(path, item) |
|
34 output.extend(ListFilesForPath(full_path)) |
|
35 return output |
|
36 |
|
37 def CalcInputs(inputs): |
|
38 """Computes the full list of input files for a set of command-line arguments. |
|
39 """ |
|
40 # |inputs| is a list of strings, each of which may contain muliple paths |
|
41 # separated by spaces. |
|
42 output = [] |
|
43 for input in inputs: |
|
44 tokens = input.split() |
|
45 for token in tokens: |
|
46 output.extend(ListFilesForPath(token)) |
|
47 return output |
|
48 |
|
49 def CopyFiles(relative_filenames, output_basedir): |
|
50 """Copies files to the given output directory.""" |
|
51 for file in relative_filenames: |
|
52 relative_dirname = os.path.dirname(file) |
|
53 output_dir = os.path.join(output_basedir, relative_dirname) |
|
54 output_filename = os.path.join(output_basedir, file) |
|
55 |
|
56 # In cases where a directory has turned into a file or vice versa, delete it |
|
57 # before copying it below. |
|
58 if os.path.exists(output_dir) and not os.path.isdir(output_dir): |
|
59 os.remove(output_dir) |
|
60 if os.path.exists(output_filename) and os.path.isdir(output_filename): |
|
61 shutil.rmtree(output_filename) |
|
62 |
|
63 if not os.path.exists(output_dir): |
|
64 os.makedirs(output_dir) |
|
65 shutil.copy(file, output_filename) |
|
66 |
|
67 def DoMain(argv): |
|
68 parser = optparse.OptionParser() |
|
69 usage = 'Usage: %prog -o <output_dir> [--inputs] [--outputs] <input_files>' |
|
70 parser.set_usage(usage) |
|
71 parser.add_option('-o', dest='output_dir') |
|
72 parser.add_option('--inputs', action='store_true', dest='list_inputs') |
|
73 parser.add_option('--outputs', action='store_true', dest='list_outputs') |
|
74 options, arglist = parser.parse_args(argv) |
|
75 |
|
76 if len(arglist) == 0: |
|
77 raise WrongNumberOfArgumentsException('<input_files> required.') |
|
78 |
|
79 files_to_copy = CalcInputs(arglist) |
|
80 if options.list_inputs: |
|
81 return '\n'.join(files_to_copy) |
|
82 |
|
83 if not options.output_dir: |
|
84 raise WrongNumberOfArgumentsException('-o required.') |
|
85 |
|
86 if options.list_outputs: |
|
87 outputs = [os.path.join(options.output_dir, x) for x in files_to_copy] |
|
88 return '\n'.join(outputs) |
|
89 |
|
90 CopyFiles(files_to_copy, options.output_dir) |
|
91 return |
|
92 |
|
93 def main(argv): |
|
94 try: |
|
95 result = DoMain(argv[1:]) |
|
96 except WrongNumberOfArgumentsException, e: |
|
97 print >>sys.stderr, e |
|
98 return 1 |
|
99 if result: |
|
100 print result |
|
101 return 0 |
|
102 |
|
103 if __name__ == '__main__': |
|
104 sys.exit(main(sys.argv)) |