machineconfig 6.82__py3-none-any.whl → 8.51__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.
- machineconfig/cluster/remote/cloud_manager.py +1 -1
- machineconfig/cluster/remote/run_cluster.py +1 -1
- machineconfig/cluster/remote/run_remote.py +1 -1
- machineconfig/cluster/sessions_managers/utils/maker.py +29 -15
- machineconfig/cluster/sessions_managers/wt_local.py +17 -222
- machineconfig/cluster/sessions_managers/wt_local_manager.py +56 -194
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +42 -198
- 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_reporting.py +76 -0
- machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
- machineconfig/cluster/sessions_managers/zellij_local.py +1 -1
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +4 -2
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +3 -2
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +2 -2
- machineconfig/jobs/installer/checks/check_installations.py +133 -0
- machineconfig/jobs/installer/checks/install_utils.py +132 -0
- machineconfig/jobs/installer/checks/report_utils.py +39 -0
- machineconfig/jobs/installer/checks/vt_utils.py +89 -0
- machineconfig/jobs/installer/installer_data.json +1500 -310
- machineconfig/jobs/installer/linux_scripts/docker.sh +6 -9
- machineconfig/jobs/installer/linux_scripts/q.sh +10 -7
- machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
- machineconfig/jobs/installer/package_groups.py +62 -91
- machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
- machineconfig/jobs/installer/{custom → python_scripts}/boxes.py +2 -3
- machineconfig/jobs/installer/{custom_dev → python_scripts}/brave.py +5 -3
- machineconfig/jobs/installer/python_scripts/cloudflare_warp_cli.py +23 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/code.py +14 -9
- machineconfig/jobs/installer/{custom_dev → python_scripts}/dubdb_adbc.py +1 -1
- machineconfig/jobs/installer/python_scripts/hx.py +214 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/nerdfont.py +2 -2
- machineconfig/jobs/installer/{custom_dev → python_scripts}/nerfont_windows_helper.py +32 -26
- machineconfig/jobs/installer/python_scripts/sysabc.py +145 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/wezterm.py +2 -19
- machineconfig/jobs/installer/{custom_dev → python_scripts}/winget.py +10 -14
- machineconfig/jobs/installer/python_scripts/yazi.py +139 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nfs +0 -1
- machineconfig/jobs/scripts/powershell_scripts/cmatrix.ps1 +52 -0
- machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +13 -0
- machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +4 -0
- machineconfig/jobs/scripts_dynamic/a.py +428 -0
- machineconfig/logger.py +1 -2
- machineconfig/profile/create_helper.py +56 -18
- machineconfig/profile/create_links.py +79 -21
- machineconfig/profile/create_links_export.py +87 -36
- machineconfig/profile/create_shell_profile.py +92 -127
- machineconfig/profile/mapper_data.toml +45 -0
- machineconfig/profile/mapper_dotfiles.toml +249 -0
- machineconfig/scripts/__init__.py +0 -4
- machineconfig/scripts/linux/wrap_mcfg +46 -0
- machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
- machineconfig/scripts/python/agents.py +85 -165
- machineconfig/scripts/python/ai/initai.py +4 -2
- machineconfig/scripts/python/ai/scripts/__init__.py +1 -0
- machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
- machineconfig/scripts/python/ai/{command_runner → scripts}/command_runner.sh +1 -1
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +2 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +8 -6
- machineconfig/scripts/python/ai/solutions/claude/claude.py +1 -1
- machineconfig/scripts/python/ai/solutions/cline/cline.py +1 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
- machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +6 -6
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +33 -0
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
- machineconfig/scripts/python/ai/solutions/crush/crush.py +1 -1
- machineconfig/scripts/python/ai/solutions/cursor/cursors.py +1 -1
- machineconfig/scripts/python/ai/solutions/gemini/gemini.py +1 -1
- machineconfig/scripts/python/ai/solutions/gemini/settings.json +3 -0
- machineconfig/scripts/python/ai/{generate_files.py → utils/generate_files.py} +2 -2
- machineconfig/scripts/python/ai/{solutions → utils}/generic.py +2 -15
- machineconfig/scripts/python/ai/{vscode_tasks.py → utils/vscode_tasks.py} +13 -5
- machineconfig/scripts/python/cloud.py +58 -11
- machineconfig/scripts/python/croshell.py +10 -162
- machineconfig/scripts/python/devops.py +73 -36
- machineconfig/scripts/python/devops_navigator.py +16 -6
- machineconfig/scripts/python/fire_jobs.py +8 -222
- machineconfig/scripts/python/ftpx.py +7 -200
- machineconfig/scripts/python/graph/cli_graph.json +8743 -0
- machineconfig/scripts/python/{env_manager → helper_env}/path_manager_tui.py +2 -2
- machineconfig/scripts/python/helpers/helper_env/env_manager_tui.py +204 -0
- machineconfig/scripts/python/helpers/helper_env/path_manager_tui.py +228 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_crush.json +1 -1
- machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_cursor_agents.py +3 -4
- machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
- machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
- machineconfig/scripts/python/helpers/helpers_agents/agents_impl.py +168 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_launch.py +38 -16
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_helper_types.py +11 -14
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aichat/config.yaml +5 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aider/.aider.conf.yml +2 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/copilot/config.yml +1 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/crush/crush.json +10 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/gemini/settings.json +12 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/privacy.py +109 -0
- machineconfig/scripts/python/helpers/helpers_agents/templates/prompt.txt +10 -0
- machineconfig/scripts/python/helpers/helpers_agents/templates/template.sh +34 -0
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_copy.py +32 -25
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_mount.py +29 -22
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_sync.py +9 -8
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers2.py +1 -1
- machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/crosh.py +3 -3
- machineconfig/scripts/python/helpers/helpers_croshell/croshell_impl.py +225 -0
- machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/scheduler.py +4 -4
- machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/start_slidev.py +12 -12
- machineconfig/scripts/python/helpers/helpers_devops/backup_config.py +149 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_backup_retrieve.py +262 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_config.py +98 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_config_dotfile.py +274 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_data.py +67 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_nw.py +201 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_repos.py +274 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_self.py +197 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_share_file.py +151 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_share_server.py +125 -0
- machineconfig/scripts/python/{helpers_devops/cli_terminal.py → helpers/helpers_devops/cli_share_terminal.py} +26 -22
- machineconfig/scripts/python/helpers/helpers_devops/cli_ssh.py +167 -0
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_status.py +17 -23
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_update_repos.py +1 -1
- machineconfig/scripts/python/{interactive.py → helpers/helpers_devops/interactive.py} +78 -71
- machineconfig/scripts/python/helpers/helpers_devops/run_script.py +197 -0
- machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.ps1 +41 -0
- machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.sh +48 -0
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_wezterm_theme.py +4 -4
- machineconfig/scripts/python/{helpers_fire/helpers4.py → helpers/helpers_fire_command/file_wrangler.py} +57 -20
- machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_args_helper.py +1 -0
- machineconfig/scripts/python/helpers/helpers_fire_command/fire_jobs_impl.py +233 -0
- machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_route_helper.py +26 -16
- machineconfig/scripts/python/helpers/helpers_msearch/__init__.py +5 -0
- machineconfig/scripts/python/helpers/helpers_msearch/msearch_impl.py +248 -0
- machineconfig/scripts/{linux → python/helpers/helpers_msearch/scripts_linux}/fzfg +6 -5
- machineconfig/scripts/python/helpers/helpers_msearch/scripts_linux/search_with_context.sh +48 -0
- machineconfig/scripts/python/helpers/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
- machineconfig/scripts/python/helpers/helpers_navigator/__init__.py +20 -0
- machineconfig/scripts/python/helpers/helpers_navigator/cli_graph_loader.py +234 -0
- machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/command_builder.py +61 -13
- machineconfig/scripts/python/helpers/helpers_navigator/command_detail.py +153 -0
- machineconfig/scripts/python/helpers/helpers_navigator/command_tree.py +45 -0
- machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/data_models.py +18 -11
- machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/main_app.py +5 -5
- machineconfig/scripts/python/helpers/helpers_network/address.py +174 -0
- machineconfig/scripts/python/helpers/helpers_network/address_switch.py +78 -0
- machineconfig/scripts/python/helpers/helpers_network/ftpx_impl.py +276 -0
- machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nfs.py +2 -2
- machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_ssh.py +3 -3
- machineconfig/scripts/python/helpers/helpers_network/ssh_add_identity.py +73 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh_add_ssh_key.py +175 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh_debug_linux.py +319 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh_debug_windows.py +275 -0
- machineconfig/scripts/python/{nw → helpers/helpers_network}/wifi_conn.py +1 -53
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action.py +3 -3
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action_helper.py +3 -3
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/clone.py +0 -1
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/cloud_repo_sync.py +159 -48
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/grource.py +4 -3
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/record.py +33 -12
- machineconfig/scripts/python/helpers/helpers_repos/repo_analyzer_1.py +160 -0
- machineconfig/scripts/python/{helpers_repos/count_lines.py → helpers/helpers_repos/repo_analyzer_2.py} +156 -191
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/update.py +0 -6
- machineconfig/scripts/python/helpers/helpers_search/ast_search.py +74 -0
- machineconfig/scripts/python/helpers/helpers_search/qr_code.py +166 -0
- machineconfig/scripts/python/helpers/helpers_search/repo_rag.py +325 -0
- machineconfig/scripts/python/helpers/helpers_search/script_help.py +81 -0
- machineconfig/scripts/python/helpers/helpers_search/symantic_search.py +25 -0
- machineconfig/scripts/python/helpers/helpers_sessions/__init__.py +0 -0
- machineconfig/scripts/python/helpers/helpers_sessions/sessions_impl.py +186 -0
- machineconfig/scripts/python/{helpers_sessions → helpers/helpers_sessions}/sessions_multiprocess.py +20 -14
- machineconfig/scripts/python/helpers/helpers_terminal/__init__.py +0 -0
- machineconfig/scripts/python/helpers/helpers_terminal/terminal_impl.py +96 -0
- machineconfig/scripts/python/helpers/helpers_utils/download.py +150 -0
- machineconfig/scripts/python/helpers/helpers_utils/pdf.py +96 -0
- machineconfig/scripts/python/helpers/helpers_utils/python.py +210 -0
- machineconfig/scripts/python/helpers/helpers_utils/specs.py +246 -0
- machineconfig/scripts/python/mcfg_entry.py +143 -0
- machineconfig/scripts/python/msearch.py +26 -0
- machineconfig/scripts/python/sessions.py +69 -135
- machineconfig/scripts/python/terminal.py +58 -0
- machineconfig/scripts/python/utils.py +115 -38
- machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
- machineconfig/settings/atuin/config.toml +294 -0
- machineconfig/settings/atuin/themes/catppuccin-mocha-mauve.toml +12 -0
- 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 +3 -2
- machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
- machineconfig/settings/lf/windows/lfrc +14 -16
- machineconfig/settings/linters/.ruff.toml +2 -1
- machineconfig/settings/marimo/marimo.toml +1 -1
- machineconfig/settings/marimo/snippets/globalize.py +34 -0
- machineconfig/settings/mprocs/windows/mprocs.yaml +2 -2
- machineconfig/settings/shells/bash/init.sh +47 -12
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
- machineconfig/settings/shells/nushell/config.nu +25 -33
- machineconfig/settings/shells/nushell/env.nu +21 -8
- machineconfig/settings/shells/nushell/init.nu +138 -0
- machineconfig/settings/shells/pwsh/init.ps1 +111 -17
- machineconfig/settings/shells/pwsh/search_pwsh_history.ps1 +99 -0
- machineconfig/settings/shells/starship/starship.toml +16 -0
- machineconfig/settings/shells/wezterm/wezterm.lua +6 -1
- machineconfig/settings/shells/wt/settings.json +27 -18
- machineconfig/settings/shells/zsh/init.sh +42 -23
- machineconfig/settings/television/cable_unix/alias.toml +8 -0
- machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
- machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
- machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
- machineconfig/settings/television/cable_unix/channels.toml +19 -0
- machineconfig/settings/television/cable_unix/dirs.toml +13 -0
- machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
- machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
- machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_unix/env.toml +17 -0
- machineconfig/settings/television/cable_unix/files.toml +11 -0
- machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
- machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
- machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
- machineconfig/settings/television/cable_unix/git-log.toml +12 -0
- machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
- machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
- machineconfig/settings/television/cable_unix/guix.toml +20 -0
- machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
- machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
- machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
- machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
- machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
- machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
- machineconfig/settings/television/cable_unix/procs.toml +20 -0
- machineconfig/settings/television/cable_unix/text.toml +17 -0
- machineconfig/settings/television/cable_unix/tldr.toml +18 -0
- machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
- machineconfig/settings/television/cable_windows/alias.toml +7 -0
- machineconfig/settings/television/cable_windows/dirs.toml +13 -0
- machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
- machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_windows/env.toml +17 -0
- machineconfig/settings/television/cable_windows/files.toml +14 -0
- machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
- machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
- machineconfig/settings/television/cable_windows/git-log.toml +11 -0
- machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
- machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
- machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
- machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
- machineconfig/settings/television/cable_windows/text.toml +17 -0
- machineconfig/settings/tv/config.toml +234 -0
- machineconfig/settings/tv/themes/catppuccin-mocha-sky.toml +22 -0
- machineconfig/settings/wsl/.wslconfig +5 -30
- machineconfig/settings/wt/__init__.py +0 -0
- machineconfig/settings/yazi/init.lua +61 -0
- machineconfig/settings/yazi/keymap_linux.toml +94 -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/theme.toml +4 -0
- machineconfig/settings/yazi/yazi_linux.toml +94 -0
- machineconfig/settings/yazi/yazi_windows.toml +58 -0
- machineconfig/settings/zellij/layouts/st.kdl +40 -9
- machineconfig/settings/zellij/layouts/st2.kdl +1 -1
- machineconfig/setup_linux/__init__.py +2 -2
- machineconfig/setup_linux/apps_desktop.sh +8 -27
- machineconfig/setup_linux/web_shortcuts/interactive.sh +27 -12
- machineconfig/setup_linux/web_shortcuts/live_from_github.sh +34 -0
- machineconfig/setup_mac/__init__.py +1 -4
- machineconfig/setup_mac/apps_gui.sh +248 -0
- machineconfig/setup_windows/__init__.py +2 -5
- machineconfig/setup_windows/uv.ps1 +8 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +28 -12
- machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +31 -0
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
- machineconfig/type_hinting/sql/__init__.py +1 -0
- machineconfig/type_hinting/sql/base.py +216 -0
- machineconfig/type_hinting/sql/core_schema.py +64 -0
- machineconfig/type_hinting/sql/core_schema_typeddict.py +41 -0
- machineconfig/type_hinting/sql/typeddict_codegen.py +222 -0
- machineconfig/type_hinting/typedict/__init__.py +1 -0
- machineconfig/type_hinting/typedict/ast_utils.py +130 -0
- machineconfig/type_hinting/typedict/generator_helpers.py +319 -0
- machineconfig/type_hinting/typedict/generators.py +231 -0
- machineconfig/type_hinting/typedict/polars_schema.py +24 -0
- machineconfig/type_hinting/typedict/polars_schema_typeddict.py +63 -0
- machineconfig/utils/accessories.py +31 -4
- machineconfig/utils/code.py +163 -51
- machineconfig/utils/files/ascii_art.py +11 -15
- machineconfig/utils/files/headers.py +6 -7
- machineconfig/utils/files/read.py +8 -1
- machineconfig/utils/installer_utils/github_release_bulk.py +95 -138
- machineconfig/utils/installer_utils/github_release_scraper.py +99 -0
- machineconfig/utils/installer_utils/install_from_url.py +183 -0
- machineconfig/utils/installer_utils/installer_class.py +53 -102
- machineconfig/utils/installer_utils/installer_cli.py +161 -0
- machineconfig/utils/installer_utils/installer_helper.py +129 -0
- machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +42 -91
- machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +20 -65
- machineconfig/utils/io.py +94 -9
- machineconfig/utils/links.py +56 -38
- machineconfig/utils/meta.py +38 -21
- machineconfig/utils/options.py +81 -23
- machineconfig/utils/options_utils/__init__.py +0 -0
- machineconfig/utils/options_utils/options_tv_linux.py +211 -0
- machineconfig/utils/options_utils/options_tv_windows.py +88 -0
- machineconfig/utils/options_utils/tv_options.py +37 -0
- machineconfig/utils/path_extended.py +52 -102
- machineconfig/utils/path_helper.py +76 -23
- machineconfig/utils/procs.py +1 -1
- machineconfig/utils/scheduler.py +26 -53
- machineconfig/utils/scheduling.py +0 -2
- machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
- machineconfig/utils/schemas/layouts/layout_types.py +1 -1
- machineconfig/utils/source_of_truth.py +6 -1
- machineconfig/utils/ssh.py +216 -419
- machineconfig/utils/ssh_utils/abc.py +5 -0
- machineconfig/utils/ssh_utils/copy_from_here.py +116 -0
- machineconfig/utils/ssh_utils/copy_to_here.py +303 -0
- machineconfig/utils/ssh_utils/utils.py +158 -0
- machineconfig/utils/ssh_utils/wsl.py +147 -0
- machineconfig/utils/ssh_utils/wsl_helper.py +217 -0
- machineconfig/utils/terminal.py +1 -0
- machineconfig/utils/upgrade_packages.py +107 -35
- machineconfig/utils/ve.py +12 -4
- machineconfig-8.51.dist-info/METADATA +140 -0
- machineconfig-8.51.dist-info/RECORD +543 -0
- {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/entry_points.txt +4 -1
- machineconfig/jobs/installer/check_installations.py +0 -248
- machineconfig/jobs/installer/custom/hx.py +0 -140
- machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
- machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
- machineconfig/jobs/installer/powershell_scripts/archive_pygraphviz.ps1 +0 -12
- machineconfig/jobs/installer/powershell_scripts/openssh-server_add_key.ps1 +0 -7
- machineconfig/jobs/installer/powershell_scripts/openssh-server_copy-ssh-id.ps1 +0 -14
- machineconfig/profile/backup.toml +0 -49
- machineconfig/profile/mapper.toml +0 -256
- machineconfig/scripts/linux/fzf2g +0 -21
- machineconfig/scripts/linux/fzfag +0 -17
- machineconfig/scripts/linux/fzffg +0 -25
- machineconfig/scripts/linux/fzfrga +0 -21
- machineconfig/scripts/linux/mcfgs +0 -38
- machineconfig/scripts/linux/other/share_smb +0 -1
- machineconfig/scripts/linux/other/switch_ip +0 -20
- machineconfig/scripts/linux/skrg +0 -4
- machineconfig/scripts/linux/warp-cli.sh +0 -122
- machineconfig/scripts/linux/z_ls +0 -104
- machineconfig/scripts/python/ai/command_runner/prompt.txt +0 -9
- machineconfig/scripts/python/helpers_devops/cli_config.py +0 -120
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +0 -77
- machineconfig/scripts/python/helpers_devops/cli_data.py +0 -25
- machineconfig/scripts/python/helpers_devops/cli_nw.py +0 -73
- machineconfig/scripts/python/helpers_devops/cli_repos.py +0 -181
- machineconfig/scripts/python/helpers_devops/cli_self.py +0 -122
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +0 -104
- machineconfig/scripts/python/helpers_devops/cli_utils.py +0 -221
- machineconfig/scripts/python/helpers_devops/devops_backup_retrieve.py +0 -80
- machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +0 -3
- machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_crush.py +0 -37
- machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_gemini.py +0 -44
- machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_qwen.py +0 -43
- machineconfig/scripts/python/helpers_fire/prompt.txt +0 -2
- machineconfig/scripts/python/helpers_fire/template.sh +0 -15
- machineconfig/scripts/python/helpers_navigator/__init__.py +0 -20
- machineconfig/scripts/python/helpers_navigator/command_detail.py +0 -44
- machineconfig/scripts/python/helpers_navigator/command_tree.py +0 -588
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +0 -17
- machineconfig/scripts/python/helpers_repos/entrypoint.py +0 -76
- machineconfig/scripts/python/helpers_repos/secure_repo.py +0 -15
- machineconfig/scripts/python/mcfg.py +0 -48
- machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
- machineconfig/scripts/python/nw/devops_add_identity.py +0 -82
- machineconfig/scripts/python/nw/devops_add_ssh_key.py +0 -134
- machineconfig/scripts/python/nw/ssh_debug_linux.py +0 -391
- machineconfig/scripts/python/nw/ssh_debug_windows.py +0 -338
- machineconfig/scripts/python/nw/wsl_windows_transfer.py +0 -66
- machineconfig/scripts/windows/fzfb.ps1 +0 -3
- machineconfig/scripts/windows/fzfg.ps1 +0 -2
- machineconfig/scripts/windows/fzfrga.bat +0 -20
- machineconfig/scripts/windows/mcfgs.ps1 +0 -17
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +0 -13
- machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
- machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
- machineconfig/settings/lf/windows/tst.ps1 +0 -1
- machineconfig/settings/yazi/yazi.toml +0 -4
- machineconfig/setup_linux/apps.sh +0 -66
- machineconfig/setup_linux/others/cli_installation.sh +0 -137
- machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh +0 -30
- machineconfig/setup_linux/ssh/openssh_all.sh +0 -25
- machineconfig/setup_linux/ssh/openssh_wsl.sh +0 -38
- machineconfig/setup_mac/apps.sh +0 -73
- machineconfig/setup_mac/ssh/openssh_setup.sh +0 -114
- machineconfig/setup_windows/apps.ps1 +0 -62
- machineconfig/setup_windows/others/obs.ps1 +0 -4
- machineconfig/setup_windows/ssh/add-sshkey.ps1 +0 -29
- machineconfig/setup_windows/ssh/add_identity.ps1 +0 -11
- machineconfig/setup_windows/ssh/openssh-server.ps1 +0 -37
- machineconfig/utils/installer_utils/installer.py +0 -225
- machineconfig/utils/tst.py +0 -20
- machineconfig-6.82.dist-info/METADATA +0 -82
- machineconfig-6.82.dist-info/RECORD +0 -441
- machineconfig/jobs/installer/{custom_dev → checks}/__init__.py +0 -0
- machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
- machineconfig/{scripts/python/helpers_cloud → jobs/installer/python_scripts}/__init__.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/alacritty.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/bypass_paywall.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/cursor.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/espanso.py +0 -0
- machineconfig/jobs/installer/{custom → python_scripts}/gh.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/goes.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/lvim.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/redis.py +0 -0
- machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/android.sh +0 -0
- machineconfig/jobs/{installer/linux_scripts → scripts/bash_scripts}/lid.sh +0 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_drive +0 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nw_drive +0 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_smb +0 -0
- machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_cloud.sh +0 -0
- machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_nfs +0 -0
- machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/start_docker +0 -0
- machineconfig/{scripts → jobs/scripts/powershell_scripts}/Restore-ThunderbirdProfile.ps1 +0 -0
- machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/docker.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nfs.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nw.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_smb.ps1 +0 -0
- machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/power_options.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_cloud.cmd +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_smb.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/unlock_bitlocker.ps1 +0 -0
- machineconfig/scripts/python/{helpers_croshell → ai/utils}/__init__.py +0 -0
- machineconfig/scripts/python/ai/{solutions/_shared.py → utils/shared.py} +0 -0
- machineconfig/scripts/python/{helpers_devops → graph}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_devops/themes → helpers}/__init__.py +0 -0
- machineconfig/scripts/python/{env_manager → helpers/helper_env}/__init__.py +0 -0
- machineconfig/scripts/python/{env_manager → helpers/helper_env}/path_manager_backend.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_search.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_load_balancer.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents/templates}/template.ps1 +0 -0
- machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_cloud}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_helpers.py +1 -1
- /machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers5.py +0 -0
- /machineconfig/scripts/python/{helpers_sessions → helpers/helpers_croshell}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/pomodoro.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer_template.py +0 -0
- /machineconfig/scripts/python/{nw → helpers/helpers_devops}/__init__.py +0 -0
- /machineconfig/{setup_windows/wt_and_pwsh → scripts/python/helpers/helpers_devops/themes}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_pwsh_theme.ps1 +0 -0
- /machineconfig/scripts/python/{helpers_devops/themes/choose_starship_theme.ps1 → helpers/helpers_fire_command/__init__.py} +0 -0
- /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/cloud_manager.py +0 -0
- /machineconfig/scripts/python/{helpers_fire_command/fire_jobs_streamlit_helper.py → helpers/helpers_fire_command/f.py} +0 -0
- /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers/helpers_fire_command/fire_jobs_streamlit_helper.py} +0 -0
- /machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/search_bar.py +0 -0
- /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers/helpers_network/__init__.py} +0 -0
- /machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nw_drive.py +0 -0
- /machineconfig/scripts/python/{nw → helpers/helpers_network}/onetimeshare.py +0 -0
- /machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/sync.py +0 -0
- /machineconfig/{setup_windows/wt_and_pwsh → settings/wt}/set_wt_settings.py +0 -0
- {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/WHEEL +0 -0
- {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/top_level.txt +0 -0
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
from machineconfig.utils.installer_utils.installer_helper import install_deb_package, download_and_prepare
|
|
1
2
|
from machineconfig.utils.path_extended import PathExtended
|
|
2
|
-
from machineconfig.utils.
|
|
3
|
-
from machineconfig.utils.
|
|
4
|
-
from machineconfig.utils.installer_utils.installer_abc import check_tool_exists
|
|
3
|
+
from machineconfig.utils.source_of_truth import INSTALL_VERSION_ROOT
|
|
4
|
+
from machineconfig.utils.installer_utils.installer_locator_utils import find_move_delete_linux, find_move_delete_windows, check_tool_exists
|
|
5
5
|
from machineconfig.utils.schemas.installer.installer_types import InstallerData, get_os_name, get_normalized_arch
|
|
6
|
+
from machineconfig.utils.installer_utils.github_release_bulk import (
|
|
7
|
+
get_repo_name_from_url,
|
|
8
|
+
get_release_info,
|
|
9
|
+
)
|
|
6
10
|
|
|
7
11
|
import platform
|
|
8
12
|
import subprocess
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
PACAKGE_MANAGERS = ["bun", "npm", "pip", "uv", "winget", "powershell", "irm", "brew", "curl", "sudo"]
|
|
12
17
|
|
|
13
18
|
|
|
14
19
|
class Installer:
|
|
@@ -42,10 +47,8 @@ class Installer:
|
|
|
42
47
|
result_new = subprocess.run(f"{exe_name} --version", shell=True, capture_output=True, text=True)
|
|
43
48
|
new_version_cli = result_new.stdout.strip()
|
|
44
49
|
if old_version_cli == new_version_cli:
|
|
45
|
-
# print(f"ℹ️ Same version detected: {old_version_cli}")
|
|
46
50
|
return f"""📦️ 😑 {exe_name}, same version: {old_version_cli}"""
|
|
47
51
|
else:
|
|
48
|
-
# print(f"🚀 Update successful: {old_version_cli} ➡️ {new_version_cli}")
|
|
49
52
|
return f"""📦️ 🤩 {exe_name} updated from {old_version_cli} ➡️ TO ➡️ {new_version_cli}"""
|
|
50
53
|
except Exception as ex:
|
|
51
54
|
exe_name = self._get_exe_name()
|
|
@@ -62,25 +65,31 @@ class Installer:
|
|
|
62
65
|
if installer_arch_os is None:
|
|
63
66
|
raise ValueError(f"No installation pattern for {exe_name} on {os_name} {arch}")
|
|
64
67
|
version_to_be_installed: str = "unknown" # Initialize to ensure it's always bound
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
|
|
69
|
+
package_manager_installer = any(pm in installer_arch_os.split(" ") for pm in PACAKGE_MANAGERS)
|
|
70
|
+
script_installer = installer_arch_os.endswith((".sh", ".py", ".ps1"))
|
|
71
|
+
binary_download_link = installer_arch_os.startswith("https://") or installer_arch_os.startswith("http://")
|
|
72
|
+
|
|
73
|
+
if (repo_url == "CMD") or package_manager_installer or script_installer or binary_download_link:
|
|
74
|
+
if package_manager_installer:
|
|
75
|
+
from rich import print as rprint
|
|
76
|
+
from rich.panel import Panel
|
|
77
|
+
from rich.console import Group
|
|
67
78
|
package_manager = installer_arch_os.split(" ", maxsplit=1)[0]
|
|
68
79
|
print(f"📦 Using package manager: {installer_arch_os}")
|
|
69
80
|
desc = package_manager + " installation"
|
|
70
81
|
version_to_be_installed = package_manager + "Latest"
|
|
71
|
-
result = subprocess.run(installer_arch_os, shell=True, capture_output=
|
|
72
|
-
|
|
73
|
-
# result = run_shell_script(installer_arch_os)
|
|
74
|
-
success = result.returncode == 0 and result.stderr == "".encode()
|
|
82
|
+
result = subprocess.run(installer_arch_os, shell=True, capture_output=False, text=True)
|
|
83
|
+
success = result.returncode == 0 and result.stderr == ""
|
|
75
84
|
if not success:
|
|
76
|
-
|
|
85
|
+
sub_panels = []
|
|
77
86
|
if result.stdout:
|
|
78
|
-
|
|
87
|
+
sub_panels.append(Panel(result.stdout, title="STDOUT", style="blue"))
|
|
79
88
|
if result.stderr:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
89
|
+
sub_panels.append(Panel(result.stderr, title="STDERR", style="red"))
|
|
90
|
+
group_content = Group(f"❌ {desc} failed\nReturn code: {result.returncode}", *sub_panels)
|
|
91
|
+
rprint(Panel(group_content, title=desc, style="red"))
|
|
92
|
+
elif script_installer:
|
|
84
93
|
import machineconfig.jobs.installer as module
|
|
85
94
|
from pathlib import Path
|
|
86
95
|
search_root = Path(module.__file__).parent
|
|
@@ -105,14 +114,11 @@ class Installer:
|
|
|
105
114
|
import runpy
|
|
106
115
|
runpy.run_path(str(installer_path), run_name=None)["main"](self.installer_data, version=version)
|
|
107
116
|
version_to_be_installed = str(version)
|
|
108
|
-
elif
|
|
109
|
-
downloaded_object =
|
|
110
|
-
# object is either a zip containing a binary or a straight out binary.
|
|
111
|
-
if downloaded_object.suffix in [".zip", ".tar.gz"]:
|
|
112
|
-
downloaded_object = downloaded_object.decompress()
|
|
117
|
+
elif binary_download_link:
|
|
118
|
+
downloaded_object = download_and_prepare(installer_arch_os)
|
|
113
119
|
if downloaded_object.suffix in [".exe", ""]: # likely an executable
|
|
114
120
|
if platform.system() == "Windows":
|
|
115
|
-
exe = find_move_delete_windows(downloaded_file_path=downloaded_object,
|
|
121
|
+
exe = find_move_delete_windows(downloaded_file_path=downloaded_object, tool_name=exe_name, delete=True, rename_to=exe_name.replace(".exe", "") + ".exe")
|
|
116
122
|
elif platform.system() in ["Linux", "Darwin"]:
|
|
117
123
|
system_name = "Linux" if platform.system() == "Linux" else "macOS"
|
|
118
124
|
print(f"🐧 Installing on {system_name}...")
|
|
@@ -131,29 +137,20 @@ class Installer:
|
|
|
131
137
|
print(f"🔄 Renaming to correct name: {new_exe_name}")
|
|
132
138
|
exe.with_name(name=new_exe_name, inplace=True, overwrite=True)
|
|
133
139
|
version_to_be_installed = "downloaded_binary"
|
|
140
|
+
elif downloaded_object.suffix in [".deb"]:
|
|
141
|
+
install_deb_package(downloaded_object)
|
|
142
|
+
version_to_be_installed = "downloaded_deb"
|
|
143
|
+
else:
|
|
144
|
+
raise ValueError(f"Downloaded file is not an executable: {downloaded_object}")
|
|
134
145
|
else:
|
|
135
146
|
raise NotImplementedError(f"CMD installation method not implemented for: {installer_arch_os}")
|
|
136
147
|
else:
|
|
137
148
|
assert repo_url.startswith("https://github.com/"), f"repoURL must be a GitHub URL, got {repo_url}"
|
|
138
|
-
downloaded, version_to_be_installed = self.
|
|
139
|
-
if str(downloaded).endswith(".deb"):
|
|
140
|
-
print(f"📦 Installing .deb package: {downloaded}")
|
|
141
|
-
assert platform.system() == "Linux"
|
|
142
|
-
result = subprocess.run(f"sudo nala install -y {downloaded}", shell=True, capture_output=True, text=True)
|
|
143
|
-
success = result.returncode == 0 and result.stderr == ""
|
|
144
|
-
if not success:
|
|
145
|
-
desc = "Installing .deb"
|
|
146
|
-
print(f"❌ {desc} failed")
|
|
147
|
-
if result.stdout:
|
|
148
|
-
print(f"STDOUT: {result.stdout}")
|
|
149
|
-
if result.stderr:
|
|
150
|
-
print(f"STDERR: {result.stderr}")
|
|
151
|
-
print(f"Return code: {result.returncode}")
|
|
152
|
-
print("🗑️ Cleaning up .deb package...")
|
|
153
|
-
downloaded.delete(sure=True)
|
|
149
|
+
downloaded, version_to_be_installed = self.binary_download(version=version)
|
|
150
|
+
if str(downloaded).endswith(".deb"): install_deb_package(downloaded)
|
|
154
151
|
else:
|
|
155
152
|
if platform.system() == "Windows":
|
|
156
|
-
exe = find_move_delete_windows(downloaded_file_path=downloaded,
|
|
153
|
+
exe = find_move_delete_windows(downloaded_file_path=downloaded, tool_name=exe_name, delete=True, rename_to=exe_name.replace(".exe", "") + ".exe")
|
|
157
154
|
elif platform.system() in ["Linux", "Darwin"]:
|
|
158
155
|
system_name = "Linux" if platform.system() == "Linux" else "macOS"
|
|
159
156
|
print(f"🐧 Installing on {system_name}...")
|
|
@@ -173,13 +170,13 @@ class Installer:
|
|
|
173
170
|
exe.with_name(name=new_exe_name, inplace=True, overwrite=True)
|
|
174
171
|
INSTALL_VERSION_ROOT.joinpath(exe_name).parent.mkdir(parents=True, exist_ok=True)
|
|
175
172
|
INSTALL_VERSION_ROOT.joinpath(exe_name).write_text(version_to_be_installed or "unknown", encoding="utf-8")
|
|
176
|
-
def
|
|
173
|
+
def binary_download(self, version: Optional[str]) -> tuple[PathExtended, str]:
|
|
177
174
|
exe_name = self._get_exe_name()
|
|
178
175
|
repo_url = self.installer_data["repoURL"]
|
|
179
176
|
# app_name = self.installer_data["appName"]
|
|
180
177
|
download_link: Optional[str] = None
|
|
181
178
|
version_to_be_installed: Optional[str] = None
|
|
182
|
-
if "github" not in repo_url
|
|
179
|
+
if "github" not in repo_url:
|
|
183
180
|
# Direct download URL
|
|
184
181
|
download_link = repo_url
|
|
185
182
|
version_to_be_installed = "predefined_url"
|
|
@@ -193,63 +190,17 @@ class Installer:
|
|
|
193
190
|
print(f"🧭 Detected system={os_name} arch={arch}")
|
|
194
191
|
# Use existing get_github_release method to get download link and version
|
|
195
192
|
download_link, version_to_be_installed = self.get_github_release(repo_url, version)
|
|
193
|
+
# print(f"🌟 Retrieved download link from GitHub: {download_link}")
|
|
194
|
+
# print(f"📦 Version to be installed: {version_to_be_installed}")
|
|
196
195
|
if download_link is None:
|
|
197
196
|
raise ValueError(f"Could not retrieve download link for {exe_name} version {version or 'latest'}")
|
|
198
197
|
print(f"📦 Version to be installed: {version_to_be_installed}")
|
|
199
198
|
print(f"🔗 Download URL: {download_link}")
|
|
200
199
|
assert download_link is not None, "download_link must be set"
|
|
201
200
|
assert version_to_be_installed is not None, "version_to_be_installed must be set"
|
|
202
|
-
downloaded =
|
|
201
|
+
downloaded = download_and_prepare(download_link)
|
|
203
202
|
return downloaded, version_to_be_installed
|
|
204
203
|
|
|
205
|
-
# --------------------------- Arch / template helpers ---------------------------
|
|
206
|
-
|
|
207
|
-
@staticmethod
|
|
208
|
-
def _get_repo_name_from_url(repo_url: str) -> str:
|
|
209
|
-
"""Extract owner/repo from GitHub URL."""
|
|
210
|
-
try:
|
|
211
|
-
parsed = urlparse(repo_url)
|
|
212
|
-
path_parts = parsed.path.strip("/").split("/")
|
|
213
|
-
return f"{path_parts[0]}/{path_parts[1]}"
|
|
214
|
-
except (IndexError, AttributeError):
|
|
215
|
-
return ""
|
|
216
|
-
|
|
217
|
-
@staticmethod
|
|
218
|
-
def _fetch_github_release_data(repo_name: str, version: Optional[str] = None) -> Optional[dict[str, Any]]:
|
|
219
|
-
"""Fetch release data from GitHub API using requests."""
|
|
220
|
-
import requests
|
|
221
|
-
|
|
222
|
-
try:
|
|
223
|
-
if version and version.lower() != "latest":
|
|
224
|
-
# Fetch specific version
|
|
225
|
-
url = f"https://api.github.com/repos/{repo_name}/releases/tags/{version}"
|
|
226
|
-
else:
|
|
227
|
-
# Fetch latest release
|
|
228
|
-
url = f"https://api.github.com/repos/{repo_name}/releases/latest"
|
|
229
|
-
|
|
230
|
-
response = requests.get(url, timeout=30)
|
|
231
|
-
|
|
232
|
-
if response.status_code != 200:
|
|
233
|
-
print(f"❌ Failed to fetch data for {repo_name}: HTTP {response.status_code}")
|
|
234
|
-
return None
|
|
235
|
-
|
|
236
|
-
response_data = response.json()
|
|
237
|
-
|
|
238
|
-
# Check if API returned an error
|
|
239
|
-
if "message" in response_data:
|
|
240
|
-
if "API rate limit exceeded" in response_data.get("message", ""):
|
|
241
|
-
print(f"🚫 Rate limit exceeded for {repo_name}")
|
|
242
|
-
return None
|
|
243
|
-
elif "Not Found" in response_data.get("message", ""):
|
|
244
|
-
print(f"🔍 No releases found for {repo_name}")
|
|
245
|
-
return None
|
|
246
|
-
|
|
247
|
-
return response_data
|
|
248
|
-
|
|
249
|
-
except (requests.RequestException, requests.Timeout, json.JSONDecodeError) as e:
|
|
250
|
-
print(f"❌ Error fetching {repo_name}: {e}")
|
|
251
|
-
return None
|
|
252
|
-
|
|
253
204
|
def get_github_release(self, repo_url: str, version: Optional[str]) -> tuple[Optional[str], Optional[str]]:
|
|
254
205
|
"""
|
|
255
206
|
Get download link and version from GitHub release based on fileNamePattern.
|
|
@@ -260,20 +211,20 @@ class Installer:
|
|
|
260
211
|
filename_pattern = self.installer_data["fileNamePattern"][arch][os_name]
|
|
261
212
|
if filename_pattern is None:
|
|
262
213
|
raise ValueError(f"No fileNamePattern for {self._get_exe_name()} on {os_name} {arch}")
|
|
263
|
-
|
|
264
|
-
if not
|
|
214
|
+
repo_info = get_repo_name_from_url(repo_url)
|
|
215
|
+
if not repo_info:
|
|
265
216
|
print(f"❌ Invalid repository URL: {repo_url}")
|
|
266
217
|
return None, None
|
|
267
|
-
|
|
268
|
-
|
|
218
|
+
username, repository = repo_info
|
|
219
|
+
release_info = get_release_info(username, repository, version)
|
|
220
|
+
if not release_info:
|
|
269
221
|
return None, None
|
|
270
|
-
|
|
271
|
-
actual_version = release_data.get("tag_name", "unknown")
|
|
222
|
+
actual_version = release_info.get("tag_name", "unknown") or "unknown"
|
|
272
223
|
filename = filename_pattern.format(version=actual_version)
|
|
273
224
|
|
|
274
225
|
available_filenames: list[str] = []
|
|
275
|
-
for asset in
|
|
276
|
-
an_dl = asset
|
|
226
|
+
for asset in release_info["assets"]:
|
|
227
|
+
an_dl = asset["browser_download_url"]
|
|
277
228
|
available_filenames.append(an_dl.split("/")[-1])
|
|
278
229
|
if filename not in available_filenames:
|
|
279
230
|
candidates = [
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
|
|
2
|
+
"""Devops Devapps Install
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from machineconfig.utils.installer_utils.installer_helper import get_group_name_to_repr
|
|
6
|
+
import typer
|
|
7
|
+
from typing import Annotated, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main_installer_cli(
|
|
11
|
+
which: Annotated[Optional[str], typer.Argument(..., help="Comma-separated list of program/groups names to install (if --group flag is set).")] = None,
|
|
12
|
+
group: Annotated[bool, typer.Option(..., "--group", "-g", help="Treat 'which' as a group name. A group is bundle of apps.")] = False,
|
|
13
|
+
interactive: Annotated[bool, typer.Option(..., "--interactive", "-i", help="Interactive selection of programs to install.")] = False,
|
|
14
|
+
) -> None:
|
|
15
|
+
if interactive:
|
|
16
|
+
return install_interactively()
|
|
17
|
+
if which is not None:
|
|
18
|
+
if group:
|
|
19
|
+
for a_group in [x.strip() for x in which.split(",") if x.strip() != ""]:
|
|
20
|
+
return install_group(package_group=a_group)
|
|
21
|
+
else:
|
|
22
|
+
return install_clis(clis_names=[x.strip() for x in which.split(",") if x.strip() != ""])
|
|
23
|
+
else:
|
|
24
|
+
if group:
|
|
25
|
+
from rich.console import Console
|
|
26
|
+
from rich.table import Table
|
|
27
|
+
console = Console()
|
|
28
|
+
|
|
29
|
+
typer.echo("❌ You must provide a group name when using the --group/-g option.")
|
|
30
|
+
from machineconfig.utils.installer_utils.installer_helper import get_group_name_to_repr
|
|
31
|
+
res = get_group_name_to_repr()
|
|
32
|
+
console.print("[bold blue]Here are the available groups:[/bold blue]")
|
|
33
|
+
table = Table(show_header=True, header_style="bold magenta")
|
|
34
|
+
table.add_column("Group", style="cyan", no_wrap=True)
|
|
35
|
+
table.add_column("AppsBundled", style="green", overflow="fold")
|
|
36
|
+
for display, group_name in res.items():
|
|
37
|
+
# Parse display
|
|
38
|
+
if " -- " in display:
|
|
39
|
+
group_part, items_part = display.split(" -- ", 1)
|
|
40
|
+
group_name_parsed = group_part.replace("📦 ", "").strip()
|
|
41
|
+
items_str = items_part.strip()
|
|
42
|
+
else:
|
|
43
|
+
group_name_parsed = display
|
|
44
|
+
items_str = group_name
|
|
45
|
+
table.add_row(group_name_parsed, items_str)
|
|
46
|
+
console.print(table)
|
|
47
|
+
raise typer.Exit(1)
|
|
48
|
+
typer.echo("❌ You must provide either a program name/group name, or use --interactive/-ia option.")
|
|
49
|
+
import click
|
|
50
|
+
ctx = click.get_current_context()
|
|
51
|
+
typer.echo(ctx.get_help())
|
|
52
|
+
raise typer.Exit(1)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def install_interactively():
|
|
59
|
+
from machineconfig.utils.options import choose_from_options
|
|
60
|
+
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
61
|
+
from machineconfig.utils.installer_utils.installer_runner import get_installers
|
|
62
|
+
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
63
|
+
from rich.console import Console
|
|
64
|
+
from rich.panel import Panel
|
|
65
|
+
# from rich.table import Table
|
|
66
|
+
installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=None)
|
|
67
|
+
installer_options = [Installer(installer_data=x).get_description() for x in installers]
|
|
68
|
+
category_display_to_name = get_group_name_to_repr()
|
|
69
|
+
options = list(category_display_to_name.keys()) + installer_options
|
|
70
|
+
program_names = choose_from_options(multi=True, msg="Categories are prefixed with 📦", options=options, header="🚀 CHOOSE DEV APP OR CATEGORY", tv=True)
|
|
71
|
+
installation_messages: list[str] = []
|
|
72
|
+
for _an_idx, a_program_name in enumerate(program_names):
|
|
73
|
+
if a_program_name.startswith("📦 "):
|
|
74
|
+
category_name = category_display_to_name.get(a_program_name)
|
|
75
|
+
if category_name:
|
|
76
|
+
install_group(package_group=category_name)
|
|
77
|
+
else:
|
|
78
|
+
installer_idx = installer_options.index(a_program_name)
|
|
79
|
+
an_installer_data = installers[installer_idx]
|
|
80
|
+
status_message = Installer(an_installer_data).install_robust(version=None) # finish the task - this returns a status message, not a command
|
|
81
|
+
installation_messages.append(status_message)
|
|
82
|
+
if installation_messages:
|
|
83
|
+
console = Console()
|
|
84
|
+
|
|
85
|
+
panel = Panel("\n".join([f"[blue]• {message}[/blue]" for message in installation_messages]), title="[bold green]📊 Installation Summary[/bold green]", border_style="green", padding=(1, 2))
|
|
86
|
+
console.print(panel)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def install_group(package_group: str):
|
|
90
|
+
from machineconfig.utils.installer_utils.installer_runner import get_installers, install_bulk
|
|
91
|
+
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
92
|
+
from rich.console import Console
|
|
93
|
+
from rich.panel import Panel
|
|
94
|
+
# from rich.table import Table
|
|
95
|
+
from machineconfig.jobs.installer.package_groups import PACKAGE_GROUP2NAMES
|
|
96
|
+
if package_group in PACKAGE_GROUP2NAMES:
|
|
97
|
+
panel = Panel(f"[bold yellow]Installing programs from category: [green]{package_group}[/green][/bold yellow]", title="[bold blue]📦 Category Installation[/bold blue]", border_style="blue", padding=(1, 2))
|
|
98
|
+
console = Console()
|
|
99
|
+
console.print(panel)
|
|
100
|
+
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=[package_group])
|
|
101
|
+
install_bulk(installers_data=installers_)
|
|
102
|
+
return
|
|
103
|
+
console = Console()
|
|
104
|
+
console.print(f"❌ ERROR: Unknown package group: {package_group}. Available groups are: {list(PACKAGE_GROUP2NAMES.keys())}")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def install_clis(clis_names: list[str]):
|
|
108
|
+
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
109
|
+
from machineconfig.utils.installer_utils.installer_runner import get_installers
|
|
110
|
+
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
111
|
+
from rich.console import Console
|
|
112
|
+
all_installers_data = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=None)
|
|
113
|
+
total_messages: list[str] = []
|
|
114
|
+
for a_cli_name in clis_names:
|
|
115
|
+
if "github.com" in a_cli_name.lower():
|
|
116
|
+
from machineconfig.utils.installer_utils.install_from_url import install_from_github_url
|
|
117
|
+
install_from_github_url(github_url=a_cli_name)
|
|
118
|
+
continue
|
|
119
|
+
elif a_cli_name.startswith("https://") or a_cli_name.startswith("http://"):
|
|
120
|
+
print(f"⏳ Installing from binary URL: {a_cli_name} ...")
|
|
121
|
+
from machineconfig.utils.installer_utils.install_from_url import install_from_binary_url
|
|
122
|
+
install_from_binary_url(binary_url=a_cli_name)
|
|
123
|
+
continue
|
|
124
|
+
selected_installer = None
|
|
125
|
+
for installer in all_installers_data:
|
|
126
|
+
app_name = installer["appName"]
|
|
127
|
+
if app_name.lower() == a_cli_name.lower():
|
|
128
|
+
selected_installer = installer
|
|
129
|
+
break
|
|
130
|
+
if selected_installer is None:
|
|
131
|
+
from machineconfig.utils.installer_utils.installer_helper import handle_installer_not_found
|
|
132
|
+
handle_installer_not_found(a_cli_name, all_installers_data)
|
|
133
|
+
return None
|
|
134
|
+
message = Installer(selected_installer).install_robust(version=None) # finish the task
|
|
135
|
+
total_messages.append(message)
|
|
136
|
+
if total_messages:
|
|
137
|
+
console = Console()
|
|
138
|
+
console.print("\n[bold green]📊 Installation Results:[/bold green]")
|
|
139
|
+
for a_message in total_messages:
|
|
140
|
+
console.print(f"[blue]• {a_message}[/blue]")
|
|
141
|
+
return None
|
|
142
|
+
def install_if_missing(which: str) -> bool:
|
|
143
|
+
from machineconfig.utils.installer_utils.installer_locator_utils import check_tool_exists
|
|
144
|
+
exists = check_tool_exists(which)
|
|
145
|
+
if exists:
|
|
146
|
+
print(f"✅ {which} is already installed.")
|
|
147
|
+
return True
|
|
148
|
+
print(f"⏳ {which} not found. Installing...")
|
|
149
|
+
from machineconfig.utils.installer_utils.installer_cli import main_installer_cli
|
|
150
|
+
try:
|
|
151
|
+
main_installer_cli(which=which, interactive=False)
|
|
152
|
+
return True
|
|
153
|
+
except Exception as e:
|
|
154
|
+
print(f"❌ Error installing {which}: {e}")
|
|
155
|
+
return False
|
|
156
|
+
|
|
157
|
+
if __name__ == "__main__":
|
|
158
|
+
from machineconfig.utils.schemas.installer.installer_types import InstallerData
|
|
159
|
+
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
160
|
+
_ = InstallerData, Installer
|
|
161
|
+
pass
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
from machineconfig.jobs.installer.package_groups import PACKAGE_GROUP2NAMES
|
|
2
|
+
from machineconfig.utils.schemas.installer.installer_types import InstallerData
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from machineconfig.utils.path_extended import DECOMPRESS_SUPPORTED_FORMATS, PathExtended
|
|
5
|
+
from machineconfig.utils.source_of_truth import INSTALL_TMP_DIR
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_group_name_to_repr() -> dict[str, str]:
|
|
9
|
+
# Build category options and maintain a mapping from display text to actual category name
|
|
10
|
+
category_display_to_name: dict[str, str] = {}
|
|
11
|
+
for group_name, group_values in PACKAGE_GROUP2NAMES.items():
|
|
12
|
+
display = f"📦 {group_name:<20}" + " -- " + f"{'|'.join(group_values):<60}"
|
|
13
|
+
category_display_to_name[display] = group_name
|
|
14
|
+
return category_display_to_name
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def handle_installer_not_found(search_term: str, app_apps: list[InstallerData]) -> None: # type: ignore
|
|
18
|
+
"""Handle installer not found with friendly suggestions using fuzzy matching."""
|
|
19
|
+
from difflib import get_close_matches
|
|
20
|
+
from rich.console import Console
|
|
21
|
+
from rich.panel import Panel
|
|
22
|
+
from rich.table import Table
|
|
23
|
+
all_names = sorted([inst["appName"] for inst in app_apps])
|
|
24
|
+
name_to_doc = {inst["appName"]: inst["doc"] for inst in app_apps}
|
|
25
|
+
all_descriptions = {f"{inst['appName']}: {inst['doc']}": inst["appName"] for inst in app_apps}
|
|
26
|
+
|
|
27
|
+
close_name_matches = get_close_matches(search_term, all_names, n=5, cutoff=0.4)
|
|
28
|
+
close_description_matches = get_close_matches(search_term, list(all_descriptions.keys()), n=5, cutoff=0.4)
|
|
29
|
+
|
|
30
|
+
search_lower = search_term.lower()
|
|
31
|
+
substring_matches = [
|
|
32
|
+
inst["appName"]
|
|
33
|
+
for inst in app_apps
|
|
34
|
+
if search_lower in inst["appName"].lower() or search_lower in inst["doc"].lower()
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
ordered_matches: list[str] = list(
|
|
38
|
+
dict.fromkeys(
|
|
39
|
+
close_name_matches
|
|
40
|
+
+ [all_descriptions[desc] for desc in close_description_matches]
|
|
41
|
+
+ substring_matches
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
top_matches = ordered_matches[:10]
|
|
45
|
+
console = Console()
|
|
46
|
+
|
|
47
|
+
console.print(f"\n❌ '[red]{search_term}[/red]' was not found.", style="bold")
|
|
48
|
+
if top_matches:
|
|
49
|
+
console.print("🤔 Did you mean one of these?", style="yellow")
|
|
50
|
+
table = Table(show_header=True, header_style="bold", box=None, pad_edge=False)
|
|
51
|
+
table.add_column("#", justify="right", width=3)
|
|
52
|
+
table.add_column("Installer", style="green")
|
|
53
|
+
table.add_column("Description", style="dim", overflow="fold")
|
|
54
|
+
for i, match in enumerate(top_matches, 1):
|
|
55
|
+
table.add_row(f"[cyan]{i}[/cyan]", match, name_to_doc.get(match, ""))
|
|
56
|
+
console.print(table)
|
|
57
|
+
else:
|
|
58
|
+
console.print("📋 Here are some available options:", style="blue")
|
|
59
|
+
# Show first 10 installers as examples
|
|
60
|
+
if len(all_names) > 10:
|
|
61
|
+
sample_names = all_names[:10]
|
|
62
|
+
else:
|
|
63
|
+
sample_names = all_names
|
|
64
|
+
table = Table(show_header=True, header_style="bold", box=None, pad_edge=False)
|
|
65
|
+
table.add_column("#", justify="right", width=3)
|
|
66
|
+
table.add_column("Installer", style="green")
|
|
67
|
+
table.add_column("Description", style="dim", overflow="fold")
|
|
68
|
+
for i, name in enumerate(sample_names, 1):
|
|
69
|
+
table.add_row(f"[cyan]{i}[/cyan]", name, name_to_doc.get(name, ""))
|
|
70
|
+
console.print(table)
|
|
71
|
+
if len(all_names) > 10:
|
|
72
|
+
console.print(f" [dim]... and {len(all_names) - 10} more[/dim]")
|
|
73
|
+
|
|
74
|
+
panel = Panel(f"[bold blue]💡 Use 'ia' to interactively browse all available installers.[/bold blue]\n[bold blue]💡 Use one of the categories: {list(PACKAGE_GROUP2NAMES.keys())}[/bold blue]", title="[yellow]Helpful Tips[/yellow]", border_style="yellow")
|
|
75
|
+
console.print(panel)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def install_deb_package(downloaded: Path) -> None:
|
|
79
|
+
from rich import print as rprint
|
|
80
|
+
from rich.panel import Panel
|
|
81
|
+
print(f"📦 Installing .deb package: {downloaded}")
|
|
82
|
+
import platform
|
|
83
|
+
import subprocess
|
|
84
|
+
assert platform.system() == "Linux"
|
|
85
|
+
result = subprocess.run(f"sudo nala install -y {downloaded}", shell=True, capture_output=True, text=True)
|
|
86
|
+
success = result.returncode == 0 and result.stderr == ""
|
|
87
|
+
if not success:
|
|
88
|
+
from rich.console import Group
|
|
89
|
+
desc = "Installing .deb"
|
|
90
|
+
sub_panels = []
|
|
91
|
+
if result.stdout:
|
|
92
|
+
sub_panels.append(Panel(result.stdout, title="STDOUT", style="blue"))
|
|
93
|
+
if result.stderr:
|
|
94
|
+
sub_panels.append(Panel(result.stderr, title="STDERR", style="red"))
|
|
95
|
+
group_content = Group(f"❌ {desc} failed\nReturn code: {result.returncode}", *sub_panels)
|
|
96
|
+
rprint(Panel(group_content, title=desc, style="red"))
|
|
97
|
+
print("🗑️ Cleaning up .deb package...")
|
|
98
|
+
if downloaded.is_file():
|
|
99
|
+
downloaded.unlink(missing_ok=True)
|
|
100
|
+
elif downloaded.is_dir():
|
|
101
|
+
import shutil
|
|
102
|
+
shutil.rmtree(downloaded, ignore_errors=True)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def download_and_prepare(download_url: str) -> PathExtended:
|
|
106
|
+
# archive_path = PathExtended(download_url).download(folder=INSTALL_TMP_DIR)
|
|
107
|
+
from machineconfig.scripts.python.helpers.helpers_utils.download import download
|
|
108
|
+
downloaded_object = download(download_url, output_dir=str(INSTALL_TMP_DIR))
|
|
109
|
+
if downloaded_object is None:
|
|
110
|
+
raise ValueError(f"Failed to download from URL: {download_url}")
|
|
111
|
+
archive_path = PathExtended(downloaded_object)
|
|
112
|
+
extracted_path = archive_path
|
|
113
|
+
if extracted_path.is_file() and any(ext in archive_path.suffixes for ext in DECOMPRESS_SUPPORTED_FORMATS):
|
|
114
|
+
extracted_path = archive_path.decompress()
|
|
115
|
+
# print(f"Decompressed {archive_path} to {extracted_path}")
|
|
116
|
+
archive_path.delete(sure=True)
|
|
117
|
+
if extracted_path.is_dir():
|
|
118
|
+
nested_items = list(extracted_path.glob("*"))
|
|
119
|
+
if len(nested_items) == 1:
|
|
120
|
+
nested_path = PathExtended(nested_items[0])
|
|
121
|
+
if nested_path.is_file() and any(ex in nested_path.suffixes for ex in DECOMPRESS_SUPPORTED_FORMATS):
|
|
122
|
+
extracted_path = nested_path.decompress()
|
|
123
|
+
nested_path.delete(sure=True)
|
|
124
|
+
elif extracted_path.is_dir() and len([p for p in extracted_path.rglob("*") if not p.name.startswith(".")]) == 1:
|
|
125
|
+
only_file_in = next(extracted_path.glob("*"))
|
|
126
|
+
if only_file_in.is_file() and any(ext in str(only_file_in) for ext in DECOMPRESS_SUPPORTED_FORMATS): # further decompress
|
|
127
|
+
extracted_path = only_file_in.decompress()
|
|
128
|
+
only_file_in.delete(sure=True)
|
|
129
|
+
return extracted_path
|