cowcopy/cowcopy.py

87 lines
2.7 KiB
Python

import argparse
from pathlib import Path
import os
SAFETY = 'jellyfin'
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument('source', type=Path)
parser.add_argument('dest', type=Path)
parser.add_argument('--dry', help='Only output changes', action="store_true")
return parser.parse_args()
def main(source: Path, dest: Path, dry: bool):
remove_deleted_files(source, dest, dry)
create_new_links(source, dest, dry)
def remove_deleted_files(source: Path, dest: Path, dry: bool):
for file in dest.iterdir():
if file.is_dir():
original_dir = source / file.name
if original_dir.is_dir():
remove_deleted_files(original_dir, file, dry)
else:
remove_deleted_files(original_dir, file, dry)
if dry:
print(f"Remove directory: {file}")
else:
file.rmdir() # will fail if files have since been created
elif file.is_file():
original_file = source / file.name
if not original_file.exists() or original_file.is_dir():
if SAFETY not in str(file):
raise Exception("Deletion path does not include jellyfin")
if dry:
print(f"Remove file: {file}")
else:
file.unlink()
def create_new_links(source: Path, dest: Path, dry: bool):
for file in source.iterdir():
if file.is_dir():
new_dest = dest / file.name
if not new_dest.exists():
if dry:
print(f"Create directory: {new_dest}")
else:
new_dest.mkdir()
elif new_dest.exists() and not new_dest.is_dir():
raise Exception("Directory expected")
create_new_links(file, new_dest, dry)
elif file.is_file():
new_file = dest / file.name
if not new_file.exists():
if dry:
print(f"Create file: {new_file}")
else:
try:
file.copy(new_file)
except AttributeError:
os.system(f'cp --reflink "{file}" "{new_file}"')
if __name__ == '__main__':
args = get_args()
source_directory = args.source
destination_directory = args.dest
dryrun = args.dry
if len(source_directory.parts) < 3 or len(destination_directory.parts) < 3:
raise Exception("Paths too short")
if dryrun:
print("Dry run - no changes will be made")
main(source_directory, destination_directory, dryrun)
if dryrun:
print("Dry run - no changes have been made")