Index: tools/copy_tree.py |
diff --git a/tools/copy_tree.py b/tools/copy_tree.py |
index da1cb6c8aa98a0384e7acd253efd29ecb9637956..7bb544649634ff7ba6fe14439fc5ebeaa98c2193 100755 |
--- a/tools/copy_tree.py |
+++ b/tools/copy_tree.py |
@@ -14,6 +14,11 @@ def ParseArgs(args): |
parser = argparse.ArgumentParser( |
description='A script to copy a file tree somewhere') |
+ parser.add_argument('--dry-run', '-d', |
+ dest='dryrun', |
+ default=False, |
+ action='store_true', |
+ help='Print the paths of the source files, but do not copy anything.') |
parser.add_argument('--exclude_patterns', '-e', |
type=str, |
help='Patterns to exclude [passed to shutil.copytree]') |
@@ -21,11 +26,11 @@ def ParseArgs(args): |
dest="copy_from", |
type=str, |
required=True, |
- help='Source tree root') |
+ help='Source directory') |
parser.add_argument('--to', '-t', |
type=str, |
required=True, |
- help='Destination') |
+ help='Destination directory') |
return parser.parse_args(args) |
@@ -37,18 +42,60 @@ def ValidateArgs(args): |
return True |
+def CopyTree(src, dst, dryrun=False, symlinks=False, ignore=None): |
+ names = os.listdir(src) |
+ if ignore is not None: |
+ ignored_names = ignore(src, names) |
+ else: |
+ ignored_names = set() |
+ |
+ if not dryrun: |
+ os.makedirs(dst) |
+ errors = [] |
+ for name in names: |
+ if name in ignored_names: |
+ continue |
+ srcname = os.path.join(src, name) |
+ dstname = os.path.join(dst, name) |
+ try: |
+ if os.path.isdir(srcname): |
+ CopyTree(srcname, dstname, dryrun, symlinks, ignore) |
+ else: |
+ if dryrun: |
+ print srcname |
+ else: |
+ shutil.copy(srcname, dstname) |
+ except (IOError, os.error) as why: |
+ errors.append((srcname, dstname, str(why))) |
+ # catch the Error from the recursive CopyTree so that we can |
+ # continue with other files |
+ except Error as err: |
+ errors.extend(err.args[0]) |
+ try: |
+ if not dryrun: |
+ shutil.copystat(src, dst) |
+ except WindowsError: |
+ # can't copy file access times on Windows |
+ pass |
+ except OSError as why: |
+ errors.extend((src, dst, str(why))) |
+ if errors: |
+ raise Error(errors) |
+ |
+ |
def Main(argv): |
args = ParseArgs(argv) |
if not ValidateArgs(args): |
return -1 |
+ |
if os.path.exists(args.to): |
shutil.rmtree(args.to) |
if args.exclude_patterns == None: |
- shutil.copytree(args.copy_from, args.to) |
+ CopyTree(args.copy_from, args.to, dryrun=args.dryrun) |
else: |
patterns = args.exclude_patterns.split(',') |
- shutil.copytree(args.copy_from, args.to, |
- ignore=shutil.ignore_patterns(tuple(patterns))) |
+ CopyTree(args.copy_from, args.to, dryrun=args.dryrun, |
+ ignore=shutil.ignore_patterns(*patterns)) |
return 0 |