#!/usr/bin/env python3 """Syncs files from a source dir to an output dir. Reads a list of files from a response file, copies them from the source dir to the output dir, and removes files in the output dir that are not in the list (except for files passed via --except).""" import argparse import os import shlex import sys def read(filename): with open(filename) as f: return f.read() def main(): parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter ) parser.add_argument( "--stamp", required=True, help="name of a file whose mtime is updated on run" ) parser.add_argument("--source-dir", required=True) parser.add_argument("--output-dir", required=True) parser.add_argument("--except", dest="exceptions", action="append", default=[]) parser.add_argument("rspfile") args = parser.parse_args() files = shlex.split(read(args.rspfile)) # Copy files from source dir to output dir. for f in files: src = os.path.join(args.source_dir, f) dst = os.path.join(args.output_dir, f) os.makedirs(os.path.dirname(dst), exist_ok=True) data = read(src) if not os.path.exists(dst) or read(dst) != data: with open(dst, "w") as dst_file: dst_file.write(data) # Remove files in output dir that are not in the list. want = set(files) exceptions = set(args.exceptions) for root, dirs, filenames in os.walk(args.output_dir): for filename in filenames: filepath = os.path.join(root, filename) relpath = os.path.relpath(filepath, args.output_dir) if relpath not in want and relpath not in exceptions: os.remove(filepath) open(args.stamp, "w") # Update mtime on stamp file. if __name__ == "__main__": sys.exit(main())