diff --git a/config.py b/config.py index 808f103..2fb5954 100644 --- a/config.py +++ b/config.py @@ -68,6 +68,9 @@ def setup_config(translator=None): 'updater_path': os.path.join(localappdata, "cursor-updater"), 'update_yml_path': os.path.join(localappdata, "Programs", "Cursor", "resources", "app-update.yml") } + # Create storage directory + os.makedirs(os.path.dirname(default_config['WindowsPaths']['storage_path']), exist_ok=True) + elif sys.platform == "darwin": default_config['MacPaths'] = { 'storage_path': os.path.abspath(os.path.expanduser("~/Library/Application Support/Cursor/User/globalStorage/storage.json")), @@ -77,17 +80,91 @@ def setup_config(translator=None): 'updater_path': os.path.expanduser("~/Library/Application Support/cursor-updater"), 'update_yml_path': "/Applications/Cursor.app/Contents/Resources/app-update.yml" } - elif sys.platform == "linux": - sudo_user = os.environ.get('SUDO_USER') - actual_home = f"/home/{sudo_user}" if sudo_user else os.path.expanduser("~") + # Create storage directory + os.makedirs(os.path.dirname(default_config['MacPaths']['storage_path']), exist_ok=True) + elif sys.platform == "linux": + # Get the actual user's home directory, handling both sudo and normal cases + current_user = os.getenv('USER') or os.getenv('USERNAME') or os.getenv('SUDO_USER') + if not current_user: + current_user = os.path.expanduser('~').split('/')[-1] + + actual_home = f"/home/{current_user}" + if not os.path.exists(actual_home): + actual_home = os.path.expanduser("~") + + # Define base config directory + config_base = os.path.join(actual_home, ".config") + + # Try both "Cursor" and "cursor" directory names + cursor_dir = None + for dir_name in ["Cursor", "cursor"]: + test_dir = os.path.join(config_base, dir_name) + if os.path.exists(test_dir): + cursor_dir = test_dir + break + + if not cursor_dir: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {translator.get('config.neither_cursor_nor_cursor_directory_found', config_base=config_base)}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('config.please_make_sure_cursor_is_installed_and_has_been_run_at_least_once')}{Style.RESET_ALL}") + + # Define Linux paths using the found cursor directory + storage_path = os.path.abspath(os.path.join(cursor_dir, "User/globalStorage/storage.json")) if cursor_dir else "" + storage_dir = os.path.dirname(storage_path) if storage_path else "" + + # Verify paths and permissions + try: + # Check storage directory + if storage_dir and not os.path.exists(storage_dir): + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {translator.get('config.storage_directory_not_found', storage_dir=storage_dir)}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('config.please_make_sure_cursor_is_installed_and_has_been_run_at_least_once')}{Style.RESET_ALL}") + + # Check storage.json with more detailed verification + if storage_path and os.path.exists(storage_path): + # Get file stats + try: + stat = os.stat(storage_path) + print(f"{Fore.GREEN}{EMOJI['INFO']} {translator.get('config.storage_file_found', storage_path=storage_path)}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['INFO']} {translator.get('config.file_size', stat.st_size)}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['INFO']} {translator.get('config.file_permissions', oct(stat.st_mode & 0o777))}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['INFO']} {translator.get('config.file_owner', stat.st_uid)}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['INFO']} {translator.get('config.file_group', stat.st_gid)}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('config.error_getting_file_stats', error=str(e))}{Style.RESET_ALL}") + + # Check if file is readable and writable + if not os.access(storage_path, os.R_OK | os.W_OK): + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('config.permission_denied', storage_path=storage_path)}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('config.try_running', current_user=current_user, storage_path=storage_path)}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('config.and', storage_path=storage_path)}{Style.RESET_ALL}") + + # Try to read the file to verify it's not corrupted + try: + with open(storage_path, 'r') as f: + content = f.read() + if not content.strip(): + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {translator.get('config.storage_file_is_empty', storage_path=storage_path)}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('config.please_make_sure_cursor_is_installed_and_has_been_run_at_least_once')}{Style.RESET_ALL}") + else: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('config.storage_file_is_valid_and_contains_data')}{Style.RESET_ALL}") + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('config.error_reading_storage_file', error=str(e))}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('config.the_file_might_be_corrupted_please_reinstall_cursor')}{Style.RESET_ALL}") + elif storage_path: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {translator.get('config.storage_file_not_found', storage_path=storage_path)}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('config.please_make_sure_cursor_is_installed_and_has_been_run_at_least_once')}{Style.RESET_ALL}") + + except (OSError, IOError) as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('config.error_checking_linux_paths', error=str(e))}{Style.RESET_ALL}") + + # Define all paths using the found cursor directory default_config['LinuxPaths'] = { - 'storage_path': os.path.abspath(os.path.join(actual_home, ".config/cursor/User/globalStorage/storage.json")), - 'sqlite_path': os.path.abspath(os.path.join(actual_home, ".config/cursor/User/globalStorage/state.vscdb")), - 'machine_id_path': os.path.expanduser("~/.config/cursor/machineid"), + 'storage_path': storage_path, + 'sqlite_path': os.path.abspath(os.path.join(cursor_dir, "User/globalStorage/state.vscdb")) if cursor_dir else "", + 'machine_id_path': os.path.join(cursor_dir, "machineid") if cursor_dir else "", 'cursor_path': get_linux_cursor_path(), - 'updater_path': os.path.expanduser("~/.config/cursor-updater"), - 'update_yml_path': "/Applications/Cursor.app/Contents/Resources/app-update.yml" + 'updater_path': os.path.join(config_base, "cursor-updater"), + 'update_yml_path': os.path.join(cursor_dir, "resources/app-update.yml") if cursor_dir else "" } # Read existing configuration and merge @@ -104,13 +181,13 @@ def setup_config(translator=None): config.set(section, option, str(value)) config_modified = True if translator: - print(f"{Fore.YELLOW}ℹ️ {translator.get('register.config_option_added', option=f'{section}.{option}')}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('register.config_option_added', option=f'{section}.{option}')}{Style.RESET_ALL}") if config_modified: with open(config_file, 'w', encoding='utf-8') as f: config.write(f) if translator: - print(f"{Fore.GREEN}✅ {translator.get('register.config_updated')}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('register.config_updated')}{Style.RESET_ALL}") else: for section, options in default_config.items(): config.add_section(section) @@ -120,15 +197,13 @@ def setup_config(translator=None): with open(config_file, 'w', encoding='utf-8') as f: config.write(f) if translator: - print(f"{Fore.GREEN}✅ {translator.get('register.config_created')}: {config_file}{Style.RESET_ALL}") + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('register.config_created')}: {config_file}{Style.RESET_ALL}") return config except Exception as e: if translator: - print(f"{Fore.RED}❌ {translator.get('register.config_setup_error', error=str(e))}{Style.RESET_ALL}") - else: - print(f"{Fore.RED}❌ Error setting up config: {e}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('register.config_setup_error', error=str(e))}{Style.RESET_ALL}") return None def print_config(config, translator=None): diff --git a/locales/en.json b/locales/en.json index 5fddde1..c3bef05 100644 --- a/locales/en.json +++ b/locales/en.json @@ -493,6 +493,27 @@ "configuration": "Configuration", "enabled": "Enabled", "disabled": "Disabled", - "config_directory": "Config Directory" + "config_directory": "Config Directory", + "neither_cursor_nor_cursor_directory_found": "Neither Cursor nor Cursor directory found in {config_base}", + "please_make_sure_cursor_is_installed_and_has_been_run_at_least_once": "Please make sure Cursor is installed and has been run at least once", + "storage_directory_not_found": "Storage directory not found: {storage_dir}", + "storage_file_found": "Storage file found: {storage_path}", + "file_size": "File size: {size}", + "file_permissions": "File permissions: {permissions}", + "file_owner": "File owner: {owner}", + "file_group": "File group: {group}", + "error_getting_file_stats": "Error getting file stats: {error}", + "permission_denied": "Permission denied: {storage_path}", + "try_running": "Try running 'cursor --help' to check if it's installed", + "and": "and", + "storage_file_is_empty": "Storage file is empty: {storage_path}", + "the_file_might_be_corrupted_please_reinstall_cursor": "The file might be corrupted, please reinstall Cursor", + "storage_file_not_found": "Storage file not found: {storage_path}", + "error_checking_linux_paths": "Error checking Linux paths: {error}", + "config_option_added": "Config option added: {option}", + "config_updated": "Config updated", + "config_created": "Config created: {config_file}", + "config_setup_error": "Error setting up config: {error}" + } } \ No newline at end of file diff --git a/locales/zh_cn.json b/locales/zh_cn.json index 910941a..05710fe 100644 --- a/locales/zh_cn.json +++ b/locales/zh_cn.json @@ -488,6 +488,27 @@ "configuration": "配置", "enabled": "已启用", "disabled": "已禁用", - "config_directory": "配置目录" + "config_directory": "配置目录", + "neither_cursor_nor_cursor_directory_found": "未找到 Cursor 或 Cursor 目录", + "please_make_sure_cursor_is_installed_and_has_been_run_at_least_once": "请确保 Cursor 已安装并至少运行一次", + "storage_directory_not_found": "未找到存储目录", + "storage_file_found": "找到存储文件", + "file_size": "文件大小", + "file_permissions": "文件权限", + "file_owner": "文件所有者", + "file_group": "文件组", + "error_getting_file_stats": "获取文件统计信息时出错", + "permission_denied": "权限拒绝", + "try_running": "尝试运行 'cursor --help' 检查是否已安装", + "and": "和", + "storage_file_is_empty": "存储文件为空", + "the_file_might_be_corrupted_please_reinstall_cursor": "文件可能已损坏,请重新安装 Cursor", + "storage_file_not_found": "未找到存储文件", + "error_checking_linux_paths": "检查 Linux 路径时出错", + "config_option_added": "添加配置选项", + "config_updated": "配置更新", + "config_created": "配置已创建", + "config_setup_error": "配置设置错误" } + } \ No newline at end of file diff --git a/locales/zh_tw.json b/locales/zh_tw.json index 8cfb910..c88ae6e 100644 --- a/locales/zh_tw.json +++ b/locales/zh_tw.json @@ -467,6 +467,27 @@ "configuration": "配置", "enabled": "已啟用", "disabled": "已禁用", - "config_directory": "配置目錄" + "config_directory": "配置目錄", + "neither_cursor_nor_cursor_directory_found": "未找到 Cursor 或 Cursor 目錄", + "please_make_sure_cursor_is_installed_and_has_been_run_at_least_once": "請確保 Cursor 已安裝並至少運行一次", + "storage_directory_not_found": "未找到儲存目錄", + "storage_file_found": "找到儲存文件", + "file_size": "文件大小", + "file_permissions": "文件權限", + "file_owner": "文件所有者", + "file_group": "文件組", + "error_getting_file_stats": "獲取文件統計信息時出錯", + "permission_denied": "權限拒絕", + "try_running": "嘗試運行 'cursor --help' 檢查是否已安裝", + "and": "和", + "storage_file_is_empty": "儲存文件為空", + "the_file_might_be_corrupted_please_reinstall_cursor": "文件可能已損壞,請重新安裝 Cursor", + "storage_file_not_found": "未找到儲存文件", + "error_checking_linux_paths": "檢查 Linux 路徑時出錯", + "config_option_added": "添加配置選項", + "config_updated": "配置更新", + "config_created": "配置已創建", + "config_setup_error": "配置設置錯誤" + } } \ No newline at end of file