machineconfig 3.99__py3-none-any.whl → 7.66__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of machineconfig might be problematic. Click here for more details.

Files changed (418) hide show
  1. machineconfig/__init__.py +0 -28
  2. machineconfig/cluster/remote/distribute.py +0 -1
  3. machineconfig/cluster/remote/file_manager.py +0 -2
  4. machineconfig/cluster/remote/script_execution.py +1 -2
  5. machineconfig/cluster/sessions_managers/{enhanced_command_runner.py → helpers/enhanced_command_runner.py} +4 -6
  6. machineconfig/cluster/sessions_managers/helpers/load_balancer_helper.py +145 -0
  7. machineconfig/cluster/sessions_managers/utils/load_balancer.py +53 -0
  8. machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
  9. machineconfig/cluster/sessions_managers/wt_local.py +128 -330
  10. machineconfig/cluster/sessions_managers/wt_local_manager.py +53 -187
  11. machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
  12. machineconfig/cluster/sessions_managers/wt_remote_manager.py +49 -197
  13. machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
  14. machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
  15. machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
  16. machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +4 -2
  17. machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
  18. machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
  19. machineconfig/cluster/sessions_managers/zellij_local.py +81 -375
  20. machineconfig/cluster/sessions_managers/zellij_local_manager.py +22 -172
  21. machineconfig/cluster/sessions_managers/zellij_remote.py +40 -41
  22. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +13 -10
  23. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -8
  24. machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
  25. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -9
  26. machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -1
  27. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper.py +298 -0
  28. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_restart.py +77 -0
  29. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_with_panes.py +228 -0
  30. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_manager_helper.py +165 -0
  31. machineconfig/jobs/{python → installer}/check_installations.py +2 -16
  32. machineconfig/jobs/installer/custom/boxes.py +61 -0
  33. machineconfig/jobs/installer/custom/gh.py +69 -53
  34. machineconfig/jobs/installer/custom/hx.py +77 -20
  35. machineconfig/jobs/installer/custom_dev/alacritty.py +45 -30
  36. machineconfig/jobs/installer/custom_dev/brave.py +43 -35
  37. machineconfig/jobs/installer/custom_dev/bypass_paywall.py +31 -20
  38. machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
  39. machineconfig/jobs/installer/custom_dev/code.py +33 -21
  40. machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +30 -0
  41. machineconfig/jobs/installer/custom_dev/espanso.py +64 -41
  42. machineconfig/jobs/installer/custom_dev/goes.py +41 -36
  43. machineconfig/jobs/installer/custom_dev/lvim.py +49 -33
  44. machineconfig/jobs/installer/custom_dev/nerdfont.py +71 -47
  45. machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +32 -26
  46. machineconfig/jobs/installer/custom_dev/redis.py +51 -33
  47. machineconfig/jobs/installer/custom_dev/sysabc.py +119 -0
  48. machineconfig/jobs/installer/custom_dev/wezterm.py +55 -39
  49. machineconfig/jobs/installer/custom_dev/winget.py +1 -0
  50. machineconfig/jobs/installer/installer_data.json +3406 -0
  51. machineconfig/jobs/installer/linux_scripts/brave.sh +4 -14
  52. machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +5 -17
  53. machineconfig/jobs/installer/linux_scripts/docker.sh +5 -17
  54. machineconfig/jobs/installer/linux_scripts/docker_start.sh +6 -14
  55. machineconfig/jobs/installer/linux_scripts/edge.sh +3 -11
  56. machineconfig/jobs/{linux/msc → installer/linux_scripts}/lid.sh +2 -8
  57. machineconfig/jobs/installer/linux_scripts/nerdfont.sh +5 -17
  58. machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +2 -8
  59. machineconfig/jobs/installer/linux_scripts/ngrok.sh +6 -0
  60. machineconfig/jobs/installer/linux_scripts/q.sh +9 -0
  61. machineconfig/jobs/installer/linux_scripts/redis.sh +6 -17
  62. machineconfig/jobs/installer/linux_scripts/vscode.sh +5 -17
  63. machineconfig/jobs/installer/linux_scripts/wezterm.sh +4 -12
  64. machineconfig/jobs/installer/package_groups.py +255 -0
  65. machineconfig/logger.py +0 -1
  66. machineconfig/profile/backup.toml +49 -0
  67. machineconfig/profile/bash_shell_profiles.md +11 -0
  68. machineconfig/profile/create_helper.py +74 -0
  69. machineconfig/profile/create_links.py +288 -0
  70. machineconfig/profile/create_links_export.py +100 -0
  71. machineconfig/profile/create_shell_profile.py +136 -0
  72. machineconfig/profile/mapper.toml +258 -0
  73. machineconfig/scripts/Restore-ThunderbirdProfile.ps1 +92 -0
  74. machineconfig/scripts/__init__.py +0 -4
  75. machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +14 -25
  76. machineconfig/scripts/linux/wrap_mcfg +47 -0
  77. machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
  78. machineconfig/scripts/python/agents.py +198 -0
  79. machineconfig/scripts/python/ai/command_runner/command_runner.sh +9 -0
  80. machineconfig/scripts/python/ai/command_runner/prompt.txt +9 -0
  81. machineconfig/scripts/python/ai/generate_files.py +307 -42
  82. machineconfig/scripts/python/ai/initai.py +3 -28
  83. machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +17 -18
  84. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +17 -18
  85. machineconfig/scripts/python/ai/solutions/_shared.py +9 -1
  86. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +1 -1
  87. machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
  88. machineconfig/scripts/python/ai/solutions/generic.py +27 -4
  89. machineconfig/scripts/python/ai/vscode_tasks.py +37 -0
  90. machineconfig/scripts/python/cloud.py +29 -0
  91. machineconfig/scripts/python/croshell.py +117 -181
  92. machineconfig/scripts/python/define.py +31 -0
  93. machineconfig/scripts/python/devops.py +44 -124
  94. machineconfig/scripts/python/devops_navigator.py +10 -0
  95. machineconfig/scripts/python/env_manager/__init__.py +1 -0
  96. machineconfig/scripts/python/env_manager/path_manager_backend.py +47 -0
  97. machineconfig/scripts/python/env_manager/path_manager_tui.py +228 -0
  98. machineconfig/scripts/python/explore.py +49 -0
  99. machineconfig/scripts/python/fire_jobs.py +106 -244
  100. machineconfig/scripts/python/ftpx.py +125 -68
  101. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +14 -0
  102. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +37 -0
  103. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_cursor_agents.py +22 -0
  104. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +42 -0
  105. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
  106. machineconfig/scripts/python/helpers_agents/fire_agents_help_launch.py +110 -0
  107. machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +34 -0
  108. machineconfig/scripts/python/helpers_agents/fire_agents_load_balancer.py +22 -0
  109. machineconfig/scripts/python/helpers_agents/templates/prompt.txt +6 -0
  110. machineconfig/scripts/python/helpers_agents/templates/template.ps1 +14 -0
  111. machineconfig/scripts/python/helpers_agents/templates/template.sh +24 -0
  112. machineconfig/scripts/python/{cloud_copy.py → helpers_cloud/cloud_copy.py} +30 -23
  113. machineconfig/scripts/python/{cloud_mount.py → helpers_cloud/cloud_mount.py} +11 -19
  114. machineconfig/scripts/python/{cloud_sync.py → helpers_cloud/cloud_sync.py} +12 -18
  115. machineconfig/scripts/python/{helpers → helpers_cloud}/helpers2.py +3 -3
  116. machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
  117. machineconfig/scripts/python/{start_slidev.py → helpers_croshell/start_slidev.py} +17 -7
  118. machineconfig/scripts/python/helpers_devops/cli_config.py +95 -0
  119. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
  120. machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
  121. machineconfig/scripts/python/helpers_devops/cli_nw.py +134 -0
  122. machineconfig/scripts/python/helpers_devops/cli_repos.py +182 -0
  123. machineconfig/scripts/python/helpers_devops/cli_self.py +134 -0
  124. machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
  125. machineconfig/scripts/python/helpers_devops/cli_share_server.py +141 -0
  126. machineconfig/scripts/python/helpers_devops/cli_terminal.py +156 -0
  127. machineconfig/scripts/python/helpers_devops/cli_utils.py +96 -0
  128. machineconfig/scripts/python/{devops_backup_retrieve.py → helpers_devops/devops_backup_retrieve.py} +7 -10
  129. machineconfig/scripts/python/helpers_devops/devops_status.py +511 -0
  130. machineconfig/scripts/python/helpers_devops/devops_update_repos.py +269 -0
  131. machineconfig/scripts/python/helpers_devops/themes/choose_pwsh_theme.ps1 +81 -0
  132. machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
  133. machineconfig/scripts/python/{choose_wezterm_theme.py → helpers_devops/themes/choose_wezterm_theme.py} +2 -2
  134. machineconfig/scripts/python/helpers_fire_command/__init__.py +0 -0
  135. machineconfig/scripts/python/{helpers/helpers4.py → helpers_fire_command/file_wrangler.py} +57 -87
  136. machineconfig/scripts/python/helpers_fire_command/fire_jobs_args_helper.py +145 -0
  137. machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +110 -0
  138. machineconfig/scripts/python/helpers_fire_command/fire_jobs_streamlit_helper.py +0 -0
  139. machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
  140. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfag +1 -1
  141. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +1 -1
  142. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfrga +1 -1
  143. machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
  144. machineconfig/scripts/python/helpers_navigator/command_builder.py +111 -0
  145. machineconfig/scripts/python/helpers_navigator/command_detail.py +44 -0
  146. machineconfig/scripts/python/helpers_navigator/command_tree.py +588 -0
  147. machineconfig/scripts/python/helpers_navigator/data_models.py +28 -0
  148. machineconfig/scripts/python/helpers_navigator/main_app.py +272 -0
  149. machineconfig/scripts/python/helpers_navigator/search_bar.py +15 -0
  150. machineconfig/scripts/python/helpers_repos/action.py +209 -0
  151. machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
  152. machineconfig/scripts/python/{repos_helper_clone.py → helpers_repos/clone.py} +6 -7
  153. machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +218 -0
  154. machineconfig/scripts/python/helpers_repos/count_lines.py +348 -0
  155. machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +17 -0
  156. machineconfig/scripts/python/helpers_repos/entrypoint.py +77 -0
  157. machineconfig/scripts/python/helpers_repos/grource.py +340 -0
  158. machineconfig/scripts/python/{repos_helper_record.py → helpers_repos/record.py} +7 -4
  159. machineconfig/scripts/python/helpers_repos/sync.py +66 -0
  160. machineconfig/scripts/python/{repos_helper_update.py → helpers_repos/update.py} +3 -3
  161. machineconfig/scripts/python/helpers_sessions/__init__.py +0 -0
  162. machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +58 -0
  163. machineconfig/scripts/python/helpers_utils/download.py +152 -0
  164. machineconfig/scripts/python/helpers_utils/path.py +108 -0
  165. machineconfig/scripts/python/interactive.py +79 -160
  166. machineconfig/scripts/python/machineconfig.py +63 -0
  167. machineconfig/scripts/python/msearch.py +21 -0
  168. machineconfig/scripts/python/nw/__init__.py +0 -0
  169. machineconfig/scripts/python/{devops_add_identity.py → nw/devops_add_identity.py} +1 -3
  170. machineconfig/scripts/python/{devops_add_ssh_key.py → nw/devops_add_ssh_key.py} +74 -44
  171. machineconfig/scripts/{linux → python/nw}/mount_nfs +1 -1
  172. machineconfig/scripts/python/{mount_nfs.py → nw/mount_nfs.py} +19 -16
  173. machineconfig/scripts/{linux → python/nw}/mount_nw_drive +1 -2
  174. machineconfig/scripts/python/{mount_ssh.py → nw/mount_ssh.py} +7 -8
  175. machineconfig/scripts/python/{onetimeshare.py → nw/onetimeshare.py} +0 -1
  176. machineconfig/scripts/python/nw/ssh_debug_linux.py +391 -0
  177. machineconfig/scripts/python/nw/ssh_debug_windows.py +338 -0
  178. machineconfig/scripts/python/{wifi_conn.py → nw/wifi_conn.py} +1 -53
  179. machineconfig/scripts/python/{wsl_windows_transfer.py → nw/wsl_windows_transfer.py} +6 -5
  180. machineconfig/scripts/python/sessions.py +167 -0
  181. machineconfig/scripts/python/terminal.py +127 -0
  182. machineconfig/scripts/python/utils.py +66 -0
  183. machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +1 -3
  184. machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +1 -1
  185. machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -6
  186. machineconfig/scripts/windows/wrap_mcfg.ps1 +60 -0
  187. machineconfig/settings/broot/br.sh +0 -4
  188. machineconfig/settings/broot/conf.toml +1 -1
  189. machineconfig/settings/helix/config.toml +16 -0
  190. machineconfig/settings/helix/languages.toml +13 -4
  191. machineconfig/settings/helix/yazi-picker.sh +12 -0
  192. machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
  193. machineconfig/settings/lf/linux/exe/previewer.sh +9 -3
  194. machineconfig/settings/lf/linux/lfrc +10 -12
  195. machineconfig/settings/lf/windows/fzf_edit.ps1 +2 -2
  196. machineconfig/settings/lf/windows/lfrc +18 -38
  197. machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
  198. machineconfig/settings/linters/.ruff.toml +1 -1
  199. machineconfig/settings/lvim/windows/archive/config_additional.lua +0 -6
  200. machineconfig/settings/marimo/marimo.toml +80 -0
  201. machineconfig/settings/marimo/snippets/globalize.py +34 -0
  202. machineconfig/settings/pistol/pistol.conf +1 -1
  203. machineconfig/settings/shells/bash/init.sh +55 -31
  204. machineconfig/settings/shells/nushell/config.nu +1 -34
  205. machineconfig/settings/shells/nushell/init.nu +127 -0
  206. machineconfig/settings/shells/pwsh/init.ps1 +60 -43
  207. machineconfig/settings/shells/starship/starship.toml +16 -0
  208. machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
  209. machineconfig/settings/shells/wt/settings.json +32 -17
  210. machineconfig/settings/shells/zsh/init.sh +89 -0
  211. machineconfig/settings/svim/linux/init.toml +0 -4
  212. machineconfig/settings/svim/windows/init.toml +0 -3
  213. machineconfig/settings/yazi/init.lua +57 -0
  214. machineconfig/settings/yazi/keymap_linux.toml +79 -0
  215. machineconfig/settings/yazi/keymap_windows.toml +78 -0
  216. machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
  217. machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
  218. machineconfig/settings/yazi/yazi.toml +13 -0
  219. machineconfig/setup_linux/__init__.py +10 -0
  220. machineconfig/setup_linux/apps_desktop.sh +89 -0
  221. machineconfig/setup_linux/apps_gui.sh +64 -0
  222. machineconfig/setup_linux/{nix → others}/cli_installation.sh +9 -29
  223. machineconfig/setup_linux/ssh/openssh_all.sh +25 -0
  224. machineconfig/setup_linux/ssh/openssh_wsl.sh +38 -0
  225. machineconfig/setup_linux/uv.sh +15 -0
  226. machineconfig/setup_linux/web_shortcuts/interactive.sh +26 -6
  227. machineconfig/setup_mac/__init__.py +16 -0
  228. machineconfig/setup_mac/apps_gui.sh +248 -0
  229. machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
  230. machineconfig/setup_mac/uv.sh +36 -0
  231. machineconfig/setup_windows/__init__.py +8 -0
  232. machineconfig/setup_windows/others/power_options.ps1 +7 -0
  233. machineconfig/setup_windows/ssh/add-sshkey.ps1 +29 -0
  234. machineconfig/setup_windows/ssh/add_identity.ps1 +11 -0
  235. machineconfig/setup_windows/ssh/openssh-server.ps1 +37 -0
  236. machineconfig/setup_windows/uv.ps1 +10 -0
  237. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +27 -9
  238. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +16 -0
  239. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +37 -23
  240. machineconfig/utils/accessories.py +7 -5
  241. machineconfig/utils/cloud/onedrive/README.md +139 -0
  242. machineconfig/utils/code.py +140 -93
  243. machineconfig/utils/files/art/fat_croco.txt +10 -0
  244. machineconfig/utils/files/art/halfwit_croco.txt +9 -0
  245. machineconfig/utils/files/art/happy_croco.txt +22 -0
  246. machineconfig/utils/files/art/water_croco.txt +11 -0
  247. machineconfig/utils/files/ascii_art.py +118 -0
  248. machineconfig/utils/files/dbms.py +257 -0
  249. machineconfig/utils/files/headers.py +68 -0
  250. machineconfig/utils/files/ouch/__init__.py +0 -0
  251. machineconfig/utils/files/ouch/decompress.py +45 -0
  252. machineconfig/utils/files/read.py +95 -0
  253. machineconfig/utils/installer_utils/github_release_bulk.py +2 -12
  254. machineconfig/utils/installer_utils/installer_class.py +68 -126
  255. machineconfig/utils/installer_utils/installer_cli.py +181 -0
  256. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +38 -85
  257. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +69 -69
  258. machineconfig/utils/io.py +77 -23
  259. machineconfig/utils/links.py +309 -100
  260. machineconfig/utils/meta.py +255 -0
  261. machineconfig/utils/notifications.py +1 -1
  262. machineconfig/utils/options.py +10 -25
  263. machineconfig/utils/path_extended.py +94 -104
  264. machineconfig/utils/path_helper.py +75 -22
  265. machineconfig/utils/procs.py +50 -74
  266. machineconfig/utils/scheduler.py +94 -97
  267. machineconfig/utils/scheduling.py +0 -3
  268. machineconfig/utils/schemas/fire_agents/fire_agents_input.py +5 -17
  269. machineconfig/utils/schemas/installer/installer_types.py +0 -1
  270. machineconfig/utils/schemas/layouts/layout_types.py +2 -1
  271. machineconfig/utils/source_of_truth.py +3 -6
  272. machineconfig/utils/ssh.py +742 -254
  273. machineconfig/utils/ssh_utils/utils.py +0 -0
  274. machineconfig/utils/terminal.py +3 -140
  275. machineconfig/utils/tst.py +20 -0
  276. machineconfig/utils/upgrade_packages.py +109 -28
  277. machineconfig/utils/ve.py +13 -5
  278. machineconfig-7.66.dist-info/METADATA +124 -0
  279. machineconfig-7.66.dist-info/RECORD +451 -0
  280. machineconfig-7.66.dist-info/entry_points.txt +15 -0
  281. machineconfig/cluster/templates/utils.py +0 -51
  282. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -49
  283. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -85
  284. machineconfig/jobs/installer/packages_custom_dev.json +0 -226
  285. machineconfig/jobs/installer/packages_custom_essential.json +0 -39
  286. machineconfig/jobs/installer/packages_github_dev.json +0 -1110
  287. machineconfig/jobs/installer/packages_github_essential.json +0 -804
  288. machineconfig/jobs/linux/msc/cli_agents.sh +0 -37
  289. machineconfig/jobs/python/create_bootable_media.py +0 -16
  290. machineconfig/jobs/python/python_cargo_build_share.py +0 -59
  291. machineconfig/jobs/python/python_ve_symlink.py +0 -29
  292. machineconfig/jobs/python/tasks.py +0 -3
  293. machineconfig/jobs/python/vscode/api.py +0 -49
  294. machineconfig/jobs/python/vscode/sync_code.py +0 -58
  295. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -14
  296. machineconfig/jobs/windows/start_terminal.ps1 +0 -6
  297. machineconfig/jobs/windows/startup_file.cmd +0 -2
  298. machineconfig/profile/create.py +0 -170
  299. machineconfig/profile/shell.py +0 -176
  300. machineconfig/scripts/cloud/init.sh +0 -119
  301. machineconfig/scripts/linux/choose_wezterm_theme +0 -3
  302. machineconfig/scripts/linux/cloud_copy +0 -2
  303. machineconfig/scripts/linux/cloud_mount +0 -2
  304. machineconfig/scripts/linux/cloud_repo_sync +0 -2
  305. machineconfig/scripts/linux/cloud_sync +0 -2
  306. machineconfig/scripts/linux/croshell +0 -3
  307. machineconfig/scripts/linux/devops +0 -2
  308. machineconfig/scripts/linux/fire +0 -2
  309. machineconfig/scripts/linux/fire_agents +0 -2
  310. machineconfig/scripts/linux/ftpx +0 -2
  311. machineconfig/scripts/linux/fzf2g +0 -21
  312. machineconfig/scripts/linux/fzffg +0 -25
  313. machineconfig/scripts/linux/gh_models +0 -2
  314. machineconfig/scripts/linux/initai +0 -2
  315. machineconfig/scripts/linux/kill_process +0 -2
  316. machineconfig/scripts/linux/programs +0 -21
  317. machineconfig/scripts/linux/repos +0 -2
  318. machineconfig/scripts/linux/scheduler +0 -2
  319. machineconfig/scripts/linux/share_smb +0 -1
  320. machineconfig/scripts/linux/start_slidev +0 -2
  321. machineconfig/scripts/linux/start_terminals +0 -3
  322. machineconfig/scripts/linux/warp-cli.sh +0 -122
  323. machineconfig/scripts/linux/wifi_conn +0 -2
  324. machineconfig/scripts/linux/z_ls +0 -104
  325. machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
  326. machineconfig/scripts/python/cloud_repo_sync.py +0 -186
  327. machineconfig/scripts/python/devops_devapps_install.py +0 -159
  328. machineconfig/scripts/python/devops_update_repos.py +0 -180
  329. machineconfig/scripts/python/dotfile.py +0 -52
  330. machineconfig/scripts/python/fire_agents.py +0 -175
  331. machineconfig/scripts/python/fire_agents_help_launch.py +0 -143
  332. machineconfig/scripts/python/fire_agents_load_balancer.py +0 -50
  333. machineconfig/scripts/python/fire_jobs_args_helper.py +0 -75
  334. machineconfig/scripts/python/fire_jobs_layout_helper.py +0 -74
  335. machineconfig/scripts/python/get_zellij_cmd.py +0 -15
  336. machineconfig/scripts/python/gh_models.py +0 -104
  337. machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -114
  338. machineconfig/scripts/python/repos.py +0 -80
  339. machineconfig/scripts/python/repos_helper_action.py +0 -335
  340. machineconfig/scripts/python/share_terminal.py +0 -104
  341. machineconfig/scripts/python/snapshot.py +0 -25
  342. machineconfig/scripts/python/start_terminals.py +0 -121
  343. machineconfig/scripts/python/t4.py +0 -17
  344. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
  345. machineconfig/scripts/windows/cloud_copy.ps1 +0 -1
  346. machineconfig/scripts/windows/cloud_mount.ps1 +0 -1
  347. machineconfig/scripts/windows/cloud_repo_sync.ps1 +0 -1
  348. machineconfig/scripts/windows/cloud_sync.ps1 +0 -1
  349. machineconfig/scripts/windows/croshell.ps1 +0 -1
  350. machineconfig/scripts/windows/devops.ps1 +0 -1
  351. machineconfig/scripts/windows/dotfile.ps1 +0 -1
  352. machineconfig/scripts/windows/fire.ps1 +0 -1
  353. machineconfig/scripts/windows/ftpx.ps1 +0 -1
  354. machineconfig/scripts/windows/gpt.ps1 +0 -1
  355. machineconfig/scripts/windows/grep.ps1 +0 -2
  356. machineconfig/scripts/windows/initai.ps1 +0 -1
  357. machineconfig/scripts/windows/kill_process.ps1 +0 -1
  358. machineconfig/scripts/windows/nano.ps1 +0 -3
  359. machineconfig/scripts/windows/pomodoro.ps1 +0 -1
  360. machineconfig/scripts/windows/reload_path.ps1 +0 -3
  361. machineconfig/scripts/windows/repos.ps1 +0 -1
  362. machineconfig/scripts/windows/scheduler.ps1 +0 -1
  363. machineconfig/scripts/windows/snapshot.ps1 +0 -1
  364. machineconfig/scripts/windows/start_slidev.ps1 +0 -1
  365. machineconfig/scripts/windows/start_terminals.ps1 +0 -1
  366. machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
  367. machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
  368. machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
  369. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  370. machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +0 -57
  371. machineconfig/setup_linux/web_shortcuts/ascii_art.sh +0 -93
  372. machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -11
  373. machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -52
  374. machineconfig/setup_windows/web_shortcuts/all.ps1 +0 -18
  375. machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +0 -36
  376. machineconfig/setup_windows/web_shortcuts/croshell.ps1 +0 -16
  377. machineconfig/setup_windows/web_shortcuts/ssh.ps1 +0 -11
  378. machineconfig/utils/ai/generate_file_checklist.py +0 -68
  379. machineconfig-3.99.dist-info/METADATA +0 -167
  380. machineconfig-3.99.dist-info/RECORD +0 -409
  381. machineconfig-3.99.dist-info/entry_points.txt +0 -18
  382. machineconfig/cluster/{templates → remote}/run_cloud.py +0 -0
  383. machineconfig/cluster/{templates → remote}/run_cluster.py +0 -0
  384. machineconfig/cluster/{templates → remote}/run_remote.py +0 -0
  385. machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
  386. machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
  387. machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
  388. machineconfig/{jobs/python → scripts/python/helpers_agents}/__init__.py +0 -0
  389. machineconfig/scripts/python/{helpers → helpers_agents/agentic_frameworks}/__init__.py +0 -0
  390. machineconfig/scripts/python/{fire_agents_help_search.py → helpers_agents/fire_agents_help_search.py} +0 -0
  391. machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_cloud/__init__.py} +0 -0
  392. machineconfig/scripts/python/{helpers → helpers_cloud}/cloud_helpers.py +1 -1
  393. /machineconfig/scripts/python/{helpers → helpers_cloud}/helpers5.py +0 -0
  394. /machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_croshell/__init__.py} +0 -0
  395. /machineconfig/scripts/python/{pomodoro.py → helpers_croshell/pomodoro.py} +0 -0
  396. /machineconfig/scripts/python/{scheduler.py → helpers_croshell/scheduler.py} +0 -0
  397. /machineconfig/scripts/python/{viewer.py → helpers_croshell/viewer.py} +0 -0
  398. /machineconfig/scripts/python/{viewer_template.py → helpers_croshell/viewer_template.py} +0 -0
  399. /machineconfig/scripts/python/{fire_jobs_streamlit_helper.py → helpers_devops/__init__.py} +0 -0
  400. /machineconfig/scripts/{windows/share_nfs.ps1 → python/helpers_devops/themes/__init__.py} +0 -0
  401. /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
  402. /machineconfig/scripts/python/{cloud_manager.py → helpers_fire_command/cloud_manager.py} +0 -0
  403. /machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/skrg +0 -0
  404. /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfb.ps1 +0 -0
  405. /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfg.ps1 +0 -0
  406. /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfrga.bat +0 -0
  407. /machineconfig/scripts/{linux → python/nw}/mount_drive +0 -0
  408. /machineconfig/scripts/python/{mount_nw_drive.py → nw/mount_nw_drive.py} +0 -0
  409. /machineconfig/scripts/{linux → python/nw}/mount_smb +0 -0
  410. /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
  411. /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
  412. /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
  413. /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
  414. /machineconfig/setup_linux/{web_shortcuts → others}/android.sh +0 -0
  415. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
  416. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
  417. {machineconfig-3.99.dist-info → machineconfig-7.66.dist-info}/WHEEL +0 -0
  418. {machineconfig-3.99.dist-info → machineconfig-7.66.dist-info}/top_level.txt +0 -0
