Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: tools/copy_tree.py

Issue 2992353002: Invoke copy_tree.py only once to collect all input file lists. (Closed)
Patch Set: Cleanup Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sdk/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 2 # Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
3 # for details. All rights reserved. Use of this source code is governed by a 3 # for details. All rights reserved. Use of this source code is governed by a
4 # BSD-style license that can be found in the LICENSE file. 4 # BSD-style license that can be found in the LICENSE file.
5 5
6 import argparse 6 import argparse
7 import gn_helpers
7 import os 8 import os
8 import re 9 import re
9 import shutil 10 import shutil
10 import sys 11 import sys
11 12
12 def ParseArgs(args): 13 def ParseArgs(args):
13 args = args[1:] 14 args = args[1:]
14 parser = argparse.ArgumentParser( 15 parser = argparse.ArgumentParser(
15 description='A script to copy a file tree somewhere') 16 description='A script to copy a file tree somewhere')
16 17
17 parser.add_argument('--dry-run', '-d',
18 dest='dryrun',
19 default=False,
20 action='store_true',
21 help='Print the paths of the source files, but do not copy anything.')
22 parser.add_argument('--exclude_patterns', '-e', 18 parser.add_argument('--exclude_patterns', '-e',
23 type=str, 19 type=str,
24 help='Patterns to exclude [passed to shutil.copytree]') 20 help='Patterns to exclude [passed to shutil.copytree]')
25 parser.add_argument('--from', '-f', 21 parser.add_argument('--from', '-f',
26 dest="copy_from", 22 dest="copy_from",
27 type=str, 23 type=str,
28 required=True,
29 help='Source directory') 24 help='Source directory')
25 parser.add_argument('--gn', '-g',
26 dest='gn',
27 default=False,
28 action='store_true',
29 help='Output for GN for multiple sources, but do not copy anything.')
30 parser.add_argument('gn_paths',
31 metavar='name path ignore_pattern',
32 type=str,
33 nargs='*',
34 default=None,
35 help='When --gn is given, the specification of source paths to list.')
30 parser.add_argument('--to', '-t', 36 parser.add_argument('--to', '-t',
31 type=str, 37 type=str,
32 required=True,
33 help='Destination directory') 38 help='Destination directory')
34 39
35 return parser.parse_args(args) 40 return parser.parse_args(args)
36 41
37 42
38 def ValidateArgs(args): 43 def ValidateArgs(args):
39 if not os.path.isdir(args.copy_from): 44 if args.gn:
45 if args.exclude_patterns or args.copy_from or args.to:
46 print "--gn mode does not accept other switches"
47 return False
48 if not args.gn_paths:
49 print "--gn mode requires a list of source specifications"
50 return False
51 return True
52 if not args.copy_from or not os.path.isdir(args.copy_from):
40 print "--from argument must refer to a directory" 53 print "--from argument must refer to a directory"
41 return False 54 return False
55 if not args.to:
56 print "--to is required"
57 return False
42 return True 58 return True
43 59
44 60
45 def CopyTree(src, dst, dryrun=False, symlinks=False, ignore=None): 61 def CopyTree(src, dst, ignore=None):
46 names = os.listdir(src) 62 names = os.listdir(src)
47 if ignore is not None: 63 if ignore is not None:
48 ignored_names = ignore(src, names) 64 ignored_names = ignore(src, names)
49 else: 65 else:
50 ignored_names = set() 66 ignored_names = set()
51 67
52 if not dryrun: 68 os.makedirs(dst)
53 os.makedirs(dst)
54 errors = [] 69 errors = []
55 for name in names: 70 for name in names:
56 if name in ignored_names: 71 if name in ignored_names:
57 continue 72 continue
58 srcname = os.path.join(src, name) 73 srcname = os.path.join(src, name)
59 dstname = os.path.join(dst, name) 74 dstname = os.path.join(dst, name)
60 try: 75 try:
61 if os.path.isdir(srcname): 76 if os.path.isdir(srcname):
62 CopyTree(srcname, dstname, dryrun, symlinks, ignore) 77 CopyTree(srcname, dstname, ignore)
63 else: 78 else:
64 if dryrun: 79 shutil.copy(srcname, dstname)
65 print srcname
66 else:
67 shutil.copy(srcname, dstname)
68 except (IOError, os.error) as why: 80 except (IOError, os.error) as why:
69 errors.append((srcname, dstname, str(why))) 81 errors.append((srcname, dstname, str(why)))
70 # catch the Error from the recursive CopyTree so that we can 82 # catch the Error from the recursive CopyTree so that we can
71 # continue with other files 83 # continue with other files
72 except Error as err: 84 except Error as err:
73 errors.extend(err.args[0]) 85 errors.extend(err.args[0])
74 try: 86 try:
75 if not dryrun: 87 shutil.copystat(src, dst)
76 shutil.copystat(src, dst)
77 except WindowsError: 88 except WindowsError:
78 # can't copy file access times on Windows 89 # can't copy file access times on Windows
79 pass 90 pass
80 except OSError as why: 91 except OSError as why:
81 errors.extend((src, dst, str(why))) 92 errors.extend((src, dst, str(why)))
82 if errors: 93 if errors:
83 raise Error(errors) 94 raise Error(errors)
84 95
85 96
97 def ListTree(src, ignore=None):
98 names = os.listdir(src)
99 if ignore is not None:
100 ignored_names = ignore(src, names)
101 else:
102 ignored_names = set()
103
104 srcnames = []
105 for name in names:
106 if name in ignored_names:
107 continue
108 srcname = os.path.join(src, name)
109 if os.path.isdir(srcname):
110 srcnames.extend(ListTree(srcname, ignore))
111 else:
112 srcnames.append(srcname)
113 return srcnames
114
115
116 # source_dirs is organized such that sources_dirs[n] is the path for the source
117 # directory, and source_dirs[n+1] is a list of ignore patterns.
118 def SourcesToGN(source_dirs):
119 if len(source_dirs) % 2 != 0:
120 print "--gn list length should be a multiple of 2."
121 return False
122 data = []
123 for i in xrange(0, len(source_dirs), 2):
124 path = source_dirs[i]
125 ignores = source_dirs[i + 1]
126 if ignores in ["{}"]:
127 sources = ListTree(path)
128 else:
129 patterns = ignores.split(',')
130 sources = ListTree(path, ignore=shutil.ignore_patterns(*patterns))
131 data.append(sources)
132 scope_data = {"sources": data}
133 print gn_helpers.ToGNString(scope_data)
134 return True
135
136
86 def Main(argv): 137 def Main(argv):
87 args = ParseArgs(argv) 138 args = ParseArgs(argv)
88 if not ValidateArgs(args): 139 if not ValidateArgs(args):
89 return -1 140 return -1
90 141
91 if os.path.exists(args.to) and not args.dryrun: 142 if args.gn:
143 SourcesToGN(args.gn_paths)
144 return 0
145
146 if os.path.exists(args.to):
92 shutil.rmtree(args.to) 147 shutil.rmtree(args.to)
93 if args.exclude_patterns == None: 148 if args.exclude_patterns == None:
94 CopyTree(args.copy_from, args.to, dryrun=args.dryrun) 149 CopyTree(args.copy_from, args.to)
95 else: 150 else:
96 patterns = args.exclude_patterns.split(',') 151 patterns = args.exclude_patterns.split(',')
97 CopyTree(args.copy_from, args.to, dryrun=args.dryrun, 152 CopyTree(args.copy_from, args.to, ignore=shutil.ignore_patterns(*patterns))
98 ignore=shutil.ignore_patterns(*patterns))
99 return 0 153 return 0
100 154
101 155
102 if __name__ == '__main__': 156 if __name__ == '__main__':
103 sys.exit(Main(sys.argv)) 157 sys.exit(Main(sys.argv))
OLDNEW
« no previous file with comments | « sdk/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698