""" Imperial Rclone Installer & Path Resolver rclone 바이너리를 자동으로 감지하거나 다운로드합니다. """ import os import sys import platform import subprocess # Windows: %USERPROFILE%\.rclone\rclone.exe / 기타: ~/.rclone/rclone if platform.system() == "Windows": RCLONE_EXE = os.path.join(os.path.expanduser("~"), ".rclone", "rclone.exe") else: RCLONE_EXE = os.path.join(os.path.expanduser("~"), ".rclone", "rclone") def _rclone_in_path() -> str | None: """PATH에서 rclone 실행 파일 경로를 반환합니다.""" try: result = subprocess.run( ["where" if platform.system() == "Windows" else "which", "rclone"], capture_output=True, text=True, timeout=5, encoding='utf-8', errors='replace' ) if result.returncode == 0: return result.stdout.strip().splitlines()[0] except Exception: pass return None def _ensure_boto3() -> bool: """boto3가 설치돼 있는지 확인하고, 없으면 자동 설치합니다.""" try: import boto3 return True except ImportError: pass print("[Imperial Setup] boto3 미설치 감지 — R2 직접 접속을 위해 자동 설치합니다...") try: result = subprocess.run( [sys.executable, "-m", "pip", "install", "boto3", "--quiet"], capture_output=True, text=True, timeout=120, encoding='utf-8', errors='replace' ) if result.returncode == 0: print("[Imperial Setup] boto3 설치 완료 ✓") return True else: print(f"[Imperial Setup] boto3 설치 실패: {result.stderr.strip()}") return False except Exception as e: print(f"[Imperial Setup] boto3 자동 설치 중 오류: {e}") return False def check_and_install_rclone() -> bool: """ rclone이 사용 가능한지 확인합니다. - PATH에 있으면 RCLONE_EXE를 해당 경로로 업데이트합니다. - ~/.rclone/ 에 있으면 그것을 사용합니다. - 없으면 경고 출력 후 boto3 폴백을 위해 boto3 자동 설치를 시도합니다. 반환값: rclone 사용 가능 여부 (bool) """ global RCLONE_EXE # boto3는 항상 보장 (rclone 유무와 무관하게 R2 폴백용으로 필요) _ensure_boto3() # 1. PATH 우선 탐색 path_exe = _rclone_in_path() if path_exe and os.path.exists(path_exe): RCLONE_EXE = path_exe print(f"[Rclone] PATH에서 발견: {RCLONE_EXE}") return True # 2. ~/.rclone/ 탐색 if os.path.exists(RCLONE_EXE): print(f"[Rclone] 로컬 설치 확인: {RCLONE_EXE}") return True # 3. 없음 — boto3 폴백으로 R2는 계속 사용 가능 print("[Rclone] rclone 미설치 — R2는 boto3로 직접 접속합니다. Google Drive 동기화만 비활성화됩니다.") return False