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.
Files changed (461) hide show
  1. machineconfig/cluster/remote/cloud_manager.py +1 -1
  2. machineconfig/cluster/remote/run_cluster.py +1 -1
  3. machineconfig/cluster/remote/run_remote.py +1 -1
  4. machineconfig/cluster/sessions_managers/utils/maker.py +29 -15
  5. machineconfig/cluster/sessions_managers/wt_local.py +17 -222
  6. machineconfig/cluster/sessions_managers/wt_local_manager.py +56 -194
  7. machineconfig/cluster/sessions_managers/wt_remote_manager.py +42 -198
  8. machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
  9. machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
  10. machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
  11. machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
  12. machineconfig/cluster/sessions_managers/zellij_local.py +1 -1
  13. machineconfig/cluster/sessions_managers/zellij_local_manager.py +4 -2
  14. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +3 -2
  15. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +2 -2
  16. machineconfig/jobs/installer/checks/check_installations.py +133 -0
  17. machineconfig/jobs/installer/checks/install_utils.py +132 -0
  18. machineconfig/jobs/installer/checks/report_utils.py +39 -0
  19. machineconfig/jobs/installer/checks/vt_utils.py +89 -0
  20. machineconfig/jobs/installer/installer_data.json +1500 -310
  21. machineconfig/jobs/installer/linux_scripts/docker.sh +6 -9
  22. machineconfig/jobs/installer/linux_scripts/q.sh +10 -7
  23. machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
  24. machineconfig/jobs/installer/package_groups.py +62 -91
  25. machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
  26. machineconfig/jobs/installer/{custom → python_scripts}/boxes.py +2 -3
  27. machineconfig/jobs/installer/{custom_dev → python_scripts}/brave.py +5 -3
  28. machineconfig/jobs/installer/python_scripts/cloudflare_warp_cli.py +23 -0
  29. machineconfig/jobs/installer/{custom_dev → python_scripts}/code.py +14 -9
  30. machineconfig/jobs/installer/{custom_dev → python_scripts}/dubdb_adbc.py +1 -1
  31. machineconfig/jobs/installer/python_scripts/hx.py +214 -0
  32. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerdfont.py +2 -2
  33. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerfont_windows_helper.py +32 -26
  34. machineconfig/jobs/installer/python_scripts/sysabc.py +145 -0
  35. machineconfig/jobs/installer/{custom_dev → python_scripts}/wezterm.py +2 -19
  36. machineconfig/jobs/installer/{custom_dev → python_scripts}/winget.py +10 -14
  37. machineconfig/jobs/installer/python_scripts/yazi.py +139 -0
  38. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nfs +0 -1
  39. machineconfig/jobs/scripts/powershell_scripts/cmatrix.ps1 +52 -0
  40. machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +13 -0
  41. machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +4 -0
  42. machineconfig/jobs/scripts_dynamic/a.py +428 -0
  43. machineconfig/logger.py +1 -2
  44. machineconfig/profile/create_helper.py +56 -18
  45. machineconfig/profile/create_links.py +79 -21
  46. machineconfig/profile/create_links_export.py +87 -36
  47. machineconfig/profile/create_shell_profile.py +92 -127
  48. machineconfig/profile/mapper_data.toml +45 -0
  49. machineconfig/profile/mapper_dotfiles.toml +249 -0
  50. machineconfig/scripts/__init__.py +0 -4
  51. machineconfig/scripts/linux/wrap_mcfg +46 -0
  52. machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
  53. machineconfig/scripts/python/agents.py +85 -165
  54. machineconfig/scripts/python/ai/initai.py +4 -2
  55. machineconfig/scripts/python/ai/scripts/__init__.py +1 -0
  56. machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
  57. machineconfig/scripts/python/ai/{command_runner → scripts}/command_runner.sh +1 -1
  58. machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +2 -0
  59. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +8 -6
  60. machineconfig/scripts/python/ai/solutions/claude/claude.py +1 -1
  61. machineconfig/scripts/python/ai/solutions/cline/cline.py +1 -1
  62. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
  63. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
  64. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
  65. machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +6 -6
  66. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +33 -0
  67. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
  68. machineconfig/scripts/python/ai/solutions/crush/crush.py +1 -1
  69. machineconfig/scripts/python/ai/solutions/cursor/cursors.py +1 -1
  70. machineconfig/scripts/python/ai/solutions/gemini/gemini.py +1 -1
  71. machineconfig/scripts/python/ai/solutions/gemini/settings.json +3 -0
  72. machineconfig/scripts/python/ai/{generate_files.py → utils/generate_files.py} +2 -2
  73. machineconfig/scripts/python/ai/{solutions → utils}/generic.py +2 -15
  74. machineconfig/scripts/python/ai/{vscode_tasks.py → utils/vscode_tasks.py} +13 -5
  75. machineconfig/scripts/python/cloud.py +58 -11
  76. machineconfig/scripts/python/croshell.py +10 -162
  77. machineconfig/scripts/python/devops.py +73 -36
  78. machineconfig/scripts/python/devops_navigator.py +16 -6
  79. machineconfig/scripts/python/fire_jobs.py +8 -222
  80. machineconfig/scripts/python/ftpx.py +7 -200
  81. machineconfig/scripts/python/graph/cli_graph.json +8743 -0
  82. machineconfig/scripts/python/{env_manager → helper_env}/path_manager_tui.py +2 -2
  83. machineconfig/scripts/python/helpers/helper_env/env_manager_tui.py +204 -0
  84. machineconfig/scripts/python/helpers/helper_env/path_manager_tui.py +228 -0
  85. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_crush.json +1 -1
  86. machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
  87. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_cursor_agents.py +3 -4
  88. machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
  89. machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
  90. machineconfig/scripts/python/helpers/helpers_agents/agents_impl.py +168 -0
  91. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_launch.py +38 -16
  92. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_helper_types.py +11 -14
  93. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aichat/config.yaml +5 -0
  94. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aider/.aider.conf.yml +2 -0
  95. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/copilot/config.yml +1 -0
  96. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/crush/crush.json +10 -0
  97. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/gemini/settings.json +12 -0
  98. machineconfig/scripts/python/helpers/helpers_agents/privacy/privacy.py +109 -0
  99. machineconfig/scripts/python/helpers/helpers_agents/templates/prompt.txt +10 -0
  100. machineconfig/scripts/python/helpers/helpers_agents/templates/template.sh +34 -0
  101. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_copy.py +32 -25
  102. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_mount.py +29 -22
  103. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_sync.py +9 -8
  104. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers2.py +1 -1
  105. machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/crosh.py +3 -3
  106. machineconfig/scripts/python/helpers/helpers_croshell/croshell_impl.py +225 -0
  107. machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/scheduler.py +4 -4
  108. machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/start_slidev.py +12 -12
  109. machineconfig/scripts/python/helpers/helpers_devops/backup_config.py +149 -0
  110. machineconfig/scripts/python/helpers/helpers_devops/cli_backup_retrieve.py +262 -0
  111. machineconfig/scripts/python/helpers/helpers_devops/cli_config.py +98 -0
  112. machineconfig/scripts/python/helpers/helpers_devops/cli_config_dotfile.py +274 -0
  113. machineconfig/scripts/python/helpers/helpers_devops/cli_data.py +67 -0
  114. machineconfig/scripts/python/helpers/helpers_devops/cli_nw.py +201 -0
  115. machineconfig/scripts/python/helpers/helpers_devops/cli_repos.py +274 -0
  116. machineconfig/scripts/python/helpers/helpers_devops/cli_self.py +197 -0
  117. machineconfig/scripts/python/helpers/helpers_devops/cli_share_file.py +151 -0
  118. machineconfig/scripts/python/helpers/helpers_devops/cli_share_server.py +125 -0
  119. machineconfig/scripts/python/{helpers_devops/cli_terminal.py → helpers/helpers_devops/cli_share_terminal.py} +26 -22
  120. machineconfig/scripts/python/helpers/helpers_devops/cli_ssh.py +167 -0
  121. machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_status.py +17 -23
  122. machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_update_repos.py +1 -1
  123. machineconfig/scripts/python/{interactive.py → helpers/helpers_devops/interactive.py} +78 -71
  124. machineconfig/scripts/python/helpers/helpers_devops/run_script.py +197 -0
  125. machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.ps1 +41 -0
  126. machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.sh +48 -0
  127. machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_wezterm_theme.py +4 -4
  128. machineconfig/scripts/python/{helpers_fire/helpers4.py → helpers/helpers_fire_command/file_wrangler.py} +57 -20
  129. machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_args_helper.py +1 -0
  130. machineconfig/scripts/python/helpers/helpers_fire_command/fire_jobs_impl.py +233 -0
  131. machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_route_helper.py +26 -16
  132. machineconfig/scripts/python/helpers/helpers_msearch/__init__.py +5 -0
  133. machineconfig/scripts/python/helpers/helpers_msearch/msearch_impl.py +248 -0
  134. machineconfig/scripts/{linux → python/helpers/helpers_msearch/scripts_linux}/fzfg +6 -5
  135. machineconfig/scripts/python/helpers/helpers_msearch/scripts_linux/search_with_context.sh +48 -0
  136. machineconfig/scripts/python/helpers/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
  137. machineconfig/scripts/python/helpers/helpers_navigator/__init__.py +20 -0
  138. machineconfig/scripts/python/helpers/helpers_navigator/cli_graph_loader.py +234 -0
  139. machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/command_builder.py +61 -13
  140. machineconfig/scripts/python/helpers/helpers_navigator/command_detail.py +153 -0
  141. machineconfig/scripts/python/helpers/helpers_navigator/command_tree.py +45 -0
  142. machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/data_models.py +18 -11
  143. machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/main_app.py +5 -5
  144. machineconfig/scripts/python/helpers/helpers_network/address.py +174 -0
  145. machineconfig/scripts/python/helpers/helpers_network/address_switch.py +78 -0
  146. machineconfig/scripts/python/helpers/helpers_network/ftpx_impl.py +276 -0
  147. machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nfs.py +2 -2
  148. machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_ssh.py +3 -3
  149. machineconfig/scripts/python/helpers/helpers_network/ssh_add_identity.py +73 -0
  150. machineconfig/scripts/python/helpers/helpers_network/ssh_add_ssh_key.py +175 -0
  151. machineconfig/scripts/python/helpers/helpers_network/ssh_debug_linux.py +319 -0
  152. machineconfig/scripts/python/helpers/helpers_network/ssh_debug_windows.py +275 -0
  153. machineconfig/scripts/python/{nw → helpers/helpers_network}/wifi_conn.py +1 -53
  154. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action.py +3 -3
  155. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action_helper.py +3 -3
  156. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/clone.py +0 -1
  157. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/cloud_repo_sync.py +159 -48
  158. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/grource.py +4 -3
  159. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/record.py +33 -12
  160. machineconfig/scripts/python/helpers/helpers_repos/repo_analyzer_1.py +160 -0
  161. machineconfig/scripts/python/{helpers_repos/count_lines.py → helpers/helpers_repos/repo_analyzer_2.py} +156 -191
  162. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/update.py +0 -6
  163. machineconfig/scripts/python/helpers/helpers_search/ast_search.py +74 -0
  164. machineconfig/scripts/python/helpers/helpers_search/qr_code.py +166 -0
  165. machineconfig/scripts/python/helpers/helpers_search/repo_rag.py +325 -0
  166. machineconfig/scripts/python/helpers/helpers_search/script_help.py +81 -0
  167. machineconfig/scripts/python/helpers/helpers_search/symantic_search.py +25 -0
  168. machineconfig/scripts/python/helpers/helpers_sessions/__init__.py +0 -0
  169. machineconfig/scripts/python/helpers/helpers_sessions/sessions_impl.py +186 -0
  170. machineconfig/scripts/python/{helpers_sessions → helpers/helpers_sessions}/sessions_multiprocess.py +20 -14
  171. machineconfig/scripts/python/helpers/helpers_terminal/__init__.py +0 -0
  172. machineconfig/scripts/python/helpers/helpers_terminal/terminal_impl.py +96 -0
  173. machineconfig/scripts/python/helpers/helpers_utils/download.py +150 -0
  174. machineconfig/scripts/python/helpers/helpers_utils/pdf.py +96 -0
  175. machineconfig/scripts/python/helpers/helpers_utils/python.py +210 -0
  176. machineconfig/scripts/python/helpers/helpers_utils/specs.py +246 -0
  177. machineconfig/scripts/python/mcfg_entry.py +143 -0
  178. machineconfig/scripts/python/msearch.py +26 -0
  179. machineconfig/scripts/python/sessions.py +69 -135
  180. machineconfig/scripts/python/terminal.py +58 -0
  181. machineconfig/scripts/python/utils.py +115 -38
  182. machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
  183. machineconfig/settings/atuin/config.toml +294 -0
  184. machineconfig/settings/atuin/themes/catppuccin-mocha-mauve.toml +12 -0
  185. machineconfig/settings/broot/conf.toml +1 -1
  186. machineconfig/settings/helix/config.toml +16 -0
  187. machineconfig/settings/helix/languages.toml +13 -4
  188. machineconfig/settings/helix/yazi-picker.sh +12 -0
  189. machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
  190. machineconfig/settings/lf/linux/exe/previewer.sh +3 -2
  191. machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
  192. machineconfig/settings/lf/windows/lfrc +14 -16
  193. machineconfig/settings/linters/.ruff.toml +2 -1
  194. machineconfig/settings/marimo/marimo.toml +1 -1
  195. machineconfig/settings/marimo/snippets/globalize.py +34 -0
  196. machineconfig/settings/mprocs/windows/mprocs.yaml +2 -2
  197. machineconfig/settings/shells/bash/init.sh +47 -12
  198. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
  199. machineconfig/settings/shells/nushell/config.nu +25 -33
  200. machineconfig/settings/shells/nushell/env.nu +21 -8
  201. machineconfig/settings/shells/nushell/init.nu +138 -0
  202. machineconfig/settings/shells/pwsh/init.ps1 +111 -17
  203. machineconfig/settings/shells/pwsh/search_pwsh_history.ps1 +99 -0
  204. machineconfig/settings/shells/starship/starship.toml +16 -0
  205. machineconfig/settings/shells/wezterm/wezterm.lua +6 -1
  206. machineconfig/settings/shells/wt/settings.json +27 -18
  207. machineconfig/settings/shells/zsh/init.sh +42 -23
  208. machineconfig/settings/television/cable_unix/alias.toml +8 -0
  209. machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
  210. machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
  211. machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
  212. machineconfig/settings/television/cable_unix/channels.toml +19 -0
  213. machineconfig/settings/television/cable_unix/dirs.toml +13 -0
  214. machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
  215. machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
  216. machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
  217. machineconfig/settings/television/cable_unix/env.toml +17 -0
  218. machineconfig/settings/television/cable_unix/files.toml +11 -0
  219. machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
  220. machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
  221. machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
  222. machineconfig/settings/television/cable_unix/git-log.toml +12 -0
  223. machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
  224. machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
  225. machineconfig/settings/television/cable_unix/guix.toml +20 -0
  226. machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
  227. machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
  228. machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
  229. machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
  230. machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
  231. machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
  232. machineconfig/settings/television/cable_unix/procs.toml +20 -0
  233. machineconfig/settings/television/cable_unix/text.toml +17 -0
  234. machineconfig/settings/television/cable_unix/tldr.toml +18 -0
  235. machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
  236. machineconfig/settings/television/cable_windows/alias.toml +7 -0
  237. machineconfig/settings/television/cable_windows/dirs.toml +13 -0
  238. machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
  239. machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
  240. machineconfig/settings/television/cable_windows/env.toml +17 -0
  241. machineconfig/settings/television/cable_windows/files.toml +14 -0
  242. machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
  243. machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
  244. machineconfig/settings/television/cable_windows/git-log.toml +11 -0
  245. machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
  246. machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
  247. machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
  248. machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
  249. machineconfig/settings/television/cable_windows/text.toml +17 -0
  250. machineconfig/settings/tv/config.toml +234 -0
  251. machineconfig/settings/tv/themes/catppuccin-mocha-sky.toml +22 -0
  252. machineconfig/settings/wsl/.wslconfig +5 -30
  253. machineconfig/settings/wt/__init__.py +0 -0
  254. machineconfig/settings/yazi/init.lua +61 -0
  255. machineconfig/settings/yazi/keymap_linux.toml +94 -0
  256. machineconfig/settings/yazi/keymap_windows.toml +78 -0
  257. machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
  258. machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
  259. machineconfig/settings/yazi/theme.toml +4 -0
  260. machineconfig/settings/yazi/yazi_linux.toml +94 -0
  261. machineconfig/settings/yazi/yazi_windows.toml +58 -0
  262. machineconfig/settings/zellij/layouts/st.kdl +40 -9
  263. machineconfig/settings/zellij/layouts/st2.kdl +1 -1
  264. machineconfig/setup_linux/__init__.py +2 -2
  265. machineconfig/setup_linux/apps_desktop.sh +8 -27
  266. machineconfig/setup_linux/web_shortcuts/interactive.sh +27 -12
  267. machineconfig/setup_linux/web_shortcuts/live_from_github.sh +34 -0
  268. machineconfig/setup_mac/__init__.py +1 -4
  269. machineconfig/setup_mac/apps_gui.sh +248 -0
  270. machineconfig/setup_windows/__init__.py +2 -5
  271. machineconfig/setup_windows/uv.ps1 +8 -1
  272. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +28 -12
  273. machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +31 -0
  274. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
  275. machineconfig/type_hinting/sql/__init__.py +1 -0
  276. machineconfig/type_hinting/sql/base.py +216 -0
  277. machineconfig/type_hinting/sql/core_schema.py +64 -0
  278. machineconfig/type_hinting/sql/core_schema_typeddict.py +41 -0
  279. machineconfig/type_hinting/sql/typeddict_codegen.py +222 -0
  280. machineconfig/type_hinting/typedict/__init__.py +1 -0
  281. machineconfig/type_hinting/typedict/ast_utils.py +130 -0
  282. machineconfig/type_hinting/typedict/generator_helpers.py +319 -0
  283. machineconfig/type_hinting/typedict/generators.py +231 -0
  284. machineconfig/type_hinting/typedict/polars_schema.py +24 -0
  285. machineconfig/type_hinting/typedict/polars_schema_typeddict.py +63 -0
  286. machineconfig/utils/accessories.py +31 -4
  287. machineconfig/utils/code.py +163 -51
  288. machineconfig/utils/files/ascii_art.py +11 -15
  289. machineconfig/utils/files/headers.py +6 -7
  290. machineconfig/utils/files/read.py +8 -1
  291. machineconfig/utils/installer_utils/github_release_bulk.py +95 -138
  292. machineconfig/utils/installer_utils/github_release_scraper.py +99 -0
  293. machineconfig/utils/installer_utils/install_from_url.py +183 -0
  294. machineconfig/utils/installer_utils/installer_class.py +53 -102
  295. machineconfig/utils/installer_utils/installer_cli.py +161 -0
  296. machineconfig/utils/installer_utils/installer_helper.py +129 -0
  297. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +42 -91
  298. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +20 -65
  299. machineconfig/utils/io.py +94 -9
  300. machineconfig/utils/links.py +56 -38
  301. machineconfig/utils/meta.py +38 -21
  302. machineconfig/utils/options.py +81 -23
  303. machineconfig/utils/options_utils/__init__.py +0 -0
  304. machineconfig/utils/options_utils/options_tv_linux.py +211 -0
  305. machineconfig/utils/options_utils/options_tv_windows.py +88 -0
  306. machineconfig/utils/options_utils/tv_options.py +37 -0
  307. machineconfig/utils/path_extended.py +52 -102
  308. machineconfig/utils/path_helper.py +76 -23
  309. machineconfig/utils/procs.py +1 -1
  310. machineconfig/utils/scheduler.py +26 -53
  311. machineconfig/utils/scheduling.py +0 -2
  312. machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
  313. machineconfig/utils/schemas/layouts/layout_types.py +1 -1
  314. machineconfig/utils/source_of_truth.py +6 -1
  315. machineconfig/utils/ssh.py +216 -419
  316. machineconfig/utils/ssh_utils/abc.py +5 -0
  317. machineconfig/utils/ssh_utils/copy_from_here.py +116 -0
  318. machineconfig/utils/ssh_utils/copy_to_here.py +303 -0
  319. machineconfig/utils/ssh_utils/utils.py +158 -0
  320. machineconfig/utils/ssh_utils/wsl.py +147 -0
  321. machineconfig/utils/ssh_utils/wsl_helper.py +217 -0
  322. machineconfig/utils/terminal.py +1 -0
  323. machineconfig/utils/upgrade_packages.py +107 -35
  324. machineconfig/utils/ve.py +12 -4
  325. machineconfig-8.51.dist-info/METADATA +140 -0
  326. machineconfig-8.51.dist-info/RECORD +543 -0
  327. {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/entry_points.txt +4 -1
  328. machineconfig/jobs/installer/check_installations.py +0 -248
  329. machineconfig/jobs/installer/custom/hx.py +0 -140
  330. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
  331. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
  332. machineconfig/jobs/installer/powershell_scripts/archive_pygraphviz.ps1 +0 -12
  333. machineconfig/jobs/installer/powershell_scripts/openssh-server_add_key.ps1 +0 -7
  334. machineconfig/jobs/installer/powershell_scripts/openssh-server_copy-ssh-id.ps1 +0 -14
  335. machineconfig/profile/backup.toml +0 -49
  336. machineconfig/profile/mapper.toml +0 -256
  337. machineconfig/scripts/linux/fzf2g +0 -21
  338. machineconfig/scripts/linux/fzfag +0 -17
  339. machineconfig/scripts/linux/fzffg +0 -25
  340. machineconfig/scripts/linux/fzfrga +0 -21
  341. machineconfig/scripts/linux/mcfgs +0 -38
  342. machineconfig/scripts/linux/other/share_smb +0 -1
  343. machineconfig/scripts/linux/other/switch_ip +0 -20
  344. machineconfig/scripts/linux/skrg +0 -4
  345. machineconfig/scripts/linux/warp-cli.sh +0 -122
  346. machineconfig/scripts/linux/z_ls +0 -104
  347. machineconfig/scripts/python/ai/command_runner/prompt.txt +0 -9
  348. machineconfig/scripts/python/helpers_devops/cli_config.py +0 -120
  349. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +0 -77
  350. machineconfig/scripts/python/helpers_devops/cli_data.py +0 -25
  351. machineconfig/scripts/python/helpers_devops/cli_nw.py +0 -73
  352. machineconfig/scripts/python/helpers_devops/cli_repos.py +0 -181
  353. machineconfig/scripts/python/helpers_devops/cli_self.py +0 -122
  354. machineconfig/scripts/python/helpers_devops/cli_share_server.py +0 -104
  355. machineconfig/scripts/python/helpers_devops/cli_utils.py +0 -221
  356. machineconfig/scripts/python/helpers_devops/devops_backup_retrieve.py +0 -80
  357. machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +0 -3
  358. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_crush.py +0 -37
  359. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_gemini.py +0 -44
  360. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_qwen.py +0 -43
  361. machineconfig/scripts/python/helpers_fire/prompt.txt +0 -2
  362. machineconfig/scripts/python/helpers_fire/template.sh +0 -15
  363. machineconfig/scripts/python/helpers_navigator/__init__.py +0 -20
  364. machineconfig/scripts/python/helpers_navigator/command_detail.py +0 -44
  365. machineconfig/scripts/python/helpers_navigator/command_tree.py +0 -588
  366. machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +0 -17
  367. machineconfig/scripts/python/helpers_repos/entrypoint.py +0 -76
  368. machineconfig/scripts/python/helpers_repos/secure_repo.py +0 -15
  369. machineconfig/scripts/python/mcfg.py +0 -48
  370. machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
  371. machineconfig/scripts/python/nw/devops_add_identity.py +0 -82
  372. machineconfig/scripts/python/nw/devops_add_ssh_key.py +0 -134
  373. machineconfig/scripts/python/nw/ssh_debug_linux.py +0 -391
  374. machineconfig/scripts/python/nw/ssh_debug_windows.py +0 -338
  375. machineconfig/scripts/python/nw/wsl_windows_transfer.py +0 -66
  376. machineconfig/scripts/windows/fzfb.ps1 +0 -3
  377. machineconfig/scripts/windows/fzfg.ps1 +0 -2
  378. machineconfig/scripts/windows/fzfrga.bat +0 -20
  379. machineconfig/scripts/windows/mcfgs.ps1 +0 -17
  380. machineconfig/scripts/windows/mounts/mount_ssh.ps1 +0 -13
  381. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  382. machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
  383. machineconfig/settings/lf/windows/tst.ps1 +0 -1
  384. machineconfig/settings/yazi/yazi.toml +0 -4
  385. machineconfig/setup_linux/apps.sh +0 -66
  386. machineconfig/setup_linux/others/cli_installation.sh +0 -137
  387. machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh +0 -30
  388. machineconfig/setup_linux/ssh/openssh_all.sh +0 -25
  389. machineconfig/setup_linux/ssh/openssh_wsl.sh +0 -38
  390. machineconfig/setup_mac/apps.sh +0 -73
  391. machineconfig/setup_mac/ssh/openssh_setup.sh +0 -114
  392. machineconfig/setup_windows/apps.ps1 +0 -62
  393. machineconfig/setup_windows/others/obs.ps1 +0 -4
  394. machineconfig/setup_windows/ssh/add-sshkey.ps1 +0 -29
  395. machineconfig/setup_windows/ssh/add_identity.ps1 +0 -11
  396. machineconfig/setup_windows/ssh/openssh-server.ps1 +0 -37
  397. machineconfig/utils/installer_utils/installer.py +0 -225
  398. machineconfig/utils/tst.py +0 -20
  399. machineconfig-6.82.dist-info/METADATA +0 -82
  400. machineconfig-6.82.dist-info/RECORD +0 -441
  401. machineconfig/jobs/installer/{custom_dev → checks}/__init__.py +0 -0
  402. machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
  403. machineconfig/{scripts/python/helpers_cloud → jobs/installer/python_scripts}/__init__.py +0 -0
  404. machineconfig/jobs/installer/{custom_dev → python_scripts}/alacritty.py +0 -0
  405. machineconfig/jobs/installer/{custom_dev → python_scripts}/bypass_paywall.py +0 -0
  406. machineconfig/jobs/installer/{custom_dev → python_scripts}/cursor.py +0 -0
  407. machineconfig/jobs/installer/{custom_dev → python_scripts}/espanso.py +0 -0
  408. machineconfig/jobs/installer/{custom → python_scripts}/gh.py +0 -0
  409. machineconfig/jobs/installer/{custom_dev → python_scripts}/goes.py +0 -0
  410. machineconfig/jobs/installer/{custom_dev → python_scripts}/lvim.py +0 -0
  411. machineconfig/jobs/installer/{custom_dev → python_scripts}/redis.py +0 -0
  412. machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/android.sh +0 -0
  413. machineconfig/jobs/{installer/linux_scripts → scripts/bash_scripts}/lid.sh +0 -0
  414. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_drive +0 -0
  415. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nw_drive +0 -0
  416. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_smb +0 -0
  417. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_cloud.sh +0 -0
  418. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_nfs +0 -0
  419. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/start_docker +0 -0
  420. machineconfig/{scripts → jobs/scripts/powershell_scripts}/Restore-ThunderbirdProfile.ps1 +0 -0
  421. machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/docker.ps1 +0 -0
  422. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nfs.ps1 +0 -0
  423. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nw.ps1 +0 -0
  424. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_smb.ps1 +0 -0
  425. machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/power_options.ps1 +0 -0
  426. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_cloud.cmd +0 -0
  427. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_smb.ps1 +0 -0
  428. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/unlock_bitlocker.ps1 +0 -0
  429. machineconfig/scripts/python/{helpers_croshell → ai/utils}/__init__.py +0 -0
  430. machineconfig/scripts/python/ai/{solutions/_shared.py → utils/shared.py} +0 -0
  431. machineconfig/scripts/python/{helpers_devops → graph}/__init__.py +0 -0
  432. machineconfig/scripts/python/{helpers_devops/themes → helpers}/__init__.py +0 -0
  433. machineconfig/scripts/python/{env_manager → helpers/helper_env}/__init__.py +0 -0
  434. machineconfig/scripts/python/{env_manager → helpers/helper_env}/path_manager_backend.py +0 -0
  435. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/__init__.py +0 -0
  436. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/__init__.py +0 -0
  437. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_search.py +0 -0
  438. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_load_balancer.py +0 -0
  439. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents/templates}/template.ps1 +0 -0
  440. machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_cloud}/__init__.py +0 -0
  441. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_helpers.py +1 -1
  442. /machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers5.py +0 -0
  443. /machineconfig/scripts/python/{helpers_sessions → helpers/helpers_croshell}/__init__.py +0 -0
  444. /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/pomodoro.py +0 -0
  445. /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer.py +0 -0
  446. /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer_template.py +0 -0
  447. /machineconfig/scripts/python/{nw → helpers/helpers_devops}/__init__.py +0 -0
  448. /machineconfig/{setup_windows/wt_and_pwsh → scripts/python/helpers/helpers_devops/themes}/__init__.py +0 -0
  449. /machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_pwsh_theme.ps1 +0 -0
  450. /machineconfig/scripts/python/{helpers_devops/themes/choose_starship_theme.ps1 → helpers/helpers_fire_command/__init__.py} +0 -0
  451. /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/cloud_manager.py +0 -0
  452. /machineconfig/scripts/python/{helpers_fire_command/fire_jobs_streamlit_helper.py → helpers/helpers_fire_command/f.py} +0 -0
  453. /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers/helpers_fire_command/fire_jobs_streamlit_helper.py} +0 -0
  454. /machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/search_bar.py +0 -0
  455. /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers/helpers_network/__init__.py} +0 -0
  456. /machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nw_drive.py +0 -0
  457. /machineconfig/scripts/python/{nw → helpers/helpers_network}/onetimeshare.py +0 -0
  458. /machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/sync.py +0 -0
  459. /machineconfig/{setup_windows/wt_and_pwsh → settings/wt}/set_wt_settings.py +0 -0
  460. {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/WHEEL +0 -0
  461. {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.installer_utils.installer_abc import find_move_delete_linux, find_move_delete_windows
3
- from machineconfig.utils.source_of_truth import INSTALL_TMP_DIR, INSTALL_VERSION_ROOT
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 json
10
- from typing import Optional, Any
11
- from urllib.parse import urlparse
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
- if repo_url == "CMD":
66
- if any(pm in installer_arch_os for pm in ["npm ", "pip ", "winget ", "brew ", "curl "]):
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=True, text=False)
72
- # from machineconfig.utils.code import run_shell_script
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
- print(f"❌ {desc} failed")
85
+ sub_panels = []
77
86
  if result.stdout:
78
- print(f"STDOUT: {result.stdout}")
87
+ sub_panels.append(Panel(result.stdout, title="STDOUT", style="blue"))
79
88
  if result.stderr:
80
- print(f"STDERR: {result.stderr}")
81
- print(f"Return code: {result.returncode}")
82
- elif installer_arch_os.endswith((".sh", ".py", ".ps1")):
83
- # search for the script, see which path ends with the script name
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 installer_arch_os.startswith("https://"): # its a url to be downloaded
109
- downloaded_object = PathExtended(installer_arch_os).download(folder=INSTALL_TMP_DIR)
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, exe_name=exe_name, delete=True, rename_to=exe_name.replace(".exe", "") + ".exe")
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.download(version=version)
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, exe_name=exe_name, delete=True, rename_to=exe_name.replace(".exe", "") + ".exe")
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 download(self, version: Optional[str]) -> tuple[PathExtended, str]:
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 or ".zip" in repo_url or ".tar.gz" 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 = PathExtended(download_link).download(folder=INSTALL_TMP_DIR).decompress()
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
- repo_name = self._get_repo_name_from_url(repo_url)
264
- if not repo_name:
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
- release_data = self._fetch_github_release_data(repo_name, version)
268
- if not release_data:
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
- # print(release_data)
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 release_data.get("assets", []):
276
- an_dl = asset.get("browser_download_url", "NA")
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