@@ -1,18 +1,33 @@
1
- from machineconfig.utils.path_extended import PathExtended as 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, LIBRARY_ROOT
4
- from machineconfig.utils.installer_utils.installer_abc import check_tool_exists
5
- from machineconfig.utils.io import read_json
6
- from machineconfig.utils.schemas.installer.installer_types import InstallerData, InstallerDataFiles, get_os_name, get_normalized_arch
1
+ from machineconfig.utils.path_extended import PathExtended, DECOMPRESS_SUPPORTED_FORMATS
2
+ from machineconfig.utils.source_of_truth import INSTALL_TMP_DIR, INSTALL_VERSION_ROOT
3
+ from machineconfig.utils.installer_utils.installer_locator_utils import find_move_delete_linux, find_move_delete_windows, check_tool_exists
4
+ from machineconfig.utils.schemas.installer.installer_types import InstallerData, get_os_name, get_normalized_arch
7
5
 
8
6
  import platform
9
7
  import subprocess
10
8
  import json
11
9
  from typing import Optional, Any
12
- from pathlib import Path
13
10
  from urllib.parse import urlparse
14
11
 
15
12
 
13
+
14
+ def install_deb_package(downloaded: PathExtended) -> None:
15
+ print(f"📦 Installing .deb package: {downloaded}")
16
+ assert platform.system() == "Linux"
17
+ result = subprocess.run(f"sudo nala install -y {downloaded}", shell=True, capture_output=True, text=True)
18
+ success = result.returncode == 0 and result.stderr == ""
19
+ if not success:
20
+ desc = "Installing .deb"
21
+ print(f"❌ {desc} failed")
22
+ if result.stdout:
23
+ print(f"STDOUT: {result.stdout}")
24
+ if result.stderr:
25
+ print(f"STDERR: {result.stderr}")
26
+ print(f"Return code: {result.returncode}")
27
+ print("🗑️ Cleaning up .deb package...")
28
+ downloaded.delete(sure=True)
29
+
30
+
16
31
  class Installer:
