| OLD | NEW | 
|---|
| 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 os | 7 import os | 
| 8 import re | 8 import re | 
| 9 import shutil | 9 import shutil | 
| 10 import sys | 10 import sys | 
| 11 | 11 | 
| 12 def ParseArgs(args): | 12 def ParseArgs(args): | 
| 13   args = args[1:] | 13   args = args[1:] | 
| 14   parser = argparse.ArgumentParser( | 14   parser = argparse.ArgumentParser( | 
| 15       description='A script to copy a file tree somewhere') | 15       description='A script to copy a file tree somewhere') | 
| 16 | 16 | 
|  | 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.') | 
| 17   parser.add_argument('--exclude_patterns', '-e', | 22   parser.add_argument('--exclude_patterns', '-e', | 
| 18       type=str, | 23       type=str, | 
| 19       help='Patterns to exclude [passed to shutil.copytree]') | 24       help='Patterns to exclude [passed to shutil.copytree]') | 
| 20   parser.add_argument('--from', '-f', | 25   parser.add_argument('--from', '-f', | 
| 21       dest="copy_from", | 26       dest="copy_from", | 
| 22       type=str, | 27       type=str, | 
| 23       required=True, | 28       required=True, | 
| 24       help='Source tree root') | 29       help='Source directory') | 
| 25   parser.add_argument('--to', '-t', | 30   parser.add_argument('--to', '-t', | 
| 26       type=str, | 31       type=str, | 
| 27       required=True, | 32       required=True, | 
| 28       help='Destination') | 33       help='Destination directory') | 
| 29 | 34 | 
| 30   return parser.parse_args(args) | 35   return parser.parse_args(args) | 
| 31 | 36 | 
| 32 | 37 | 
| 33 def ValidateArgs(args): | 38 def ValidateArgs(args): | 
| 34   if not os.path.isdir(args.copy_from): | 39   if not os.path.isdir(args.copy_from): | 
| 35     print "--from argument must refer to a directory" | 40     print "--from argument must refer to a directory" | 
| 36     return False | 41     return False | 
| 37   return True | 42   return True | 
| 38 | 43 | 
| 39 | 44 | 
|  | 45 def CopyTree(src, dst, dryrun=False, symlinks=False, ignore=None): | 
|  | 46   names = os.listdir(src) | 
|  | 47   if ignore is not None: | 
|  | 48     ignored_names = ignore(src, names) | 
|  | 49   else: | 
|  | 50     ignored_names = set() | 
|  | 51 | 
|  | 52   if not dryrun: | 
|  | 53     os.makedirs(dst) | 
|  | 54   errors = [] | 
|  | 55   for name in names: | 
|  | 56     if name in ignored_names: | 
|  | 57       continue | 
|  | 58     srcname = os.path.join(src, name) | 
|  | 59     dstname = os.path.join(dst, name) | 
|  | 60     try: | 
|  | 61       if os.path.isdir(srcname): | 
|  | 62         CopyTree(srcname, dstname, dryrun, symlinks, ignore) | 
|  | 63       else: | 
|  | 64         if dryrun: | 
|  | 65           print srcname | 
|  | 66         else: | 
|  | 67           shutil.copy(srcname, dstname) | 
|  | 68     except (IOError, os.error) as why: | 
|  | 69       errors.append((srcname, dstname, str(why))) | 
|  | 70     # catch the Error from the recursive CopyTree so that we can | 
|  | 71     # continue with other files | 
|  | 72     except Error as err: | 
|  | 73       errors.extend(err.args[0]) | 
|  | 74   try: | 
|  | 75     if not dryrun: | 
|  | 76       shutil.copystat(src, dst) | 
|  | 77   except WindowsError: | 
|  | 78     # can't copy file access times on Windows | 
|  | 79     pass | 
|  | 80   except OSError as why: | 
|  | 81     errors.extend((src, dst, str(why))) | 
|  | 82   if errors: | 
|  | 83     raise Error(errors) | 
|  | 84 | 
|  | 85 | 
| 40 def Main(argv): | 86 def Main(argv): | 
| 41   args = ParseArgs(argv) | 87   args = ParseArgs(argv) | 
| 42   if not ValidateArgs(args): | 88   if not ValidateArgs(args): | 
| 43     return -1 | 89     return -1 | 
|  | 90 | 
| 44   if os.path.exists(args.to): | 91   if os.path.exists(args.to): | 
| 45     shutil.rmtree(args.to) | 92     shutil.rmtree(args.to) | 
| 46   if args.exclude_patterns == None: | 93   if args.exclude_patterns == None: | 
| 47     shutil.copytree(args.copy_from, args.to) | 94     CopyTree(args.copy_from, args.to, dryrun=args.dryrun) | 
| 48   else: | 95   else: | 
| 49     patterns = args.exclude_patterns.split(',') | 96     patterns = args.exclude_patterns.split(',') | 
| 50     shutil.copytree(args.copy_from, args.to, | 97     CopyTree(args.copy_from, args.to, dryrun=args.dryrun, | 
| 51                     ignore=shutil.ignore_patterns(tuple(patterns))) | 98              ignore=shutil.ignore_patterns(*patterns)) | 
| 52   return 0 | 99   return 0 | 
| 53 | 100 | 
| 54 | 101 | 
| 55 if __name__ == '__main__': | 102 if __name__ == '__main__': | 
| 56   sys.exit(Main(sys.argv)) | 103   sys.exit(Main(sys.argv)) | 
| OLD | NEW | 
|---|