machineconfig 3.7__py3-none-any.whl → 7.69__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of machineconfig might be problematic. Click here for more details.
- machineconfig/__init__.py +0 -28
- machineconfig/cluster/remote/distribute.py +0 -1
- machineconfig/cluster/remote/file_manager.py +0 -2
- machineconfig/cluster/remote/script_execution.py +1 -2
- machineconfig/cluster/sessions_managers/{enhanced_command_runner.py → helpers/enhanced_command_runner.py} +4 -6
- machineconfig/cluster/sessions_managers/helpers/load_balancer_helper.py +145 -0
- machineconfig/cluster/sessions_managers/utils/load_balancer.py +53 -0
- machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
- machineconfig/cluster/sessions_managers/wt_local.py +128 -330
- machineconfig/cluster/sessions_managers/wt_local_manager.py +53 -187
- machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +49 -197
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
- machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
- machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
- machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +4 -2
- machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
- machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
- machineconfig/cluster/sessions_managers/zellij_local.py +81 -375
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +22 -172
- machineconfig/cluster/sessions_managers/zellij_remote.py +40 -41
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +13 -10
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -8
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -9
- machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -1
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper.py +298 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_restart.py +77 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_with_panes.py +228 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_manager_helper.py +165 -0
- machineconfig/jobs/{python → installer}/check_installations.py +7 -21
- machineconfig/jobs/installer/custom/boxes.py +61 -0
- machineconfig/jobs/installer/custom/gh.py +128 -0
- machineconfig/jobs/{python_custom_installers → installer/custom}/hx.py +84 -18
- machineconfig/jobs/installer/custom_dev/alacritty.py +86 -0
- machineconfig/jobs/installer/custom_dev/brave.py +82 -0
- machineconfig/jobs/installer/custom_dev/bypass_paywall.py +59 -0
- machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
- machineconfig/jobs/installer/custom_dev/code.py +63 -0
- machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/cursor.py +7 -7
- machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +30 -0
- machineconfig/jobs/installer/custom_dev/espanso.py +117 -0
- machineconfig/jobs/installer/custom_dev/goes.py +68 -0
- machineconfig/jobs/installer/custom_dev/lvim.py +89 -0
- machineconfig/jobs/installer/custom_dev/nerdfont.py +111 -0
- machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +149 -0
- machineconfig/jobs/installer/custom_dev/redis.py +88 -0
- machineconfig/jobs/installer/custom_dev/sysabc.py +145 -0
- machineconfig/jobs/installer/custom_dev/wezterm.py +92 -0
- machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/winget.py +2 -3
- machineconfig/jobs/installer/installer_data.json +3440 -0
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/brave.sh +4 -14
- machineconfig/jobs/{python_custom_installers/scripts/linux/warp-cli.sh → installer/linux_scripts/cloudflare_warp_cli.sh} +5 -17
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/docker.sh +6 -18
- machineconfig/jobs/installer/linux_scripts/docker_start.sh +37 -0
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/edge.sh +3 -11
- machineconfig/jobs/{linux/msc → installer/linux_scripts}/lid.sh +2 -8
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/nerdfont.sh +5 -17
- machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +2 -8
- machineconfig/jobs/installer/linux_scripts/ngrok.sh +6 -0
- machineconfig/jobs/installer/linux_scripts/q.sh +9 -0
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/redis.sh +6 -17
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/vscode.sh +5 -17
- machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/wezterm.sh +4 -12
- machineconfig/jobs/installer/package_groups.py +255 -0
- machineconfig/logger.py +0 -1
- machineconfig/profile/backup.toml +49 -0
- machineconfig/profile/bash_shell_profiles.md +11 -0
- machineconfig/profile/create_helper.py +74 -0
- machineconfig/profile/create_links.py +288 -0
- machineconfig/profile/create_links_export.py +100 -0
- machineconfig/profile/create_shell_profile.py +136 -0
- machineconfig/profile/mapper.toml +258 -0
- machineconfig/scripts/__init__.py +0 -4
- machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +14 -25
- machineconfig/scripts/linux/wrap_mcfg +47 -0
- machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
- machineconfig/scripts/python/agents.py +198 -0
- machineconfig/scripts/python/ai/command_runner/command_runner.sh +9 -0
- machineconfig/scripts/python/ai/command_runner/prompt.txt +9 -0
- machineconfig/scripts/python/ai/generate_files.py +307 -42
- machineconfig/scripts/python/ai/{mcinit.py → initai.py} +3 -38
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +114 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +88 -22
- machineconfig/scripts/python/ai/solutions/_shared.py +9 -1
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +4 -1
- machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
- machineconfig/scripts/python/ai/solutions/gemini/settings.json +1 -1
- machineconfig/scripts/python/ai/solutions/generic.py +27 -4
- machineconfig/scripts/python/ai/vscode_tasks.py +37 -0
- machineconfig/scripts/python/cloud.py +29 -0
- machineconfig/scripts/python/croshell.py +129 -198
- machineconfig/scripts/python/define.py +31 -0
- machineconfig/scripts/python/devops.py +45 -131
- machineconfig/scripts/python/devops_navigator.py +6 -0
- machineconfig/scripts/python/env_manager/__init__.py +1 -0
- machineconfig/scripts/python/env_manager/path_manager_backend.py +47 -0
- machineconfig/scripts/python/env_manager/path_manager_tui.py +228 -0
- machineconfig/scripts/python/fire_jobs.py +166 -235
- machineconfig/scripts/python/ftpx.py +164 -100
- machineconfig/scripts/python/helpers/ast_search.py +74 -0
- machineconfig/scripts/python/helpers/repo_rag.py +325 -0
- machineconfig/scripts/python/helpers/symantic_search.py +25 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +14 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +37 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_cursor_agents.py +22 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +42 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_help_launch.py +110 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +34 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_load_balancer.py +22 -0
- machineconfig/scripts/python/helpers_agents/templates/prompt.txt +6 -0
- machineconfig/scripts/python/helpers_agents/templates/template.ps1 +14 -0
- machineconfig/scripts/python/helpers_agents/templates/template.sh +24 -0
- machineconfig/scripts/python/{cloud_copy.py → helpers_cloud/cloud_copy.py} +52 -39
- machineconfig/scripts/python/{cloud_mount.py → helpers_cloud/cloud_mount.py} +13 -18
- machineconfig/scripts/python/helpers_cloud/cloud_sync.py +81 -0
- machineconfig/scripts/python/{helpers → helpers_cloud}/helpers2.py +3 -3
- machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
- machineconfig/scripts/python/{scheduler.py → helpers_croshell/scheduler.py} +0 -1
- machineconfig/scripts/python/{start_slidev.py → helpers_croshell/start_slidev.py} +32 -20
- machineconfig/scripts/python/helpers_devops/cli_config.py +95 -0
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
- machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
- machineconfig/scripts/python/helpers_devops/cli_nw.py +134 -0
- machineconfig/scripts/python/helpers_devops/cli_repos.py +182 -0
- machineconfig/scripts/python/helpers_devops/cli_self.py +134 -0
- machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +141 -0
- machineconfig/scripts/python/helpers_devops/cli_terminal.py +156 -0
- machineconfig/scripts/python/helpers_devops/cli_utils.py +96 -0
- machineconfig/scripts/python/{devops_backup_retrieve.py → helpers_devops/devops_backup_retrieve.py} +7 -10
- machineconfig/scripts/python/helpers_devops/devops_status.py +511 -0
- machineconfig/scripts/python/helpers_devops/devops_update_repos.py +269 -0
- machineconfig/scripts/python/helpers_devops/themes/choose_pwsh_theme.ps1 +81 -0
- machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
- machineconfig/scripts/python/{choose_wezterm_theme.py → helpers_devops/themes/choose_wezterm_theme.py} +2 -2
- machineconfig/scripts/python/{cloud_manager.py → helpers_fire_command/cloud_manager.py} +0 -2
- machineconfig/scripts/python/{helpers/helpers4.py → helpers_fire_command/file_wrangler.py} +57 -89
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_args_helper.py +145 -0
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +110 -0
- machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
- machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfag +1 -1
- machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +1 -1
- machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfrga +1 -1
- machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
- machineconfig/scripts/python/helpers_navigator/command_builder.py +111 -0
- machineconfig/scripts/python/helpers_navigator/command_detail.py +44 -0
- machineconfig/scripts/python/helpers_navigator/command_tree.py +620 -0
- machineconfig/scripts/python/helpers_navigator/data_models.py +28 -0
- machineconfig/scripts/python/helpers_navigator/main_app.py +272 -0
- machineconfig/scripts/python/helpers_navigator/search_bar.py +15 -0
- machineconfig/scripts/python/helpers_repos/action.py +209 -0
- machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
- machineconfig/scripts/python/{repos_helper_clone.py → helpers_repos/clone.py} +6 -7
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +218 -0
- machineconfig/scripts/python/helpers_repos/count_lines.py +348 -0
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +17 -0
- machineconfig/scripts/python/helpers_repos/entrypoint.py +77 -0
- machineconfig/scripts/python/helpers_repos/grource.py +340 -0
- machineconfig/scripts/python/{repos_helper_record.py → helpers_repos/record.py} +7 -4
- machineconfig/scripts/python/helpers_repos/sync.py +66 -0
- machineconfig/scripts/python/{repos_helper_update.py → helpers_repos/update.py} +3 -3
- machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +58 -0
- machineconfig/scripts/python/helpers_utils/download.py +152 -0
- machineconfig/scripts/python/helpers_utils/path.py +108 -0
- machineconfig/scripts/python/interactive.py +187 -0
- machineconfig/scripts/python/mcfg_entry.py +63 -0
- machineconfig/scripts/python/msearch.py +40 -0
- machineconfig/scripts/python/{devops_add_identity.py → nw/devops_add_identity.py} +1 -3
- machineconfig/scripts/python/{devops_add_ssh_key.py → nw/devops_add_ssh_key.py} +74 -44
- machineconfig/scripts/{linux → python/nw}/mount_nfs +1 -1
- machineconfig/scripts/python/{mount_nfs.py → nw/mount_nfs.py} +19 -16
- machineconfig/scripts/{linux → python/nw}/mount_nw_drive +1 -2
- machineconfig/scripts/python/{mount_ssh.py → nw/mount_ssh.py} +7 -8
- machineconfig/scripts/python/{onetimeshare.py → nw/onetimeshare.py} +0 -1
- machineconfig/scripts/python/nw/ssh_debug_linux.py +391 -0
- machineconfig/scripts/python/nw/ssh_debug_windows.py +338 -0
- machineconfig/scripts/python/{wifi_conn.py → nw/wifi_conn.py} +1 -51
- machineconfig/scripts/python/nw/wsl_windows_transfer.py +67 -0
- machineconfig/scripts/python/sessions.py +167 -0
- machineconfig/scripts/python/terminal.py +127 -0
- machineconfig/scripts/python/utils.py +66 -0
- machineconfig/scripts/windows/mounts/Restore-ThunderbirdProfile.ps1 +92 -0
- machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +1 -3
- machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +1 -1
- machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -6
- machineconfig/scripts/windows/wrap_mcfg.ps1 +60 -0
- machineconfig/settings/broot/br.sh +0 -4
- machineconfig/settings/broot/conf.toml +1 -1
- machineconfig/settings/helix/config.toml +16 -0
- machineconfig/settings/helix/languages.toml +13 -4
- machineconfig/settings/helix/yazi-picker.sh +12 -0
- machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
- machineconfig/settings/lf/linux/exe/previewer.sh +9 -3
- machineconfig/settings/lf/linux/lfrc +10 -12
- machineconfig/settings/lf/windows/fzf_edit.ps1 +2 -2
- machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
- machineconfig/settings/lf/windows/lfrc +18 -38
- machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
- machineconfig/settings/linters/.ruff.toml +1 -1
- machineconfig/settings/lvim/windows/archive/config_additional.lua +0 -6
- machineconfig/settings/marimo/marimo.toml +80 -0
- machineconfig/settings/marimo/snippets/globalize.py +34 -0
- machineconfig/settings/pistol/pistol.conf +1 -1
- machineconfig/settings/shells/bash/init.sh +55 -31
- machineconfig/settings/shells/nushell/config.nu +1 -34
- machineconfig/settings/shells/nushell/init.nu +127 -0
- machineconfig/settings/shells/pwsh/init.ps1 +61 -43
- machineconfig/settings/shells/starship/starship.toml +16 -0
- machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
- machineconfig/settings/shells/wt/settings.json +32 -17
- machineconfig/settings/shells/zsh/init.sh +89 -0
- machineconfig/settings/svim/linux/init.toml +0 -4
- machineconfig/settings/svim/windows/init.toml +0 -3
- machineconfig/settings/yazi/init.lua +57 -0
- machineconfig/settings/yazi/keymap_linux.toml +79 -0
- machineconfig/settings/yazi/keymap_windows.toml +78 -0
- machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
- machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
- machineconfig/settings/yazi/yazi.toml +14 -1
- machineconfig/setup_linux/__init__.py +10 -0
- machineconfig/setup_linux/apps_desktop.sh +89 -0
- machineconfig/setup_linux/apps_gui.sh +64 -0
- machineconfig/setup_linux/{nix → others}/cli_installation.sh +9 -29
- machineconfig/setup_linux/ssh/openssh_all.sh +25 -0
- machineconfig/setup_linux/ssh/openssh_wsl.sh +38 -0
- machineconfig/setup_linux/uv.sh +15 -0
- machineconfig/setup_linux/web_shortcuts/interactive.sh +28 -203
- machineconfig/setup_mac/__init__.py +16 -0
- machineconfig/setup_mac/apps_gui.sh +248 -0
- machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
- machineconfig/setup_mac/uv.sh +36 -0
- machineconfig/setup_windows/__init__.py +8 -0
- machineconfig/setup_windows/others/power_options.ps1 +7 -0
- machineconfig/setup_windows/ssh/add-sshkey.ps1 +29 -0
- machineconfig/setup_windows/ssh/add_identity.ps1 +11 -0
- machineconfig/setup_windows/ssh/openssh-server.ps1 +37 -0
- machineconfig/setup_windows/uv.ps1 +17 -0
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +28 -189
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +37 -23
- machineconfig/utils/accessories.py +52 -12
- machineconfig/utils/cloud/onedrive/README.md +139 -0
- machineconfig/utils/code.py +140 -93
- machineconfig/utils/files/art/fat_croco.txt +10 -0
- machineconfig/utils/files/art/halfwit_croco.txt +9 -0
- machineconfig/utils/files/art/happy_croco.txt +22 -0
- machineconfig/utils/files/art/water_croco.txt +11 -0
- machineconfig/utils/files/ascii_art.py +118 -0
- machineconfig/utils/files/dbms.py +257 -0
- machineconfig/utils/files/headers.py +68 -0
- machineconfig/utils/files/ouch/decompress.py +45 -0
- machineconfig/utils/files/read.py +95 -0
- machineconfig/utils/installer_utils/github_release_bulk.py +188 -0
- machineconfig/utils/installer_utils/install_from_url.py +180 -0
- machineconfig/utils/installer_utils/installer_class.py +239 -316
- machineconfig/utils/installer_utils/installer_cli.py +186 -0
- machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +90 -5
- machineconfig/utils/installer_utils/installer_runner.py +191 -0
- machineconfig/utils/io.py +77 -24
- machineconfig/utils/links.py +309 -100
- machineconfig/utils/meta.py +255 -0
- machineconfig/utils/notifications.py +1 -1
- machineconfig/utils/options.py +19 -47
- machineconfig/utils/path_extended.py +111 -121
- machineconfig/utils/path_helper.py +75 -22
- machineconfig/utils/procs.py +50 -74
- machineconfig/utils/scheduler.py +94 -97
- machineconfig/utils/scheduling.py +0 -3
- machineconfig/utils/schemas/fire_agents/fire_agents_input.py +5 -17
- machineconfig/utils/schemas/installer/installer_types.py +28 -6
- machineconfig/utils/schemas/layouts/layout_types.py +34 -1
- machineconfig/utils/source_of_truth.py +3 -6
- machineconfig/utils/ssh.py +742 -254
- machineconfig/utils/ssh_utils/utils.py +0 -0
- machineconfig/utils/terminal.py +3 -140
- machineconfig/utils/tst.py +20 -0
- machineconfig/utils/upgrade_packages.py +109 -28
- machineconfig/utils/ve.py +13 -5
- machineconfig-7.69.dist-info/METADATA +124 -0
- machineconfig-7.69.dist-info/RECORD +454 -0
- machineconfig-7.69.dist-info/entry_points.txt +15 -0
- machineconfig/cluster/templates/cli_click.py +0 -102
- machineconfig/cluster/templates/cli_gooey.py +0 -115
- machineconfig/cluster/templates/utils.py +0 -51
- machineconfig/jobs/linux/msc/cli_agents.sh +0 -32
- machineconfig/jobs/python/create_bootable_media.py +0 -16
- machineconfig/jobs/python/python_cargo_build_share.py +0 -59
- machineconfig/jobs/python/python_ve_symlink.py +0 -29
- machineconfig/jobs/python/tasks.py +0 -3
- machineconfig/jobs/python/vscode/api.py +0 -48
- machineconfig/jobs/python/vscode/link_ve.py +0 -63
- machineconfig/jobs/python/vscode/select_interpreter.py +0 -87
- machineconfig/jobs/python/vscode/sync_code.py +0 -58
- machineconfig/jobs/python_custom_installers/archive/ngrok.py +0 -63
- machineconfig/jobs/python_custom_installers/dev/aider.py +0 -37
- machineconfig/jobs/python_custom_installers/dev/alacritty.py +0 -65
- machineconfig/jobs/python_custom_installers/dev/brave.py +0 -71
- machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +0 -50
- machineconfig/jobs/python_custom_installers/dev/code.py +0 -51
- machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +0 -78
- machineconfig/jobs/python_custom_installers/dev/espanso.py +0 -90
- machineconfig/jobs/python_custom_installers/dev/goes.py +0 -55
- machineconfig/jobs/python_custom_installers/dev/lvim.py +0 -77
- machineconfig/jobs/python_custom_installers/dev/nerdfont.py +0 -68
- machineconfig/jobs/python_custom_installers/dev/redis.py +0 -65
- machineconfig/jobs/python_custom_installers/dev/reverse_proxy.md +0 -31
- machineconfig/jobs/python_custom_installers/dev/wezterm.py +0 -70
- machineconfig/jobs/python_custom_installers/docker.py +0 -74
- machineconfig/jobs/python_custom_installers/gh.py +0 -97
- machineconfig/jobs/python_custom_installers/scripts/linux/docker_start.sh +0 -45
- machineconfig/jobs/python_custom_installers/scripts/linux/pgsql.sh +0 -49
- machineconfig/jobs/python_custom_installers/scripts/linux/timescaledb.sh +0 -85
- machineconfig/jobs/python_custom_installers/warp-cli.py +0 -71
- machineconfig/jobs/python_generic_installers/config.json +0 -603
- machineconfig/jobs/python_generic_installers/config.json.bak +0 -414
- machineconfig/jobs/python_generic_installers/dev/config.archive.json +0 -18
- machineconfig/jobs/python_generic_installers/dev/config.json +0 -825
- machineconfig/jobs/python_generic_installers/dev/config.json.bak +0 -565
- machineconfig/jobs/python_linux_installers/archive/config.json +0 -18
- machineconfig/jobs/python_linux_installers/archive/config.json.bak +0 -10
- machineconfig/jobs/python_linux_installers/config.json +0 -145
- machineconfig/jobs/python_linux_installers/config.json.bak +0 -110
- machineconfig/jobs/python_linux_installers/dev/config.json +0 -276
- machineconfig/jobs/python_linux_installers/dev/config.json.bak +0 -206
- machineconfig/jobs/python_windows_installers/archive/file.json +0 -11
- machineconfig/jobs/python_windows_installers/config.json +0 -82
- machineconfig/jobs/python_windows_installers/config.json.bak +0 -56
- machineconfig/jobs/python_windows_installers/dev/config.json +0 -4
- machineconfig/jobs/python_windows_installers/dev/config.json.bak +0 -3
- machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -14
- machineconfig/jobs/windows/start_terminal.ps1 +0 -6
- machineconfig/jobs/windows/startup_file.cmd +0 -2
- machineconfig/profile/create.py +0 -169
- machineconfig/profile/shell.py +0 -176
- machineconfig/scripts/cloud/init.sh +0 -119
- machineconfig/scripts/linux/choose_wezterm_theme +0 -3
- machineconfig/scripts/linux/cloud_copy +0 -2
- machineconfig/scripts/linux/cloud_mount +0 -2
- machineconfig/scripts/linux/cloud_repo_sync +0 -2
- machineconfig/scripts/linux/cloud_sync +0 -2
- machineconfig/scripts/linux/croshell +0 -3
- machineconfig/scripts/linux/devops +0 -2
- machineconfig/scripts/linux/fire +0 -2
- machineconfig/scripts/linux/fire_agents +0 -2
- machineconfig/scripts/linux/ftpx +0 -2
- machineconfig/scripts/linux/fzf2g +0 -21
- machineconfig/scripts/linux/fzffg +0 -25
- machineconfig/scripts/linux/gh_models +0 -2
- machineconfig/scripts/linux/kill_process +0 -2
- machineconfig/scripts/linux/mcinit +0 -2
- machineconfig/scripts/linux/programs +0 -21
- machineconfig/scripts/linux/repos +0 -2
- machineconfig/scripts/linux/scheduler +0 -2
- machineconfig/scripts/linux/share_smb +0 -1
- machineconfig/scripts/linux/start_slidev +0 -2
- machineconfig/scripts/linux/start_terminals +0 -3
- machineconfig/scripts/linux/warp-cli.sh +0 -122
- machineconfig/scripts/linux/wifi_conn +0 -2
- machineconfig/scripts/linux/z_ls +0 -104
- machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
- machineconfig/scripts/python/archive/im2text.py +0 -34
- machineconfig/scripts/python/archive/tmate_conn.py +0 -41
- machineconfig/scripts/python/archive/tmate_start.py +0 -44
- machineconfig/scripts/python/cloud_repo_sync.py +0 -192
- machineconfig/scripts/python/cloud_sync.py +0 -85
- machineconfig/scripts/python/devops_devapps_install.py +0 -202
- machineconfig/scripts/python/devops_update_repos.py +0 -180
- machineconfig/scripts/python/dotfile.py +0 -52
- machineconfig/scripts/python/fire_agents.py +0 -176
- machineconfig/scripts/python/fire_agents_help_launch.py +0 -143
- machineconfig/scripts/python/fire_agents_load_balancer.py +0 -50
- machineconfig/scripts/python/fire_jobs_args_helper.py +0 -84
- machineconfig/scripts/python/fire_jobs_layout_helper.py +0 -66
- machineconfig/scripts/python/get_zellij_cmd.py +0 -15
- machineconfig/scripts/python/gh_models.py +0 -104
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -114
- machineconfig/scripts/python/repos.py +0 -160
- machineconfig/scripts/python/snapshot.py +0 -25
- machineconfig/scripts/python/start_terminals.py +0 -121
- machineconfig/scripts/python/wsl_windows_transfer.py +0 -72
- machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
- machineconfig/scripts/windows/cloud_copy.ps1 +0 -1
- machineconfig/scripts/windows/cloud_mount.ps1 +0 -1
- machineconfig/scripts/windows/cloud_repo_sync.ps1 +0 -1
- machineconfig/scripts/windows/cloud_sync.ps1 +0 -1
- machineconfig/scripts/windows/croshell.ps1 +0 -1
- machineconfig/scripts/windows/devops.ps1 +0 -1
- machineconfig/scripts/windows/dotfile.ps1 +0 -1
- machineconfig/scripts/windows/fire.ps1 +0 -1
- machineconfig/scripts/windows/ftpx.ps1 +0 -1
- machineconfig/scripts/windows/gpt.ps1 +0 -1
- machineconfig/scripts/windows/grep.ps1 +0 -2
- machineconfig/scripts/windows/kill_process.ps1 +0 -1
- machineconfig/scripts/windows/mcinit.ps1 +0 -1
- machineconfig/scripts/windows/nano.ps1 +0 -3
- machineconfig/scripts/windows/pomodoro.ps1 +0 -1
- machineconfig/scripts/windows/reload_path.ps1 +0 -3
- machineconfig/scripts/windows/repos.ps1 +0 -1
- machineconfig/scripts/windows/scheduler.ps1 +0 -1
- machineconfig/scripts/windows/snapshot.ps1 +0 -1
- machineconfig/scripts/windows/start_slidev.ps1 +0 -1
- machineconfig/scripts/windows/start_terminals.ps1 +0 -1
- machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
- machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
- machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
- machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
- machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +0 -57
- machineconfig/setup_linux/web_shortcuts/ascii_art.sh +0 -93
- machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -11
- machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -52
- machineconfig/setup_windows/web_shortcuts/all.ps1 +0 -18
- machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +0 -36
- machineconfig/setup_windows/web_shortcuts/croshell.ps1 +0 -16
- machineconfig/setup_windows/web_shortcuts/ssh.ps1 +0 -11
- machineconfig/setup_windows/wt_and_pwsh/install_nerd_fonts.py +0 -100
- machineconfig/utils/ai/generate_file_checklist.py +0 -68
- machineconfig/utils/installer.py +0 -255
- machineconfig-3.7.dist-info/METADATA +0 -165
- machineconfig-3.7.dist-info/RECORD +0 -432
- machineconfig-3.7.dist-info/entry_points.txt +0 -18
- machineconfig/cluster/{templates → remote}/run_cloud.py +0 -0
- machineconfig/cluster/{templates → remote}/run_cluster.py +0 -0
- machineconfig/cluster/{templates → remote}/run_remote.py +0 -0
- machineconfig/jobs/{python → installer}/__init__.py +0 -0
- machineconfig/jobs/{python_custom_installers → installer/custom_dev}/__init__.py +0 -0
- machineconfig/{setup_windows/wt_and_pwsh → jobs/installer/powershell_scripts}/install_fonts.ps1 +0 -0
- machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
- machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
- machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
- machineconfig/{jobs/python_generic_installers → scripts/python/helpers_agents}/__init__.py +0 -0
- machineconfig/{jobs/python_linux_installers → scripts/python/helpers_agents/agentic_frameworks}/__init__.py +0 -0
- machineconfig/scripts/python/{fire_agents_help_search.py → helpers_agents/fire_agents_help_search.py} +0 -0
- machineconfig/{jobs/python_linux_installers/dev → scripts/python/helpers_cloud}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers → helpers_cloud}/cloud_helpers.py +1 -1
- /machineconfig/scripts/python/{helpers → helpers_cloud}/helpers5.py +0 -0
- /machineconfig/{jobs/python_windows_installers → scripts/python/helpers_croshell}/__init__.py +0 -0
- /machineconfig/scripts/python/{pomodoro.py → helpers_croshell/pomodoro.py} +0 -0
- /machineconfig/scripts/python/{viewer.py → helpers_croshell/viewer.py} +0 -0
- /machineconfig/scripts/python/{viewer_template.py → helpers_croshell/viewer_template.py} +0 -0
- /machineconfig/{jobs/python_windows_installers/archive → scripts/python/helpers_devops}/__init__.py +0 -0
- /machineconfig/{jobs/python_windows_installers/dev → scripts/python/helpers_devops/themes}/__init__.py +0 -0
- /machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
- /machineconfig/scripts/python/{helpers → helpers_fire_command}/__init__.py +0 -0
- /machineconfig/scripts/python/{fire_jobs_streamlit_helper.py → helpers_fire_command/fire_jobs_streamlit_helper.py} +0 -0
- /machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/skrg +0 -0
- /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfb.ps1 +0 -0
- /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfg.ps1 +0 -0
- /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfrga.bat +0 -0
- /machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_sessions/__init__.py} +0 -0
- /machineconfig/scripts/{windows/share_nfs.ps1 → python/nw/__init__.py} +0 -0
- /machineconfig/scripts/{linux → python/nw}/mount_drive +0 -0
- /machineconfig/scripts/python/{mount_nw_drive.py → nw/mount_nw_drive.py} +0 -0
- /machineconfig/scripts/{linux → python/nw}/mount_smb +0 -0
- /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
- /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
- /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
- /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
- /machineconfig/setup_linux/{web_shortcuts → others}/android.sh +0 -0
- /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
- /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
- /machineconfig/{settings/yazi/keymap.toml → utils/files/ouch/__init__.py} +0 -0
- {machineconfig-3.7.dist-info → machineconfig-7.69.dist-info}/WHEEL +0 -0
- {machineconfig-3.7.dist-info → machineconfig-7.69.dist-info}/top_level.txt +0 -0
|
@@ -1,14 +1,35 @@
|
|
|
1
|
-
from machineconfig.utils.path_extended import PathExtended
|
|
2
|
-
from machineconfig.utils.
|
|
3
|
-
from machineconfig.utils.
|
|
4
|
-
from machineconfig.utils.
|
|
5
|
-
from machineconfig.utils.io import read_json
|
|
6
|
-
from machineconfig.utils.schemas.installer.installer_types import InstallerData, InstallerDataFiles
|
|
1
|
+
from machineconfig.utils.path_extended import PathExtended, DECOMPRESS_SUPPORTED_FORMATS
|
|
2
|
+
from machineconfig.utils.source_of_truth import INSTALL_TMP_DIR, INSTALL_VERSION_ROOT
|
|
3
|
+
from machineconfig.utils.installer_utils.installer_locator_utils import find_move_delete_linux, find_move_delete_windows, check_tool_exists
|
|
4
|
+
from machineconfig.utils.schemas.installer.installer_types import InstallerData, get_os_name, get_normalized_arch
|
|
7
5
|
|
|
8
6
|
import platform
|
|
9
7
|
import subprocess
|
|
10
|
-
|
|
11
|
-
from
|
|
8
|
+
import json
|
|
9
|
+
from typing import Optional, Any
|
|
10
|
+
from urllib.parse import urlparse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def install_deb_package(downloaded: PathExtended) -> None:
|
|
15
|
+
from rich import print as rprint
|
|
16
|
+
from rich.panel import Panel
|
|
17
|
+
print(f"📦 Installing .deb package: {downloaded}")
|
|
18
|
+
assert platform.system() == "Linux"
|
|
19
|
+
result = subprocess.run(f"sudo nala install -y {downloaded}", shell=True, capture_output=True, text=True)
|
|
20
|
+
success = result.returncode == 0 and result.stderr == ""
|
|
21
|
+
if not success:
|
|
22
|
+
from rich.console import Group
|
|
23
|
+
desc = "Installing .deb"
|
|
24
|
+
sub_panels = []
|
|
25
|
+
if result.stdout:
|
|
26
|
+
sub_panels.append(Panel(result.stdout, title="STDOUT", style="blue"))
|
|
27
|
+
if result.stderr:
|
|
28
|
+
sub_panels.append(Panel(result.stderr, title="STDERR", style="red"))
|
|
29
|
+
group_content = Group(f"❌ {desc} failed\nReturn code: {result.returncode}", *sub_panels)
|
|
30
|
+
rprint(Panel(group_content, title=desc, style="red"))
|
|
31
|
+
print("🗑️ Cleaning up .deb package...")
|
|
32
|
+
downloaded.delete(sure=True)
|
|
12
33
|
|
|
13
34
|
|
|
14
35
|
class Installer:
|
|
@@ -16,162 +37,138 @@ class Installer:
|
|
|
16
37
|
self.installer_data: InstallerData = installer_data
|
|
17
38
|
|
|
18
39
|
def __repr__(self) -> str:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return f"Installer of {exe_name} {app_name} @ {repo_url}"
|
|
23
|
-
|
|
24
|
-
def get_description(self):
|
|
25
|
-
# old_version_cli = Terminal().run(f"{self.exe_name} --version").op.replace("\n", "")
|
|
26
|
-
# old_version_cli = os.system(f"{self.exe_name} --version").replace("\n", "")
|
|
27
|
-
exe_name = self.installer_data.get("exeName", "")
|
|
28
|
-
if not exe_name:
|
|
29
|
-
return "Invalid installer: missing exeName"
|
|
40
|
+
app_name = self.installer_data["appName"]
|
|
41
|
+
repo_url = self.installer_data["repoURL"]
|
|
42
|
+
return f"Installer of {app_name} @ {repo_url}"
|
|
30
43
|
|
|
44
|
+
def get_description(self) -> str:
|
|
45
|
+
exe_name = self._get_exe_name()
|
|
46
|
+
|
|
31
47
|
old_version_cli: bool = check_tool_exists(tool_name=exe_name)
|
|
32
48
|
old_version_cli_str = "✅" if old_version_cli else "❌"
|
|
33
|
-
|
|
34
|
-
doc = self.installer_data.get("doc", "No description")
|
|
49
|
+
doc = self.installer_data["doc"]
|
|
35
50
|
return f"{exe_name:<12} {old_version_cli_str} {doc}"
|
|
51
|
+
|
|
52
|
+
def _get_exe_name(self) -> str:
|
|
53
|
+
"""Derive executable name from app name by converting to lowercase and removing spaces."""
|
|
54
|
+
return self.installer_data["appName"].lower().replace(" ", "") # .replace("-", "")
|
|
36
55
|
|
|
37
|
-
|
|
38
|
-
def choose_app_and_install():
|
|
39
|
-
print(f"\n{'=' * 80}\n🔍 SELECT APPLICATION TO INSTALL 🔍\n{'=' * 80}")
|
|
40
|
-
from machineconfig.utils.options import choose_from_options
|
|
41
|
-
|
|
42
|
-
print("📂 Searching for configuration files...")
|
|
43
|
-
jobs_dir = Path(LIBRARY_ROOT.joinpath("jobs"))
|
|
44
|
-
config_paths = [Path(p) for p in jobs_dir.rglob("config.json")]
|
|
45
|
-
path = choose_from_options(multi=False, options=config_paths, msg="Choose one option")
|
|
46
|
-
print(f"📄 Loading configuration from: {path}")
|
|
47
|
-
config_data = read_json(path)
|
|
48
|
-
installer_data_files = InstallerDataFiles(config_data)
|
|
49
|
-
|
|
50
|
-
# Extract app names from the installers
|
|
51
|
-
app_names = [installer["appName"] for installer in installer_data_files["installers"]]
|
|
52
|
-
print("🔍 Select an application to install:")
|
|
53
|
-
app_name = choose_from_options(multi=False, options=app_names, fzf=True, msg="Choose one option")
|
|
54
|
-
|
|
55
|
-
# Find the selected installer data
|
|
56
|
-
selected_installer_data = None
|
|
57
|
-
for installer_data in installer_data_files["installers"]:
|
|
58
|
-
if installer_data["appName"] == app_name:
|
|
59
|
-
selected_installer_data = installer_data
|
|
60
|
-
break
|
|
61
|
-
|
|
62
|
-
if selected_installer_data is None:
|
|
63
|
-
raise ValueError(f"Could not find installer data for {app_name}")
|
|
64
|
-
|
|
65
|
-
installer = Installer(installer_data=selected_installer_data)
|
|
66
|
-
print(f"📦 Selected application: {selected_installer_data.get('exeName', 'unknown')}")
|
|
67
|
-
version = input(f"📝 Enter version to install for {selected_installer_data.get('exeName', 'unknown')} [latest]: ") or None
|
|
68
|
-
print(f"\n{'=' * 80}\n🚀 INSTALLING {selected_installer_data.get('exeName', 'UNKNOWN').upper()} 🚀\n{'=' * 80}")
|
|
69
|
-
installer.install(version=version)
|
|
70
|
-
|
|
71
|
-
def install_robust(self, version: Optional[str]):
|
|
56
|
+
def install_robust(self, version: Optional[str]) -> str:
|
|
72
57
|
try:
|
|
73
|
-
exe_name = self.
|
|
74
|
-
print(f"\n{'=' * 80}\n🚀 INSTALLING {exe_name.upper()} 🚀\n{'=' * 80}")
|
|
58
|
+
exe_name = self._get_exe_name()
|
|
75
59
|
result_old = subprocess.run(f"{exe_name} --version", shell=True, capture_output=True, text=True)
|
|
76
60
|
old_version_cli = result_old.stdout.strip()
|
|
77
|
-
print(f"📊 Current version: {old_version_cli or 'Not installed'}")
|
|
78
|
-
|
|
61
|
+
print(f"🚀 INSTALLING {exe_name.upper()} 🚀. 📊 Current version: {old_version_cli or 'Not installed'}")
|
|
79
62
|
self.install(version=version)
|
|
80
|
-
|
|
81
63
|
result_new = subprocess.run(f"{exe_name} --version", shell=True, capture_output=True, text=True)
|
|
82
64
|
new_version_cli = result_new.stdout.strip()
|
|
83
|
-
print(f"📊 New version: {new_version_cli}")
|
|
84
|
-
|
|
85
65
|
if old_version_cli == new_version_cli:
|
|
86
|
-
print(f"ℹ️ Same version detected: {old_version_cli}")
|
|
87
66
|
return f"""📦️ 😑 {exe_name}, same version: {old_version_cli}"""
|
|
88
67
|
else:
|
|
89
|
-
print(f"🚀 Update successful: {old_version_cli} ➡️ {new_version_cli}")
|
|
90
68
|
return f"""📦️ 🤩 {exe_name} updated from {old_version_cli} ➡️ TO ➡️ {new_version_cli}"""
|
|
91
|
-
|
|
92
69
|
except Exception as ex:
|
|
93
|
-
exe_name = self.
|
|
94
|
-
app_name = self.installer_data
|
|
70
|
+
exe_name = self._get_exe_name()
|
|
71
|
+
app_name = self.installer_data["appName"]
|
|
95
72
|
print(f"❌ ERROR: Installation failed for {exe_name}: {ex}")
|
|
96
73
|
return f"""📦️ ❌ Failed to install `{app_name}` with error: {ex}"""
|
|
97
74
|
|
|
98
|
-
def install(self, version: Optional[str]):
|
|
99
|
-
exe_name = self.
|
|
100
|
-
repo_url = self.installer_data
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
program: str = runpy.run_path(str(installer_path), run_name=None)["main"](version=version)
|
|
118
|
-
# print(program)
|
|
119
|
-
print("🚀 Running installation script...")
|
|
120
|
-
if platform.system() == "Linux":
|
|
121
|
-
script = "#!/bin/bash" + "\n" + program
|
|
122
|
-
else:
|
|
123
|
-
script = program
|
|
124
|
-
script_file = PathExtended.tmpfile(name="tmp_shell_script", suffix=".ps1" if platform.system() == "Windows" else ".sh", folder="tmp_scripts")
|
|
125
|
-
script_file.write_text(script, newline=None if platform.system() == "Windows" else "\n")
|
|
126
|
-
if platform.system() == "Windows":
|
|
127
|
-
start_cmd = "powershell"
|
|
128
|
-
full_command = f"{start_cmd} {script_file}"
|
|
129
|
-
else:
|
|
130
|
-
start_cmd = "bash"
|
|
131
|
-
full_command = f"{start_cmd} {script_file}"
|
|
132
|
-
subprocess.run(full_command, stdin=None, stdout=None, stderr=None, shell=True, text=True)
|
|
133
|
-
version_to_be_installed = str(version)
|
|
134
|
-
print(f"✅ Custom installation completed\n{'=' * 80}")
|
|
135
|
-
|
|
136
|
-
elif "npm " in repo_url or "pip " in repo_url or "winget " in repo_url:
|
|
137
|
-
package_manager = repo_url.split(" ", maxsplit=1)[0]
|
|
138
|
-
print(f"📦 Using package manager: {package_manager}")
|
|
139
|
-
desc = package_manager + " installation"
|
|
140
|
-
version_to_be_installed = package_manager + "Latest"
|
|
141
|
-
print(f"🚀 Running: {repo_url}")
|
|
142
|
-
result = subprocess.run(repo_url, shell=True, capture_output=True, text=True)
|
|
143
|
-
success = result.returncode == 0 and result.stderr == ""
|
|
144
|
-
if not success:
|
|
145
|
-
print(f"❌ {desc} failed")
|
|
146
|
-
if result.stdout:
|
|
147
|
-
print(f"STDOUT: {result.stdout}")
|
|
148
|
-
if result.stderr:
|
|
149
|
-
print(f"STDERR: {result.stderr}")
|
|
150
|
-
print(f"Return code: {result.returncode}")
|
|
151
|
-
print(f"✅ Package manager installation completed\n{'=' * 80}")
|
|
152
|
-
|
|
153
|
-
else:
|
|
154
|
-
print("📥 Downloading from repository...")
|
|
155
|
-
downloaded, version_to_be_installed = self.download(version=version)
|
|
156
|
-
if str(downloaded).endswith(".deb"):
|
|
157
|
-
print(f"📦 Installing .deb package: {downloaded}")
|
|
158
|
-
assert platform.system() == "Linux"
|
|
159
|
-
result = subprocess.run(f"sudo nala install -y {downloaded}", shell=True, capture_output=True, text=True)
|
|
75
|
+
def install(self, version: Optional[str]) -> None:
|
|
76
|
+
exe_name = self._get_exe_name()
|
|
77
|
+
repo_url = self.installer_data["repoURL"]
|
|
78
|
+
os_name = get_os_name()
|
|
79
|
+
arch = get_normalized_arch()
|
|
80
|
+
installer_arch_os = self.installer_data["fileNamePattern"][arch][os_name]
|
|
81
|
+
if installer_arch_os is None:
|
|
82
|
+
raise ValueError(f"No installation pattern for {exe_name} on {os_name} {arch}")
|
|
83
|
+
version_to_be_installed: str = "unknown" # Initialize to ensure it's always bound
|
|
84
|
+
if repo_url == "CMD":
|
|
85
|
+
if any(pm in installer_arch_os for pm in ["npm ", "pip ", "winget ", "brew ", "curl "]):
|
|
86
|
+
from rich import print as rprint
|
|
87
|
+
from rich.panel import Panel
|
|
88
|
+
from rich.console import Group
|
|
89
|
+
package_manager = installer_arch_os.split(" ", maxsplit=1)[0]
|
|
90
|
+
print(f"📦 Using package manager: {installer_arch_os}")
|
|
91
|
+
desc = package_manager + " installation"
|
|
92
|
+
version_to_be_installed = package_manager + "Latest"
|
|
93
|
+
result = subprocess.run(installer_arch_os, shell=True, capture_output=False, text=True)
|
|
160
94
|
success = result.returncode == 0 and result.stderr == ""
|
|
161
95
|
if not success:
|
|
162
|
-
|
|
163
|
-
print(f"❌ {desc} failed")
|
|
96
|
+
sub_panels = []
|
|
164
97
|
if result.stdout:
|
|
165
|
-
|
|
98
|
+
sub_panels.append(Panel(result.stdout, title="STDOUT", style="blue"))
|
|
166
99
|
if result.stderr:
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
100
|
+
sub_panels.append(Panel(result.stderr, title="STDERR", style="red"))
|
|
101
|
+
group_content = Group(f"❌ {desc} failed\nReturn code: {result.returncode}", *sub_panels)
|
|
102
|
+
rprint(Panel(group_content, title=desc, style="red"))
|
|
103
|
+
elif installer_arch_os.endswith((".sh", ".py", ".ps1")):
|
|
104
|
+
import machineconfig.jobs.installer as module
|
|
105
|
+
from pathlib import Path
|
|
106
|
+
search_root = Path(module.__file__).parent
|
|
107
|
+
search_results = list(search_root.rglob(installer_arch_os))
|
|
108
|
+
if len(search_results) == 0:
|
|
109
|
+
raise FileNotFoundError(f"Could not find installation script: {installer_arch_os}")
|
|
110
|
+
elif len(search_results) > 1:
|
|
111
|
+
raise ValueError(f"Multiple installation scripts found for {installer_arch_os}: {search_results}")
|
|
112
|
+
installer_path = search_results[0]
|
|
113
|
+
print(f"📄 Found installation script: {installer_path}")
|
|
114
|
+
if installer_arch_os.endswith(".sh"):
|
|
115
|
+
if platform.system() not in ["Linux", "Darwin"]:
|
|
116
|
+
raise NotImplementedError(f"Shell script installation not supported on {platform.system()}")
|
|
117
|
+
subprocess.run(f"bash {installer_path}", shell=True, check=True)
|
|
118
|
+
version_to_be_installed = "scripted_installation"
|
|
119
|
+
elif installer_arch_os.endswith(".ps1"):
|
|
120
|
+
if platform.system() != "Windows":
|
|
121
|
+
raise NotImplementedError(f"PowerShell script installation not supported on {platform.system()}")
|
|
122
|
+
subprocess.run(f"powershell -ExecutionPolicy Bypass -File {installer_path}", shell=True, check=True)
|
|
123
|
+
version_to_be_installed = "scripted_installation"
|
|
124
|
+
elif installer_arch_os.endswith(".py"):
|
|
125
|
+
import runpy
|
|
126
|
+
runpy.run_path(str(installer_path), run_name=None)["main"](self.installer_data, version=version)
|
|
127
|
+
version_to_be_installed = str(version)
|
|
128
|
+
elif installer_arch_os.startswith("https://"): # its a url to be downloaded
|
|
129
|
+
# downloaded_object = PathExtended(installer_arch_os).download(folder=INSTALL_TMP_DIR)
|
|
130
|
+
from machineconfig.scripts.python.helpers_utils.download import download
|
|
131
|
+
downloaded_object = download(installer_arch_os, output_dir=str(INSTALL_TMP_DIR))
|
|
132
|
+
if downloaded_object is None:
|
|
133
|
+
raise ValueError(f"Failed to download from URL: {installer_arch_os}")
|
|
134
|
+
# object is either a zip containing a binary or a straight out binary.
|
|
135
|
+
downloaded_object = PathExtended(downloaded_object)
|
|
136
|
+
if downloaded_object.suffix in DECOMPRESS_SUPPORTED_FORMATS:
|
|
137
|
+
downloaded_object = downloaded_object.decompress()
|
|
138
|
+
if downloaded_object.suffix in [".exe", ""]: # likely an executable
|
|
139
|
+
if platform.system() == "Windows":
|
|
140
|
+
exe = find_move_delete_windows(downloaded_file_path=downloaded_object, exe_name=exe_name, delete=True, rename_to=exe_name.replace(".exe", "") + ".exe")
|
|
141
|
+
elif platform.system() in ["Linux", "Darwin"]:
|
|
142
|
+
system_name = "Linux" if platform.system() == "Linux" else "macOS"
|
|
143
|
+
print(f"🐧 Installing on {system_name}...")
|
|
144
|
+
exe = find_move_delete_linux(downloaded=downloaded_object, tool_name=exe_name, delete=True, rename_to=exe_name)
|
|
145
|
+
else:
|
|
146
|
+
error_msg = f"❌ ERROR: System {platform.system()} not supported"
|
|
147
|
+
print(error_msg)
|
|
148
|
+
raise NotImplementedError(error_msg)
|
|
149
|
+
_ = exe
|
|
150
|
+
if exe.name.replace(".exe", "") != exe_name.replace(".exe", ""):
|
|
151
|
+
from rich import print as pprint
|
|
152
|
+
from rich.panel import Panel
|
|
153
|
+
print("⚠️ Warning: Executable name mismatch")
|
|
154
|
+
pprint(Panel(f"Expected exe name: [red]{exe_name}[/red] \nAttained name: [red]{exe.name.replace('.exe', '')}[/red]", title="exe name mismatch", subtitle=repo_url))
|
|
155
|
+
new_exe_name = exe_name + ".exe" if platform.system() == "Windows" else exe_name
|
|
156
|
+
print(f"🔄 Renaming to correct name: {new_exe_name}")
|
|
157
|
+
exe.with_name(name=new_exe_name, inplace=True, overwrite=True)
|
|
158
|
+
version_to_be_installed = "downloaded_binary"
|
|
159
|
+
elif downloaded_object.suffix in [".deb"]:
|
|
160
|
+
install_deb_package(downloaded_object)
|
|
161
|
+
version_to_be_installed = "downloaded_deb"
|
|
162
|
+
else:
|
|
163
|
+
raise ValueError(f"Downloaded file is not an executable: {downloaded_object}")
|
|
164
|
+
else:
|
|
165
|
+
raise NotImplementedError(f"CMD installation method not implemented for: {installer_arch_os}")
|
|
166
|
+
else:
|
|
167
|
+
assert repo_url.startswith("https://github.com/"), f"repoURL must be a GitHub URL, got {repo_url}"
|
|
168
|
+
downloaded, version_to_be_installed = self.binary_download(version=version)
|
|
169
|
+
if str(downloaded).endswith(".deb"): install_deb_package(downloaded)
|
|
172
170
|
else:
|
|
173
171
|
if platform.system() == "Windows":
|
|
174
|
-
print("🪟 Installing on Windows...")
|
|
175
172
|
exe = find_move_delete_windows(downloaded_file_path=downloaded, exe_name=exe_name, delete=True, rename_to=exe_name.replace(".exe", "") + ".exe")
|
|
176
173
|
elif platform.system() in ["Linux", "Darwin"]:
|
|
177
174
|
system_name = "Linux" if platform.system() == "Linux" else "macOS"
|
|
@@ -181,205 +178,131 @@ class Installer:
|
|
|
181
178
|
error_msg = f"❌ ERROR: System {platform.system()} not supported"
|
|
182
179
|
print(error_msg)
|
|
183
180
|
raise NotImplementedError(error_msg)
|
|
184
|
-
|
|
185
181
|
_ = exe
|
|
186
182
|
if exe.name.replace(".exe", "") != exe_name.replace(".exe", ""):
|
|
187
183
|
from rich import print as pprint
|
|
188
184
|
from rich.panel import Panel
|
|
189
|
-
|
|
190
185
|
print("⚠️ Warning: Executable name mismatch")
|
|
191
186
|
pprint(Panel(f"Expected exe name: [red]{exe_name}[/red] \nAttained name: [red]{exe.name.replace('.exe', '')}[/red]", title="exe name mismatch", subtitle=repo_url))
|
|
192
187
|
new_exe_name = exe_name + ".exe" if platform.system() == "Windows" else exe_name
|
|
193
188
|
print(f"🔄 Renaming to correct name: {new_exe_name}")
|
|
194
189
|
exe.with_name(name=new_exe_name, inplace=True, overwrite=True)
|
|
195
|
-
|
|
196
|
-
print(f"💾 Saving version information to: {INSTALL_VERSION_ROOT.joinpath(exe_name)}")
|
|
197
190
|
INSTALL_VERSION_ROOT.joinpath(exe_name).parent.mkdir(parents=True, exist_ok=True)
|
|
198
|
-
INSTALL_VERSION_ROOT.joinpath(exe_name).write_text(version_to_be_installed, encoding="utf-8")
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
app_name = self.installer_data.get("appName", "unknown")
|
|
205
|
-
strip_v = self.installer_data.get("stripVersion", False)
|
|
206
|
-
|
|
207
|
-
print(f"\n{'=' * 80}\n📥 DOWNLOADING: {exe_name} 📥\n{'=' * 80}")
|
|
208
|
-
download_link: Optional[Path] = None
|
|
191
|
+
INSTALL_VERSION_ROOT.joinpath(exe_name).write_text(version_to_be_installed or "unknown", encoding="utf-8")
|
|
192
|
+
def binary_download(self, version: Optional[str]) -> tuple[PathExtended, str]:
|
|
193
|
+
exe_name = self._get_exe_name()
|
|
194
|
+
repo_url = self.installer_data["repoURL"]
|
|
195
|
+
# app_name = self.installer_data["appName"]
|
|
196
|
+
download_link: Optional[str] = None
|
|
209
197
|
version_to_be_installed: Optional[str] = None
|
|
210
|
-
if "github" not in repo_url or
|
|
211
|
-
|
|
198
|
+
if "github" not in repo_url or (any(ext in repo_url for ext in DECOMPRESS_SUPPORTED_FORMATS)):
|
|
199
|
+
# Direct download URL
|
|
200
|
+
download_link = repo_url
|
|
212
201
|
version_to_be_installed = "predefined_url"
|
|
213
202
|
print(f"🔗 Using direct download URL: {download_link}")
|
|
214
203
|
print(f"📦 Version to be installed: {version_to_be_installed}")
|
|
215
|
-
elif self._any_direct_http_template():
|
|
216
|
-
template, arch = self._select_template()
|
|
217
|
-
if not template.startswith("http"):
|
|
218
|
-
# Fall back to github-style handling below
|
|
219
|
-
pass
|
|
220
|
-
else:
|
|
221
|
-
download_link = Path(template)
|
|
222
|
-
version_to_be_installed = "predefined_url"
|
|
223
|
-
system_name = self._system_name()
|
|
224
|
-
print(f"🧭 Detected system={system_name} arch={arch}")
|
|
225
|
-
print(f"🔗 Using architecture-specific direct URL: {download_link}")
|
|
226
|
-
print(f"📦 Version to be installed: {version_to_be_installed}")
|
|
227
|
-
# continue to unified download logic below
|
|
228
|
-
|
|
229
204
|
else:
|
|
205
|
+
# GitHub repository
|
|
230
206
|
print("🌐 Retrieving release information from GitHub...")
|
|
231
|
-
|
|
207
|
+
arch = get_normalized_arch()
|
|
208
|
+
os_name = get_os_name()
|
|
209
|
+
print(f"🧭 Detected system={os_name} arch={arch}")
|
|
210
|
+
# Use existing get_github_release method to get download link and version
|
|
211
|
+
download_link, version_to_be_installed = self.get_github_release(repo_url, version)
|
|
212
|
+
if download_link is None:
|
|
213
|
+
raise ValueError(f"Could not retrieve download link for {exe_name} version {version or 'latest'}")
|
|
232
214
|
print(f"📦 Version to be installed: {version_to_be_installed}")
|
|
233
|
-
print(f"
|
|
234
|
-
|
|
235
|
-
version_to_be_installed_stripped = version_to_be_installed.replace("v", "") if strip_v else version_to_be_installed
|
|
236
|
-
version_to_be_installed_stripped = version_to_be_installed_stripped.replace("ipinfo-", "")
|
|
237
|
-
|
|
238
|
-
template, arch = self._select_template()
|
|
239
|
-
system_name = self._system_name()
|
|
240
|
-
file_name = template.format(version_to_be_installed_stripped)
|
|
241
|
-
print(f"🧭 Detected system={system_name} arch={arch}")
|
|
242
|
-
print(f"📄 Using template: {template}")
|
|
243
|
-
print(f"🗂️ Resolved file name: {file_name}")
|
|
244
|
-
|
|
245
|
-
print(f"📄 File name: {file_name}")
|
|
246
|
-
download_link = release_url.joinpath(file_name)
|
|
247
|
-
|
|
215
|
+
print(f"🔗 Download URL: {download_link}")
|
|
248
216
|
assert download_link is not None, "download_link must be set"
|
|
249
217
|
assert version_to_be_installed is not None, "version_to_be_installed must be set"
|
|
250
|
-
print(f"📥 Downloading {app_name} from: {download_link}")
|
|
251
218
|
downloaded = PathExtended(download_link).download(folder=INSTALL_TMP_DIR).decompress()
|
|
252
|
-
|
|
219
|
+
if downloaded.is_dir() and len(downloaded.search("*", r=True)) == 1:
|
|
220
|
+
only_file_in = next(downloaded.glob("*"))
|
|
221
|
+
if only_file_in.is_file() and only_file_in.suffix in DECOMPRESS_SUPPORTED_FORMATS: # further decompress
|
|
222
|
+
downloaded = only_file_in.decompress()
|
|
253
223
|
return downloaded, version_to_be_installed
|
|
254
|
-
|
|
255
|
-
# --------------------------- Arch / template helpers ---------------------------
|
|
256
|
-
def _normalized_arch(self) -> str:
|
|
257
|
-
arch_raw = platform.machine().lower()
|
|
258
|
-
if arch_raw in ("x86_64", "amd64"):
|
|
259
|
-
return "amd64"
|
|
260
|
-
if arch_raw in ("aarch64", "arm64", "armv8", "armv8l"):
|
|
261
|
-
return "arm64"
|
|
262
|
-
return arch_raw
|
|
263
|
-
|
|
264
|
-
def _system_name(self) -> str:
|
|
265
|
-
sys_ = platform.system()
|
|
266
|
-
if sys_ == "Darwin":
|
|
267
|
-
return "macOS"
|
|
268
|
-
return sys_
|
|
269
|
-
|
|
270
|
-
def _any_direct_http_template(self) -> bool:
|
|
271
|
-
filename_templates = self.installer_data.get("filenameTemplate", {})
|
|
272
|
-
templates: list[str] = []
|
|
273
|
-
|
|
274
|
-
for arch_templates in filename_templates.values():
|
|
275
|
-
templates.extend([t for t in arch_templates.values() if t])
|
|
276
|
-
|
|
277
|
-
return any(t for t in templates if t.startswith("http"))
|
|
278
|
-
|
|
279
|
-
def _select_template(self) -> tuple[str, str]:
|
|
280
|
-
sys_name = platform.system()
|
|
281
|
-
arch = self._normalized_arch()
|
|
282
|
-
|
|
283
|
-
filename_templates = self.installer_data.get("filenameTemplate", {})
|
|
284
|
-
|
|
285
|
-
# Get templates for each architecture
|
|
286
|
-
amd64_templates = filename_templates.get("amd64", {})
|
|
287
|
-
arm64_templates = filename_templates.get("arm64", {})
|
|
288
|
-
|
|
289
|
-
# mapping logic
|
|
290
|
-
candidates: list[str] = []
|
|
291
|
-
template: Optional[str] = None
|
|
292
|
-
|
|
293
|
-
if sys_name == "Windows":
|
|
294
|
-
if arch == "arm64" and arm64_templates.get("windows"):
|
|
295
|
-
template = arm64_templates["windows"]
|
|
296
|
-
else:
|
|
297
|
-
template = amd64_templates.get("windows", "")
|
|
298
|
-
candidates = ["arm64.windows", "amd64.windows"]
|
|
299
|
-
elif sys_name == "Linux":
|
|
300
|
-
if arch == "arm64" and arm64_templates.get("linux"):
|
|
301
|
-
template = arm64_templates["linux"]
|
|
302
|
-
else:
|
|
303
|
-
template = amd64_templates.get("linux", "")
|
|
304
|
-
candidates = ["arm64.linux", "amd64.linux"]
|
|
305
|
-
elif sys_name == "Darwin":
|
|
306
|
-
if arch == "arm64" and arm64_templates.get("macos"):
|
|
307
|
-
template = arm64_templates["macos"]
|
|
308
|
-
elif arch == "amd64" and amd64_templates.get("macos"):
|
|
309
|
-
template = amd64_templates["macos"]
|
|
310
|
-
else:
|
|
311
|
-
# fallback between available mac templates
|
|
312
|
-
template = arm64_templates.get("macos") or amd64_templates.get("macos") or ""
|
|
313
|
-
candidates = ["arm64.macos", "amd64.macos"]
|
|
314
|
-
else:
|
|
315
|
-
raise NotImplementedError(f"System {sys_name} not supported")
|
|
316
|
-
|
|
317
|
-
if not template:
|
|
318
|
-
raise ValueError(f"No filename template available for system={sys_name} arch={arch}. Checked {candidates}")
|
|
319
|
-
|
|
320
|
-
return template, arch
|
|
321
|
-
|
|
322
224
|
@staticmethod
|
|
323
|
-
def
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
_latest_version = requests.get(str(repo_url) + "/releases/latest", timeout=10).url.split("/")[
|
|
333
|
-
-1
|
|
334
|
-
] # this is to resolve the redirection that occures: https://stackoverflow.com/questions/36070821/how-to-get-redirect-url-using-python-requests
|
|
335
|
-
version_to_be_installed = _latest_version
|
|
336
|
-
print(f"✅ Latest version detected: {version_to_be_installed}")
|
|
337
|
-
# print(version_to_be_installed)
|
|
338
|
-
else:
|
|
339
|
-
version_to_be_installed = version
|
|
340
|
-
print(f"📝 Using specified version: {version_to_be_installed}")
|
|
341
|
-
|
|
342
|
-
release_url = Path(repo_url + "/releases/download/" + version_to_be_installed)
|
|
343
|
-
print(f"🔗 Release download URL: {release_url}\n{'=' * 80}")
|
|
344
|
-
return release_url, version_to_be_installed
|
|
225
|
+
def _get_repo_name_from_url(repo_url: str) -> str:
|
|
226
|
+
"""Extract owner/repo from GitHub URL."""
|
|
227
|
+
try:
|
|
228
|
+
parsed = urlparse(repo_url)
|
|
229
|
+
path_parts = parsed.path.strip("/").split("/")
|
|
230
|
+
return f"{path_parts[0]}/{path_parts[1]}"
|
|
231
|
+
except (IndexError, AttributeError):
|
|
232
|
+
return ""
|
|
345
233
|
|
|
346
234
|
@staticmethod
|
|
347
|
-
def
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
print(f"
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
235
|
+
def _fetch_github_release_data(repo_name: str, version: Optional[str] = None) -> Optional[dict[str, Any]]:
|
|
236
|
+
"""Fetch release data from GitHub API using requests."""
|
|
237
|
+
import requests
|
|
238
|
+
try:
|
|
239
|
+
if version and version.lower() != "latest": # Fetch specific version
|
|
240
|
+
url = f"https://api.github.com/repos/{repo_name}/releases/tags/{version}"
|
|
241
|
+
else: # Fetch latest release
|
|
242
|
+
url = f"https://api.github.com/repos/{repo_name}/releases/latest"
|
|
243
|
+
response = requests.get(url, timeout=30)
|
|
244
|
+
if response.status_code != 200:
|
|
245
|
+
print(f"❌ Failed to fetch data for {repo_name}: HTTP {response.status_code}")
|
|
246
|
+
return None
|
|
247
|
+
response_data = response.json()
|
|
248
|
+
# Check if API returned an error
|
|
249
|
+
if "message" in response_data:
|
|
250
|
+
if "API rate limit exceeded" in response_data.get("message", ""):
|
|
251
|
+
print(f"🚫 Rate limit exceeded for {repo_name}")
|
|
252
|
+
return None
|
|
253
|
+
elif "Not Found" in response_data.get("message", ""):
|
|
254
|
+
print(f"🔍 No releases found for {repo_name}")
|
|
255
|
+
return None
|
|
256
|
+
|
|
257
|
+
return response_data
|
|
258
|
+
|
|
259
|
+
except (requests.RequestException, requests.Timeout, json.JSONDecodeError) as e:
|
|
260
|
+
print(f"❌ Error fetching {repo_name}: {e}")
|
|
261
|
+
return None
|
|
262
|
+
|
|
263
|
+
def get_github_release(self, repo_url: str, version: Optional[str]) -> tuple[Optional[str], Optional[str]]:
|
|
264
|
+
"""
|
|
265
|
+
Get download link and version from GitHub release based on fileNamePattern.
|
|
266
|
+
Returns (download_url, actual_version)
|
|
267
|
+
"""
|
|
268
|
+
arch = get_normalized_arch()
|
|
269
|
+
os_name = get_os_name()
|
|
270
|
+
filename_pattern = self.installer_data["fileNamePattern"][arch][os_name]
|
|
271
|
+
if filename_pattern is None:
|
|
272
|
+
raise ValueError(f"No fileNamePattern for {self._get_exe_name()} on {os_name} {arch}")
|
|
273
|
+
repo_name = self._get_repo_name_from_url(repo_url)
|
|
274
|
+
if not repo_name:
|
|
275
|
+
print(f"❌ Invalid repository URL: {repo_url}")
|
|
276
|
+
return None, None
|
|
277
|
+
release_data = self._fetch_github_release_data(repo_name, version)
|
|
278
|
+
if not release_data:
|
|
279
|
+
return None, None
|
|
280
|
+
# print(release_data)
|
|
281
|
+
actual_version = release_data.get("tag_name", "unknown")
|
|
282
|
+
filename = filename_pattern.format(version=actual_version)
|
|
283
|
+
|
|
284
|
+
available_filenames: list[str] = []
|
|
285
|
+
for asset in release_data.get("assets", []):
|
|
286
|
+
an_dl = asset.get("browser_download_url", "NA")
|
|
287
|
+
available_filenames.append(an_dl.split("/")[-1])
|
|
288
|
+
if filename not in available_filenames:
|
|
289
|
+
candidates = [
|
|
290
|
+
filename,
|
|
291
|
+
filename_pattern.format(version=actual_version),
|
|
292
|
+
filename_pattern.format(version=actual_version.replace("v", "")),
|
|
293
|
+
]
|
|
294
|
+
|
|
295
|
+
# Include hyphen/underscore variants
|
|
296
|
+
variants = []
|
|
297
|
+
for f in candidates:
|
|
298
|
+
variants += [f, f.replace("-", "_"), f.replace("_", "-")]
|
|
299
|
+
|
|
300
|
+
for f in variants:
|
|
301
|
+
if f in available_filenames:
|
|
302
|
+
filename = f
|
|
303
|
+
break
|
|
376
304
|
else:
|
|
377
|
-
print(f"
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
print(f"📦 {exe_name} is not installed. Will install version: {version_to_be_installed}")
|
|
382
|
-
tmp_path.write_text(version_to_be_installed, encoding="utf-8")
|
|
383
|
-
|
|
384
|
-
print(f"{'=' * 80}")
|
|
385
|
-
return ("⚠️ NotInstalled", "None", version_to_be_installed.strip())
|
|
305
|
+
print(f"❌ Filename not found in assets. Tried: {variants}\nAvailable: {available_filenames}")
|
|
306
|
+
return None, None
|
|
307
|
+
browser_download_url = f"{repo_url}/releases/download/{actual_version}/{filename}"
|
|
308
|
+
return browser_download_url, actual_version
|