17
32
  def __init__(self, installer_data: InstallerData):
18
33
  self.installer_data: InstallerData = installer_data
@@ -32,64 +47,21 @@ class Installer:
32
47
 
33
48
  def _get_exe_name(self) -> str:
34
49
  """Derive executable name from app name by converting to lowercase and removing spaces."""
35
- return self.installer_data["appName"].lower().replace(" ", "").replace("-", "")
36
-
37
- @staticmethod
38
- def choose_app_and_install():
39
- print(f"\n{'=' * 80}\n🔍 SELECT APPLICATION TO INSTALL 🔍\n{'=' * 80}")
40
- from machineconfig.utils.options import choose_from_options
41
-
42
- print("📂 Searching for configuration files...")
43
- jobs_dir = Path(LIBRARY_ROOT.joinpath("jobs"))
44
- config_paths = [Path(p) for p in jobs_dir.rglob("config.json")]
45
- path = choose_from_options(multi=False, options=config_paths, msg="Choose one option")
46
- print(f"📄 Loading configuration from: {path}")
47
- config_data = read_json(path)
48
- installer_data_files = InstallerDataFiles(config_data)
49
-
50
- # Extract app names from the installers
51
- app_names = [installer["appName"] for installer in installer_data_files["installers"]]
52
- print("🔍 Select an application to install:")
53
- app_name = choose_from_options(multi=False, options=app_names, fzf=True, msg="Choose one option")
54
-
55
- # Find the selected installer data
56
- selected_installer_data = None
57
- for installer_data in installer_data_files["installers"]:
58
- if installer_data["appName"] == app_name:
59
- selected_installer_data = installer_data
60
- break
61
-
62
- if selected_installer_data is None:
63
- raise ValueError(f"Could not find installer data for {app_name}")
64
-
65
- installer = Installer(installer_data=selected_installer_data)
66
- exe_name = installer._get_exe_name()
67
- print(f"📦 Selected application: {exe_name}")
68
- version = input(f"📝 Enter version to install for {exe_name} [latest]: ") or None
69
- print(f"\n{'=' * 80}\n🚀 INSTALLING {exe_name.upper()} 🚀\n{'=' * 80}")
70
- installer.install(version=version)
50
+ return self.installer_data["appName"].lower().replace(" ", "") # .replace("-", "")
71
51
 
