machineconfig 3.7__py3-none-any.whl → 7.69__py3-none-any.whl

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

Potentially problematic release.


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

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