# Simple python script used to # copy some libraries to the "target" directory # after Rust build # Note that Rust build should be run via "cargo make " command # in order to automate all the compile process import os from pathlib import Path import shutil import sys import filecmp # some config vars # format: (source, destination_name) SOURCE = ( ("resources/commands/", "resources/commands/"), ("resources/vosk/", "resources/vosk/"), ("resources/lib/", "lib/"), ("resources/keywords/", "resources/keywords/"), ("resources/rustpotter/", "resources/rustpotter/"), ("resources/sound/", "resources/sound/"), ("resources/models/", "resources/models/"), # vosk ("lib/windows/amd64/libgcc_s_seh-1.dll", None), ("lib/windows/amd64/libstdc++-6.dll", None), ("lib/windows/amd64/libvosk.dll", None), ("lib/windows/amd64/libvosk.lib", None), ("lib/windows/amd64/libwinpthread-1.dll", None), # pvrecorder ("lib/windows/amd64/libpv_recorder.dll", None), ) TARGET_DIRS = ( "target/debug", "target/release" ) ABS_PATH = os.getcwd() + "/" # flags force_overwrite = "--force" in sys.argv sync_mode = "--sync" in sys.argv if sync_mode: print("[*] Sync mode: will update changed files and remove orphans") def files_differ(src, dst): """check if two files differ by size or content""" if not os.path.isfile(dst): return True # quick check: size if os.path.getsize(src) != os.path.getsize(dst): return True # compare modification time (src newer = needs update) if os.path.getmtime(src) > os.path.getmtime(dst): return True return False def sync_directory(src_dir, dst_dir): """sync dst_dir to match src_dir: copy new/changed, remove orphans""" copied = 0 updated = 0 removed = 0 # walk source, copy new/changed files for root, dirs, files in os.walk(src_dir): rel_root = os.path.relpath(root, src_dir) dst_root = os.path.join(dst_dir, rel_root) if rel_root != "." else dst_dir # ensure dir exists os.makedirs(dst_root, exist_ok=True) for f in files: src_file = os.path.join(root, f) dst_file = os.path.join(dst_root, f) if not os.path.exists(dst_file): shutil.copy2(src_file, dst_file) copied += 1 elif files_differ(src_file, dst_file): shutil.copy2(src_file, dst_file) updated += 1 # walk destination, remove files/dirs not in source for root, dirs, files in os.walk(dst_dir, topdown=False): rel_root = os.path.relpath(root, dst_dir) src_root = os.path.join(src_dir, rel_root) if rel_root != "." else src_dir for f in files: dst_file = os.path.join(root, f) src_file = os.path.join(src_root, f) if not os.path.exists(src_file): os.remove(dst_file) print(f" [-] Removed orphan file: {os.path.relpath(dst_file, dst_dir)}") removed += 1 for d in dirs: dst_sub = os.path.join(root, d) src_sub = os.path.join(src_root, d) if not os.path.exists(src_sub): shutil.rmtree(dst_sub) print(f" [-] Removed orphan dir: {os.path.relpath(dst_sub, dst_dir)}") removed += 1 return copied, updated, removed def sync_file(src_path, dst_path): """sync a single file, returns (copied, updated)""" if not os.path.exists(dst_path): os.makedirs(os.path.dirname(dst_path), exist_ok=True) shutil.copy2(src_path, dst_path) return 1, 0 elif files_differ(src_path, dst_path): shutil.copy2(src_path, dst_path) return 0, 1 return 0, 0 for tdir in TARGET_DIRS: tdir = ABS_PATH + tdir if not Path(tdir).is_dir(): print("Skipping target, not a directory: ", tdir) continue for entry in SOURCE: if isinstance(entry, tuple): src, dest_name = entry else: src, dest_name = entry, None src_path = ABS_PATH + src if os.path.isdir(src_path): target_name = dest_name if dest_name else os.path.basename(src.rstrip('/')) full_target_dir_path = os.path.join(tdir, target_name) if sync_mode: # sync: update changed, add new, remove orphans if os.path.isdir(full_target_dir_path): c, u, r = sync_directory(src_path, full_target_dir_path) if c or u or r: print(f"[~] Synced: {src} -> {target_name} (+{c} new, ~{u} updated, -{r} removed)") else: print(f"[=] Up to date: {src} -> {target_name}") else: shutil.copytree(src_path, full_target_dir_path) print("[+] Directory copied: ", src, "->", target_name) elif os.path.isdir(full_target_dir_path): if force_overwrite: shutil.rmtree(full_target_dir_path) shutil.copytree(src_path, full_target_dir_path) print("[+] Directory overwritten: ", src, "->", target_name) else: print("[-] Directory already exists, skipping: ", src, "->", target_name) else: shutil.copytree(src_path, full_target_dir_path) print("[+] Directory copied: ", src, "->", target_name) elif os.path.isfile(src_path): target_name = dest_name if dest_name else os.path.basename(src) full_target_file_path = os.path.join(tdir, target_name) if sync_mode: c, u = sync_file(src_path, full_target_file_path) if c: print("[+] File copied: ", src, "->", target_name) elif u: print("[~] File updated: ", src, "->", target_name) else: print("[=] Up to date: ", src, "->", target_name) elif os.path.isfile(full_target_file_path): if force_overwrite: os.remove(full_target_file_path) shutil.copy(src_path, full_target_file_path) print("[+] File overwritten: ", src, "->", target_name) else: print("[-] File already exists, skipping: ", src, "->", target_name) else: shutil.copy(src_path, full_target_file_path) print("[+] File copied: ", src, "->", target_name) else: print("[?] Unknown entity to copy: ", src) print("Post compile build done.")