72
52
  def install_robust(self, version: Optional[str]) -> str:
73
53
  try:
74
54
  exe_name = self._get_exe_name()
75
- print(f"\n{'=' * 80}\n🚀 INSTALLING {exe_name.upper()} 🚀\n{'=' * 80}")
76
55
  result_old = subprocess.run(f"{exe_name} --version", shell=True, capture_output=True, text=True)
77
56
  old_version_cli = result_old.stdout.strip()
78
- print(f"📊 Current version: {old_version_cli or 'Not installed'}")
79
-
57
+ print(f"🚀 INSTALLING {exe_name.upper()} 🚀. 📊 Current version: {old_version_cli or 'Not installed'}")
80
58
  self.install(version=version)
81
-
82
59
  result_new = subprocess.run(f"{exe_name} --version", shell=True, capture_output=True, text=True)
83
60
  new_version_cli = result_new.stdout.strip()
84
- print(f"📊 New version: {new_version_cli}")
85
-
86
61
  if old_version_cli == new_version_cli:
87
- print(f"ℹ️ Same version detected: {old_version_cli}")
88
62
  return f"""📦️ 😑 {exe_name}, same version: {old_version_cli}"""
89
63
  else:
90
- print(f"🚀 Update successful: {old_version_cli} ➡️ {new_version_cli}")
91
64
  return f"""📦️ 🤩 {exe_name} updated from {old_version_cli} ➡️ TO ➡️ {new_version_cli}"""
