import os import platform import subprocess from config_loader import CONFIG ######################################################## def get_current_os(): system = platform.system().lower() if system == "darwin": return "mac" return system ######################################################## def get_mount_point(): current_os = get_current_os() return CONFIG.smb.mount_points.get(current_os) ######################################################## def esta_montado(mount_point): """Verifica si el punto de montaje ya está activo.""" if get_current_os() == "windows": return os.path.exists(mount_point) return os.path.ismount(mount_point) or os.path.exists(os.path.join(mount_point, ".mounted_check")) # Simplificado ######################################################## def montar_smb(): """Intenta montar la unidad SMB según el SO.""" mount_point = get_mount_point() current_os = get_current_os() if not mount_point: print(" ⚠️ No hay punto de montaje configurado para este SO.") return False if esta_montado(mount_point): # print(f" ✅ SMB ya montado en: {mount_point}") return True # En Windows no creamos la carpeta del punto de montaje (es una unidad virtual) if current_os != "windows" and not os.path.exists(mount_point): os.makedirs(mount_point) smb = CONFIG.smb current_os = get_current_os() try: if current_os == "mac": # mount_smbfs //user:pass@server/share mount_point cmd = f"mount_smbfs //'{smb.username}':'{smb.password}'@{smb.server}/{smb.share} {mount_point}" subprocess.run(cmd, shell=True, check=True, capture_output=True) elif current_os == "linux": # mount -t cifs //server/share mount_point -o username=user,password=pass cmd = f"sudo mount -t cifs //{smb.server}/{smb.share} {mount_point} -o username={smb.username},password={smb.password}" subprocess.run(cmd, shell=True, check=True, capture_output=True) elif current_os == "windows": # net use S: \\server\share /user:user pass ruta_smb = f"\\\\{smb.server}\\{smb.share}" cmd = [ "net", "use", mount_point, ruta_smb, smb.password, f"/user:{smb.username}", "/persistent:no" ] subprocess.run(cmd, check=True, capture_output=True) print(f" ✅ SMB montado exitosamente en: {mount_point}") return True except Exception as e: print(f" ⚠️ Error montando SMB: {e}") return False ######################################################## def sincronizar_a_smb(ruta_local, smb_subfolder): """Sincroniza archivos hacia el recurso SMB montado según el SO.""" if not montar_smb(): print(" ❌ No se pudo sincronizar: SMB no montado.") return False mount_point = get_mount_point() current_os = get_current_os() # Normalizar punto de montaje para Windows (asegurar S:\ en lugar de S:) if current_os == "windows" and mount_point.endswith(":") and len(mount_point) == 2: mount_point += "\\" subfolder = smb_subfolder.lstrip('/') ruta_destino = os.path.normpath(os.path.join(mount_point, subfolder)) if not os.path.exists(ruta_destino): os.makedirs(ruta_destino) print(f" 📁 Carpeta de destino creada en SMB: {ruta_destino}") source = os.path.abspath(ruta_local) destination = os.path.abspath(ruta_destino) print(f" 🚀 Sincronizando a SMB ({current_os.upper()}): {ruta_destino}...") try: if current_os in ["mac", "linux"]: # Usar rsync en sistemas Unix # El / al final del source indica copiar contenido cmd = ["rsync", "-av", "--remove-source-files", source + "/", destination + "/"] subprocess.run(cmd, check=True, capture_output=True, text=True) elif current_os == "windows": # Usar shutil de Python (sin dependencias externas) import shutil for archivo in os.listdir(source): src_path = os.path.join(source, archivo) dst_path = os.path.join(destination, archivo) if os.path.isfile(src_path): # shutil.move maneja copia y borrado incluso entre discos diferentes if os.path.exists(dst_path): os.remove(dst_path) shutil.move(src_path, dst_path) elif os.path.isdir(src_path): # Para carpetas, usamos copytree + rmtree o move if os.path.exists(dst_path): shutil.rmtree(dst_path) shutil.move(src_path, dst_path) print(f" ✅ Sincronización completada.") return True except Exception as e: print(f" ❌ Error en la sincronización: {e}") return False ########################################################