from datetime import datetime import os import shutil import git import argparse import core.file_utils as file_utils from git.repo import Repo from core.argparse_utils import add_toggle_opt from core.file_utils import SparkPaths def _exit(code=0, msg=None): if msg is not None: print(msg) exit(code) def _get_arg_parser(): parser = argparse.ArgumentParser(description='Save git-changed files') parser.add_argument( '--o', '--output-dir', metavar='path', type=str, nargs=1, help='The directory in which to save files') add_toggle_opt(parser, 'modified', help='Backup modified files') add_toggle_opt(parser, 'untracked', help='Backup untracked files') parser.add_argument( '-p', '--path', metavar='targets', type=str, action='append', nargs='+', help='The path(s) whose changes to save') parser.set_defaults(modified=True, untracked=False) return parser def _main(): parser = _get_arg_parser() args = parser.parse_args() repo = Repo(SparkPaths.root()) change_types = [] if args.modified: change_types.append('M') if args.untracked: change_types.append('U') if len(change_types) == 0: _exit(1, 'No change types specified (no files would be saved)') paths = args.path or [['src'], ['tools']] # flatten paths print(args.path) print(repo.working_dir[-24:]) paths = [ os.path.realpath(path)[len(repo.working_dir) + 1:] for path_arg in paths for path in path_arg ] print(f'Evaluating: {", ".join(paths)}') diff_items = repo.index.diff(None, paths=paths) files_to_copy = [] for di in diff_items: if type(di) is not git.Diff: continue if di.change_type not in change_types: continue files_to_copy.append(di.a_path) if 'U' in change_types: for u in repo.untracked_files: if any([os.path.commonpath([u, p]) == p for p in paths]): files_to_copy.append(u) dest = os.path.join( SparkPaths.root(), '.tmp', file_utils.fmt_datetime_suffix()) dest = os.path.realpath(dest) dest = file_utils.get_unique_path(dest) file_utils.create_dir(dest) print(f'Copying files to {dest}') for f in files_to_copy: f = os.path.normpath(f) f = os.path.join(os.path.normpath(repo.working_dir), f) dname = os.path.dirname(f)[len(repo.working_dir) + 1:] fdest = os.path.join(dest, dname) file_utils.create_dir(fdest) print(f'copy {f} ({dname})-> {fdest}') shutil.copy(f, fdest) if __name__ == '__main__': _main()