92
-
93
65
  except Exception as ex:
94
66
  exe_name = self._get_exe_name()
95
67
  app_name = self.installer_data["appName"]
@@ -104,18 +76,15 @@ class Installer:
104
76
  installer_arch_os = self.installer_data["fileNamePattern"][arch][os_name]
105
77
  if installer_arch_os is None:
106
78
  raise ValueError(f"No installation pattern for {exe_name} on {os_name} {arch}")
107
-
108
- print(f"\n{'=' * 80}\n🔧 INSTALLATION PROCESS: {exe_name} 🔧\n{'=' * 80}")
109
79
  version_to_be_installed: str = "unknown" # Initialize to ensure it's always bound
110
80
  if repo_url == "CMD":
111
- if "npm " in installer_arch_os or "pip " in installer_arch_os or "winget " in installer_arch_os:
81
+ if any(pm in installer_arch_os for pm in ["npm ", "pip ", "winget ", "brew ", "curl "]):
112
82
  package_manager = installer_arch_os.split(" ", maxsplit=1)[0]
113
- print(f"📦 Using package manager: {package_manager}")
83
+ print(f"📦 Using package manager: {installer_arch_os}")
114
84
  desc = package_manager + " installation"
115
85
  version_to_be_installed = package_manager + "Latest"
116
- print(f"🚀 Running: {installer_arch_os}")
117
- result = subprocess.run(installer_arch_os, shell=True, capture_output=True, text=True)
118
- success = result.returncode == 0 and result.stderr == ""
86
+ result = subprocess.run(installer_arch_os, shell=True, capture_output=True, text=False)
87
+ success = result.returncode == 0 and result.stderr == "".encode()
119
88
  if not success:
120
89
  print(f"❌ {desc} failed")
121
90
  if result.stdout:
@@ -123,9 +92,7 @@ class Installer:
123
92
  if result.stderr:
124
93
  print(f"STDERR: {result.stderr}")
125
94
  print(f"Return code: {result.returncode}")
126
- print(f"✅ Package manager installation completed\n{'=' * 80}")
127
95
  elif installer_arch_os.endswith((".sh", ".py", ".ps1")):
128
- # search for the script, see which path ends with the script name
129
96
  import machineconfig.jobs.installer as module
130
97
  from pathlib import Path
131
98
  search_root = Path(module.__file__).parent
@@ -139,33 +106,29 @@ class Installer:
139
106
  if installer_arch_os.endswith(".sh"):
140
107
  if platform.system() not in ["Linux", "Darwin"]:
141
108
  raise NotImplementedError(f"Shell script installation not supported on {platform.system()}")
142
- print(f"🚀 Running shell script: {installer_path}")
143
109
  subprocess.run(f"bash {installer_path}", shell=True, check=True)
144
110
  version_to_be_installed = "scripted_installation"
145
- print(f"✅ Shell script installation completed\n{'=' * 80}")
146
111
  elif installer_arch_os.endswith(".ps1"):
147
112
  if platform.system() != "Windows":
148
113
  raise NotImplementedError(f"PowerShell script installation not supported on {platform.system()}")
149
- print(f"🚀 Running PowerShell script: {installer_path}")
150
114
  subprocess.run(f"powershell -ExecutionPolicy Bypass -File {installer_path}", shell=True, check=True)
151
115
  version_to_be_installed = "scripted_installation"
152
- print(f"✅ PowerShell script installation completed\n{'=' * 80}")
153
116
  elif installer_arch_os.endswith(".py"):
154
117
  import runpy
155
118
  runpy.run_path(str(installer_path), run_name=None)["main"](self.installer_data, version=version)
156
119
  version_to_be_installed = str(version)
157
- print(f"✅ Custom installation completed\n{'=' * 80}")
158
120
  elif installer_arch_os.startswith("https://"): # its a url to be downloaded
159
- print(f"📥 Downloading object from URL: {installer_arch_os}")
160
- downloaded_object = PathExtended(installer_arch_os).download(folder=INSTALL_TMP_DIR)
121
+ # downloaded_object = PathExtended(installer_arch_os).download(folder=INSTALL_TMP_DIR)
122
+ from machineconfig.scripts.python.helpers_utils.download import download
123
+ downloaded_object = download(installer_arch_os, output_dir=str(INSTALL_TMP_DIR))
124
+ if downloaded_object is None:
125
+ raise ValueError(f"Failed to download from URL: {installer_arch_os}")
161
126
  # object is either a zip containing a binary or a straight out binary.
162
- if downloaded_object.suffix in [".zip", ".tar.gz"]:
163
- print(f"📦 Decompressing downloaded archive: {downloaded_object}")
127
+ downloaded_object = PathExtended(downloaded_object)
128
+ if downloaded_object.suffix in DECOMPRESS_SUPPORTED_FORMATS:
164
129
  downloaded_object = downloaded_object.decompress()
165
- print(f"✅ Decompression completed to: {downloaded_object}")
166
130
  if downloaded_object.suffix in [".exe", ""]: # likely an executable
167
131
  if platform.system() == "Windows":
168
- print("🪟 Installing on Windows...")
169
132
  exe = find_move_delete_windows(downloaded_file_path=downloaded_object, exe_name=exe_name, delete=True, rename_to=exe_name.replace(".exe", "") + ".exe")
170
133
  elif platform.system() in ["Linux", "Darwin"]:
171
134
  system_name = "Linux" if platform.system() == "Linux" else "macOS"
@@ -175,7 +138,6 @@ class Installer:
175
138
  error_msg = f"❌ ERROR: System {platform.system()} not supported"
176
139
  print(error_msg)
177
140
  raise NotImplementedError(error_msg)
178
-
179
141
  _ = exe
180
142
  if exe.name.replace(".exe", "") != exe_name.replace(".exe", ""):
181
143
  from rich import print as pprint
@@ -186,32 +148,19 @@ class Installer:
186
148
  print(f"🔄 Renaming to correct name: {new_exe_name}")
187
149
  exe.with_name(name=new_exe_name, inplace=True, overwrite=True)
188
150
  version_to_be_installed = "downloaded_binary"
189
- print(f"✅ Downloaded binary installation completed\n{'=' * 80}")
151
+ elif downloaded_object.suffix in [".deb"]:
152
+ install_deb_package(downloaded_object)
153
+ version_to_be_installed = "downloaded_deb"
154
+ else:
155
+ raise ValueError(f"Downloaded file is not an executable: {downloaded_object}")
190
156
  else:
191
157
  raise NotImplementedError(f"CMD installation method not implemented for: {installer_arch_os}")
192
158
  else:
193
159
  assert repo_url.startswith("https://github.com/"), f"repoURL must be a GitHub URL, got {repo_url}"
194
- print("📥 Downloading from repository...")
195
- downloaded, version_to_be_installed = self.download(version=version)
196
- if str(downloaded).endswith(".deb"):
197
- print(f"📦 Installing .deb package: {downloaded}")
198
- assert platform.system() == "Linux"
199
- result = subprocess.run(f"sudo nala install -y {downloaded}", shell=True, capture_output=True, text=True)
200
- success = result.returncode == 0 and result.stderr == ""
201
- if not success:
202
- desc = "Installing .deb"
203
- print(f"❌ {desc} failed")
204
- if result.stdout:
205
- print(f"STDOUT: {result.stdout}")
206
- if result.stderr:
207
- print(f"STDERR: {result.stderr}")
208
- print(f"Return code: {result.returncode}")
209
- print("🗑️ Cleaning up .deb package...")
210
- downloaded.delete(sure=True)
211
- print(f"✅ DEB package installation completed\n{'=' * 80}")
160
+ downloaded, version_to_be_installed = self.binary_download(version=version)
161
+ if str(downloaded).endswith(".deb"): install_deb_package(downloaded)
212
162
  else:
213
163
  if platform.system() == "Windows":
214
- print("🪟 Installing on Windows...")
215
164
  exe = find_move_delete_windows(downloaded_file_path=downloaded, exe_name=exe_name, delete=True, rename_to=exe_name.replace(".exe", "") + ".exe")
216
165
  elif platform.system() in ["Linux", "Darwin"]:
217
166
  system_name = "Linux" if platform.system() == "Linux" else "macOS"
@@ -221,33 +170,24 @@ class Installer:
221
170
  error_msg = f"❌ ERROR: System {platform.system()} not supported"
222
171
  print(error_msg)
223
172
  raise NotImplementedError(error_msg)
224
-
225
173
  _ = exe
226
174
  if exe.name.replace(".exe", "") != exe_name.replace(".exe", ""):
227
175
  from rich import print as pprint
228
176
  from rich.panel import Panel
229
-
230
177
  print("⚠️ Warning: Executable name mismatch")
231
178
  pprint(Panel(f"Expected exe name: [red]{exe_name}[/red] \nAttained name: [red]{exe.name.replace('.exe', '')}[/red]", title="exe name mismatch", subtitle=repo_url))
232
179
  new_exe_name = exe_name + ".exe" if platform.system() == "Windows" else exe_name
233
180
  print(f"🔄 Renaming to correct name: {new_exe_name}")
234
181
  exe.with_name(name=new_exe_name, inplace=True, overwrite=True)
235
-
236
- print(f"💾 Saving version information to: {INSTALL_VERSION_ROOT.joinpath(exe_name)}")
237
182
  INSTALL_VERSION_ROOT.joinpath(exe_name).parent.mkdir(parents=True, exist_ok=True)
238
183
  INSTALL_VERSION_ROOT.joinpath(exe_name).write_text(version_to_be_installed or "unknown", encoding="utf-8")
239
- print(f"✅ Installation completed successfully!\n{'=' * 80}")
240
-
241
- def download(self, version: Optional[str]) -> tuple[PathExtended, str]:
184
+ def binary_download(self, version: Optional[str]) -> tuple[PathExtended, str]:
242
185
  exe_name = self._get_exe_name()
243
186
  repo_url = self.installer_data["repoURL"]
244
- app_name = self.installer_data["appName"]
245
- print(f"\n{'=' * 80}\n📥 DOWNLOADING: {exe_name} 📥\n{'=' * 80}")
246
-
187
+ # app_name = self.installer_data["appName"]
247
188
  download_link: Optional[str] = None
248
189
  version_to_be_installed: Optional[str] = None
249
-
250
- if "github" not in repo_url or ".zip" in repo_url or ".tar.gz" in repo_url:
190
+ if "github" not in repo_url or (any(ext in repo_url for ext in DECOMPRESS_SUPPORTED_FORMATS)):
251
191
  # Direct download URL
252
192
  download_link = repo_url
253
193
  version_to_be_installed = "predefined_url"
@@ -259,25 +199,20 @@ class Installer:
259
199
  arch = get_normalized_arch()
260
200
  os_name = get_os_name()
261
201
  print(f"🧭 Detected system={os_name} arch={arch}")
262
-
263
202
  # Use existing get_github_release method to get download link and version
264
203
  download_link, version_to_be_installed = self.get_github_release(repo_url, version)
265
-
266
204
  if download_link is None:
267
205
  raise ValueError(f"Could not retrieve download link for {exe_name} version {version or 'latest'}")
268
-
269
206
  print(f"📦 Version to be installed: {version_to_be_installed}")
270
207
  print(f"🔗 Download URL: {download_link}")
271
-
272
208
  assert download_link is not None, "download_link must be set"
273
209
  assert version_to_be_installed is not None, "version_to_be_installed must be set"
274
- print(f"📥 Downloading {app_name} from: {download_link}")
275
210
  downloaded = PathExtended(download_link).download(folder=INSTALL_TMP_DIR).decompress()
276
- print(f"✅ Download and extraction completed to: {downloaded}\n{'=' * 80}")
211
+ if downloaded.is_dir() and len(downloaded.search("*", r=True)) == 1:
212
+ only_file_in = next(downloaded.glob("*"))
213
+ if only_file_in.is_file() and only_file_in.suffix in DECOMPRESS_SUPPORTED_FORMATS: # further decompress
214
+ downloaded = only_file_in.decompress()
277
215
  return downloaded, version_to_be_installed
278
-
279
- # --------------------------- Arch / template helpers ---------------------------
280
-
281
216
  @staticmethod
282
217
  def _get_repo_name_from_url(repo_url: str) -> str:
283
218
  """Extract owner/repo from GitHub URL."""
@@ -292,23 +227,16 @@ class Installer:
292
227
  def _fetch_github_release_data(repo_name: str, version: Optional[str] = None) -> Optional[dict[str, Any]]:
293
228
  """Fetch release data from GitHub API using requests."""
294
229
  import requests
295
-
296
230
  try:
297
- if version and version.lower() != "latest":
298
- # Fetch specific version
231
+ if version and version.lower() != "latest": # Fetch specific version
299
232
  url = f"https://api.github.com/repos/{repo_name}/releases/tags/{version}"
300
- else:
301
- # Fetch latest release
233
+ else: # Fetch latest release
302
234
  url = f"https://api.github.com/repos/{repo_name}/releases/latest"
303
-
304
235
  response = requests.get(url, timeout=30)
305
-
306
236
  if response.status_code != 200:
307
237
  print(f"❌ Failed to fetch data for {repo_name}: HTTP {response.status_code}")
308
238
  return None
309
-
310
239
  response_data = response.json()
311
-
312
240
  # Check if API returned an error
313
241
  if "message" in response_data:
314
242
  if "API rate limit exceeded" in response_data.get("message", ""):
@@ -350,9 +278,23 @@ class Installer:
350
278
  an_dl = asset.get("browser_download_url", "NA")
351
279
  available_filenames.append(an_dl.split("/")[-1])
352
280
  if filename not in available_filenames:
353
- filename = filename_pattern.format(version=actual_version.replace("v", ""))
354
- if filename not in available_filenames:
355
- print(f"❌ Filename {filename} not found in assets: {available_filenames}")
281
+ candidates = [
282
+ filename,
283
+ filename_pattern.format(version=actual_version),
284
+ filename_pattern.format(version=actual_version.replace("v", "")),
285
+ ]
286
+
287
+ # Include hyphen/underscore variants
288
+ variants = []
289
+ for f in candidates:
290
+ variants += [f, f.replace("-", "_"), f.replace("_", "-")]
291
+
292
+ for f in variants:
293
+ if f in available_filenames:
294
+ filename = f
295
+ break
296
+ else:
297
+ print(f"❌ Filename not found in assets. Tried: {variants}\nAvailable: {available_filenames}")
356
298
  return None, None
357
299
  browser_download_url = f"{repo_url}/releases/download/{actual_version}/{filename}"
358
300
  return browser_download_url, actual_version
@@ -0,0 +1,181 @@
1
+ """Devops Devapps Install"""
2
+
3
+ import typer
4
+ from typing import Optional, Annotated
5
+ from machineconfig.jobs.installer.package_groups import PACKAGE_GROUP2NAMES
6
+
7
+
8
+ def main(
9
+ which: Annotated[Optional[str], typer.Argument(..., help="Comma-separated list of program/groups names to install (if --group flag is set).")] = None,
10
+ group: Annotated[bool, typer.Option(..., "--group", "-g", help="Treat 'which' as a group name. A group is bundle of apps.")] = False,
11
+ interactive: Annotated[bool, typer.Option(..., "--interactive", "-i", help="Interactive selection of programs to install.")] = False,
12
+ ) -> None:
13
+ if interactive:
14
+ return install_interactively()
15
+ if which is not None:
16
+ if group:
17
+ for a_group in [x.strip() for x in which.split(",") if x.strip() != ""]:
18
+ return install_group(package_group=a_group)
19
+ else:
20
+ return install_clis(clis_names=[x.strip() for x in which.split(",") if x.strip() != ""])
21
+ else:
22
+ if group:
23
+ from rich.console import Console
24
+ from rich.table import Table
25
+ console = Console()
26
+
27
+ typer.echo("❌ You must provide a group name when using the --group/-g option.")
28
+ res = get_group_name_to_repr()
29
+ console.print("[bold blue]Here are the available groups:[/bold blue]")
30
+ table = Table(show_header=True, header_style="bold magenta")
31
+ table.add_column("Group", style="cyan", no_wrap=True)
32
+ table.add_column("AppsBundled", style="green", overflow="fold")
33
+ for display, group_name in res.items():
34
+ # Parse display
35
+ if " -- " in display:
36
+ group_part, items_part = display.split(" -- ", 1)
37
+ group_name_parsed = group_part.replace("📦 ", "").strip()
38
+ items_str = items_part.strip()
39
+ else:
40
+ group_name_parsed = display
41
+ items_str = group_name
42
+ table.add_row(group_name_parsed, items_str)
43
+ console.print(table)
44
+ raise typer.Exit(1)
45
+ typer.echo("❌ You must provide either a program name/group name, or use --interactive/-ia option.")
46
+ import click
47
+ ctx = click.get_current_context()
48
+ typer.echo(ctx.get_help())
49
+ raise typer.Exit(1)
50
+
51
+
52
+ def get_group_name_to_repr() -> dict[str, str]:
53
+ # Build category options and maintain a mapping from display text to actual category name
54
+ category_display_to_name: dict[str, str] = {}
55
+ for group_name, group_values in PACKAGE_GROUP2NAMES.items():
56
+ display = f"📦 {group_name:<20}" + " -- " + f"{'|'.join(group_values):<60}"
57
+ category_display_to_name[display] = group_name
58
+ return category_display_to_name
59
+
60
+
61
+ def install_interactively():
62
+ from machineconfig.utils.options import choose_from_options
63
+ from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
64
+ from machineconfig.utils.installer_utils.installer_runner import get_installers
65
+ from machineconfig.utils.installer_utils.installer_class import Installer
66
+ from rich.console import Console
67
+ from rich.panel import Panel
68
+ # from rich.table import Table
69
+ installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=None)
70
+ installer_options = [Installer(installer_data=x).get_description() for x in installers]
71
+ category_display_to_name = get_group_name_to_repr()
72
+ options = list(category_display_to_name.keys()) + installer_options
73
+ program_names = choose_from_options(multi=True, msg="Categories are prefixed with 📦", options=options, header="🚀 CHOOSE DEV APP OR CATEGORY", fzf=True)
74
+ installation_messages: list[str] = []
75
+ for _an_idx, a_program_name in enumerate(program_names):
76
+ if a_program_name.startswith("📦 "):
77
+ category_name = category_display_to_name.get(a_program_name)
78
+ if category_name:
79
+ install_group(package_group=category_name)
80
+ else:
81
+ installer_idx = installer_options.index(a_program_name)
82
+ an_installer_data = installers[installer_idx]
83
+ status_message = Installer(an_installer_data).install_robust(version=None) # finish the task - this returns a status message, not a command
84
+ installation_messages.append(status_message)
85
+ if installation_messages:
86
+ console = Console()
87
+
88
+ 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))
89
+ console.print(panel)
90
+
91
+
92
+ def install_group(package_group: str):
93
+ from machineconfig.utils.installer_utils.installer_runner import get_installers, install_bulk
94
+ from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
95
+ from rich.console import Console
96
+ from rich.panel import Panel
97
+ # from rich.table import Table
98
+ if package_group in PACKAGE_GROUP2NAMES:
99
+ 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))
100
+ console = Console()
101
+ console.print(panel)
102
+ installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=[package_group])
103
+ install_bulk(installers_data=installers_)
104
+ return
105
+ console = Console()
106
+ console.print(f"❌ ERROR: Unknown package group: {package_group}. Available groups are: {list(PACKAGE_GROUP2NAMES.keys())}")
107
+ def _handle_installer_not_found(search_term: str, all_names: list[str]) -> None: # type: ignore
108
+ """Handle installer not found with friendly suggestions using fuzzy matching."""
109
+ from difflib import get_close_matches
110
+ from rich.console import Console
111
+ from rich.panel import Panel
112
+ from rich.table import Table
113
+ close_matches = get_close_matches(search_term, all_names, n=5, cutoff=0.4)
114
+ console = Console()
115
+
116
+ console.print(f"\n❌ '[red]{search_term}[/red]' was not found.", style="bold")
117
+ if close_matches:
118
+ console.print("🤔 Did you mean one of these?", style="yellow")
119
+ table = Table(show_header=False, box=None, pad_edge=False)
120
+ for i, match in enumerate(close_matches, 1):
121
+ table.add_row(f"[cyan]{i}.[/cyan]", f"[green]{match}[/green]")
122
+ console.print(table)
123
+ else:
124
+ console.print("📋 Here are some available options:", style="blue")
125
+ # Show first 10 installers as examples
126
+ if len(all_names) > 10:
127
+ sample_names = all_names[:10]
128
+ else:
129
+ sample_names = all_names
130
+ table = Table(show_header=False, box=None, pad_edge=False)
131
+ for i, name in enumerate(sample_names, 1):
132
+ table.add_row(f"[cyan]{i}.[/cyan]", f"[green]{name}[/green]")
133
+ console.print(table)
134
+ if len(all_names) > 10:
135
+ console.print(f" [dim]... and {len(all_names) - 10} more[/dim]")
136
+
137
+ 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")
138
+ console.print(panel)
139
+
140
+ def install_clis(clis_names: list[str]):
141
+ from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
142
+ from machineconfig.utils.installer_utils.installer_runner import get_installers
143
+ from machineconfig.utils.installer_utils.installer_class import Installer
144
+ from rich.console import Console
145
+ total_messages: list[str] = []
146
+ for a_which in clis_names:
147
+ all_installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=None)
148
+ selected_installer = None
149
+ for installer in all_installers:
150
+ app_name = installer["appName"]
151
+ if app_name.lower() == a_which.lower():
152
+ selected_installer = installer
153
+ break
154
+ if selected_installer is None:
155
+ _handle_installer_not_found(a_which, all_names=[inst["appName"] for inst in all_installers])
156
+ return None
157
+ message = Installer(selected_installer).install_robust(version=None) # finish the task
158
+ total_messages.append(message)
159
+ if total_messages:
160
+ console = Console()
161
+ console.print("\n[bold green]📊 Installation Results:[/bold green]")
162
+ for a_message in total_messages:
163
+ console.print(f"[blue]• {a_message}[/blue]")
164
+ return None
165
+ def install_if_missing(which: str):
166
+ from machineconfig.utils.installer_utils.installer_locator_utils import check_tool_exists
167
+ exists = check_tool_exists(which)
168
+ if exists:
169
+ print(f"✅ {which} is already installed.")
170
+ return
171
+ print(f"⏳ {which} not found. Installing...")
172
+ from machineconfig.utils.installer_utils.installer_cli import main
173
+ main(which=which, interactive=False)
174
+
175
+
176
+ if __name__ == "__main__":
177
+ from machineconfig.utils.schemas.installer.installer_types import InstallerData
178
+ from machineconfig.utils.installer_utils.installer_class import Installer
179
+
180
+ _ = InstallerData, Installer
181
+ pass