machineconfig 5.15__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 (389) 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 +0 -1
  5. machineconfig/cluster/sessions_managers/{utils → helpers}/enhanced_command_runner.py +4 -6
  6. machineconfig/cluster/sessions_managers/utils/load_balancer.py +1 -1
  7. machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
  8. machineconfig/cluster/sessions_managers/wt_local.py +114 -289
  9. machineconfig/cluster/sessions_managers/wt_local_manager.py +50 -193
  10. machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
  11. machineconfig/cluster/sessions_managers/wt_remote_manager.py +49 -197
  12. machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
  13. machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
  14. machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
  15. machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +4 -2
  16. machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
  17. machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
  18. machineconfig/cluster/sessions_managers/zellij_local.py +81 -375
  19. machineconfig/cluster/sessions_managers/zellij_local_manager.py +22 -169
  20. machineconfig/cluster/sessions_managers/zellij_remote.py +40 -41
  21. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +13 -10
  22. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -8
  23. machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
  24. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -9
  25. machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -1
  26. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper.py +298 -0
  27. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_restart.py +77 -0
  28. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_with_panes.py +228 -0
  29. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_manager_helper.py +165 -0
  30. machineconfig/jobs/{python → installer}/check_installations.py +2 -3
  31. machineconfig/jobs/installer/custom/boxes.py +61 -0
  32. machineconfig/jobs/installer/custom/hx.py +76 -19
  33. machineconfig/jobs/installer/custom_dev/alacritty.py +4 -4
  34. machineconfig/jobs/installer/custom_dev/brave.py +1 -7
  35. machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
  36. machineconfig/jobs/installer/custom_dev/code.py +4 -1
  37. machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +30 -0
  38. machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +9 -18
  39. machineconfig/jobs/installer/custom_dev/sysabc.py +119 -0
  40. machineconfig/jobs/installer/custom_dev/wezterm.py +2 -19
  41. machineconfig/jobs/installer/installer_data.json +1101 -115
  42. machineconfig/jobs/installer/linux_scripts/brave.sh +4 -14
  43. machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +5 -17
  44. machineconfig/jobs/installer/linux_scripts/docker.sh +5 -17
  45. machineconfig/jobs/installer/linux_scripts/docker_start.sh +6 -14
  46. machineconfig/jobs/installer/linux_scripts/edge.sh +3 -11
  47. machineconfig/jobs/{linux/msc → installer/linux_scripts}/lid.sh +2 -8
  48. machineconfig/jobs/installer/linux_scripts/nerdfont.sh +5 -17
  49. machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +2 -8
  50. machineconfig/jobs/installer/linux_scripts/q.sh +1 -0
  51. machineconfig/jobs/installer/linux_scripts/redis.sh +6 -17
  52. machineconfig/jobs/installer/linux_scripts/vscode.sh +5 -17
  53. machineconfig/jobs/installer/linux_scripts/wezterm.sh +4 -12
  54. machineconfig/jobs/installer/package_groups.py +108 -180
  55. machineconfig/logger.py +0 -1
  56. machineconfig/profile/backup.toml +49 -0
  57. machineconfig/profile/bash_shell_profiles.md +11 -0
  58. machineconfig/profile/create_helper.py +74 -0
  59. machineconfig/profile/create_links.py +288 -0
  60. machineconfig/profile/create_links_export.py +100 -0
  61. machineconfig/profile/create_shell_profile.py +136 -0
  62. machineconfig/profile/mapper.toml +258 -0
  63. machineconfig/scripts/Restore-ThunderbirdProfile.ps1 +92 -0
  64. machineconfig/scripts/__init__.py +0 -4
  65. machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +14 -25
  66. machineconfig/scripts/linux/wrap_mcfg +47 -0
  67. machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
  68. machineconfig/scripts/python/agents.py +92 -103
  69. machineconfig/scripts/python/ai/command_runner/command_runner.sh +9 -0
  70. machineconfig/scripts/python/ai/command_runner/prompt.txt +9 -0
  71. machineconfig/scripts/python/ai/generate_files.py +307 -42
  72. machineconfig/scripts/python/ai/initai.py +3 -28
  73. machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +17 -18
  74. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +17 -18
  75. machineconfig/scripts/python/ai/solutions/_shared.py +9 -1
  76. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +1 -1
  77. machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
  78. machineconfig/scripts/python/ai/solutions/generic.py +27 -4
  79. machineconfig/scripts/python/ai/vscode_tasks.py +37 -0
  80. machineconfig/scripts/python/cloud.py +29 -0
  81. machineconfig/scripts/python/croshell.py +111 -114
  82. machineconfig/scripts/python/define.py +31 -0
  83. machineconfig/scripts/python/devops.py +44 -103
  84. machineconfig/scripts/python/devops_navigator.py +10 -0
  85. machineconfig/scripts/python/env_manager/__init__.py +1 -0
  86. machineconfig/scripts/python/env_manager/path_manager_backend.py +47 -0
  87. machineconfig/scripts/python/env_manager/path_manager_tui.py +228 -0
  88. machineconfig/scripts/python/explore.py +49 -0
  89. machineconfig/scripts/python/fire_jobs.py +115 -152
  90. machineconfig/scripts/python/ftpx.py +29 -24
  91. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +14 -0
  92. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +37 -0
  93. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_cursor_agents.py +22 -0
  94. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +42 -0
  95. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
  96. machineconfig/scripts/python/{fire_agents_help_launch.py → helpers_agents/fire_agents_help_launch.py} +34 -44
  97. machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +34 -0
  98. machineconfig/scripts/python/helpers_agents/templates/prompt.txt +6 -0
  99. machineconfig/scripts/python/helpers_agents/templates/template.ps1 +14 -0
  100. machineconfig/scripts/python/helpers_agents/templates/template.sh +24 -0
  101. machineconfig/scripts/python/{cloud_copy.py → helpers_cloud/cloud_copy.py} +30 -23
  102. machineconfig/scripts/python/{cloud_mount.py → helpers_cloud/cloud_mount.py} +10 -18
  103. machineconfig/scripts/python/{cloud_sync.py → helpers_cloud/cloud_sync.py} +12 -18
  104. machineconfig/scripts/python/{helpers → helpers_cloud}/helpers2.py +1 -1
  105. machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
  106. machineconfig/scripts/python/{start_slidev.py → helpers_croshell/start_slidev.py} +2 -2
  107. machineconfig/scripts/python/helpers_devops/cli_config.py +95 -0
  108. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
  109. machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
  110. machineconfig/scripts/python/helpers_devops/cli_nw.py +134 -0
  111. machineconfig/scripts/python/helpers_devops/cli_repos.py +182 -0
  112. machineconfig/scripts/python/helpers_devops/cli_self.py +134 -0
  113. machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
  114. machineconfig/scripts/python/helpers_devops/cli_share_server.py +141 -0
  115. machineconfig/scripts/python/{share_terminal.py → helpers_devops/cli_terminal.py} +35 -23
  116. machineconfig/scripts/python/helpers_devops/cli_utils.py +96 -0
  117. machineconfig/scripts/python/{devops_backup_retrieve.py → helpers_devops/devops_backup_retrieve.py} +7 -10
  118. machineconfig/scripts/python/helpers_devops/devops_status.py +511 -0
  119. machineconfig/scripts/python/{devops_update_repos.py → helpers_devops/devops_update_repos.py} +68 -49
  120. machineconfig/scripts/python/helpers_devops/themes/choose_pwsh_theme.ps1 +81 -0
  121. machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
  122. machineconfig/scripts/python/{choose_wezterm_theme.py → helpers_devops/themes/choose_wezterm_theme.py} +2 -2
  123. machineconfig/scripts/python/helpers_fire_command/__init__.py +0 -0
  124. machineconfig/scripts/python/{helpers/helpers4.py → helpers_fire_command/file_wrangler.py} +56 -20
  125. machineconfig/scripts/python/{fire_jobs_args_helper.py → helpers_fire_command/fire_jobs_args_helper.py} +5 -1
  126. machineconfig/scripts/python/{fire_jobs_route_helper.py → helpers_fire_command/fire_jobs_route_helper.py} +47 -2
  127. machineconfig/scripts/python/helpers_fire_command/fire_jobs_streamlit_helper.py +0 -0
  128. machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
  129. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfag +1 -1
  130. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +1 -1
  131. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfrga +1 -1
  132. machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
  133. machineconfig/scripts/python/helpers_navigator/command_builder.py +111 -0
  134. machineconfig/scripts/python/helpers_navigator/command_detail.py +44 -0
  135. machineconfig/scripts/python/helpers_navigator/command_tree.py +588 -0
  136. machineconfig/scripts/python/helpers_navigator/data_models.py +28 -0
  137. machineconfig/scripts/python/helpers_navigator/main_app.py +272 -0
  138. machineconfig/scripts/python/helpers_navigator/search_bar.py +15 -0
  139. machineconfig/scripts/python/helpers_repos/action.py +209 -0
  140. machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
  141. machineconfig/scripts/python/{repos_helper_clone.py → helpers_repos/clone.py} +2 -3
  142. machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +218 -0
  143. machineconfig/scripts/python/{count_lines.py → helpers_repos/count_lines.py} +10 -10
  144. machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +17 -0
  145. machineconfig/scripts/python/{repos_helper.py → helpers_repos/entrypoint.py} +9 -17
  146. machineconfig/scripts/python/helpers_repos/grource.py +340 -0
  147. machineconfig/scripts/python/{repos_helper_record.py → helpers_repos/record.py} +4 -3
  148. machineconfig/scripts/python/helpers_repos/sync.py +66 -0
  149. machineconfig/scripts/python/{repos_helper_update.py → helpers_repos/update.py} +3 -3
  150. machineconfig/scripts/python/helpers_sessions/__init__.py +0 -0
  151. machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +58 -0
  152. machineconfig/scripts/python/helpers_utils/download.py +152 -0
  153. machineconfig/scripts/python/helpers_utils/path.py +108 -0
  154. machineconfig/scripts/python/interactive.py +64 -84
  155. machineconfig/scripts/python/machineconfig.py +63 -0
  156. machineconfig/scripts/python/msearch.py +21 -0
  157. machineconfig/scripts/python/nw/__init__.py +0 -0
  158. machineconfig/scripts/python/{devops_add_identity.py → nw/devops_add_identity.py} +0 -2
  159. machineconfig/scripts/python/{devops_add_ssh_key.py → nw/devops_add_ssh_key.py} +73 -43
  160. machineconfig/scripts/{linux → python/nw}/mount_nfs +1 -1
  161. machineconfig/scripts/python/{mount_nfs.py → nw/mount_nfs.py} +3 -3
  162. machineconfig/scripts/{linux → python/nw}/mount_nw_drive +1 -2
  163. machineconfig/scripts/python/{mount_ssh.py → nw/mount_ssh.py} +3 -3
  164. machineconfig/scripts/python/{onetimeshare.py → nw/onetimeshare.py} +0 -1
  165. machineconfig/scripts/python/nw/ssh_debug_linux.py +391 -0
  166. machineconfig/scripts/python/nw/ssh_debug_windows.py +338 -0
  167. machineconfig/scripts/python/{wifi_conn.py → nw/wifi_conn.py} +1 -53
  168. machineconfig/scripts/python/{wsl_windows_transfer.py → nw/wsl_windows_transfer.py} +5 -4
  169. machineconfig/scripts/python/sessions.py +64 -44
  170. machineconfig/scripts/python/terminal.py +127 -0
  171. machineconfig/scripts/python/utils.py +66 -0
  172. machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +1 -3
  173. machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +1 -1
  174. machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -6
  175. machineconfig/scripts/windows/wrap_mcfg.ps1 +60 -0
  176. machineconfig/settings/broot/br.sh +0 -4
  177. machineconfig/settings/broot/conf.toml +1 -1
  178. machineconfig/settings/helix/config.toml +16 -0
  179. machineconfig/settings/helix/languages.toml +13 -4
  180. machineconfig/settings/helix/yazi-picker.sh +12 -0
  181. machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
  182. machineconfig/settings/lf/linux/exe/previewer.sh +9 -3
  183. machineconfig/settings/lf/linux/lfrc +10 -12
  184. machineconfig/settings/lf/windows/fzf_edit.ps1 +2 -2
  185. machineconfig/settings/lf/windows/lfrc +18 -38
  186. machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
  187. machineconfig/settings/linters/.ruff.toml +1 -1
  188. machineconfig/settings/lvim/windows/archive/config_additional.lua +0 -6
  189. machineconfig/settings/marimo/marimo.toml +80 -0
  190. machineconfig/settings/marimo/snippets/globalize.py +34 -0
  191. machineconfig/settings/pistol/pistol.conf +1 -1
  192. machineconfig/settings/shells/bash/init.sh +55 -31
  193. machineconfig/settings/shells/nushell/config.nu +1 -34
  194. machineconfig/settings/shells/nushell/init.nu +127 -0
  195. machineconfig/settings/shells/pwsh/init.ps1 +60 -43
  196. machineconfig/settings/shells/starship/starship.toml +16 -0
  197. machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
  198. machineconfig/settings/shells/wt/settings.json +32 -17
  199. machineconfig/settings/shells/zsh/init.sh +89 -0
  200. machineconfig/settings/svim/linux/init.toml +0 -4
  201. machineconfig/settings/svim/windows/init.toml +0 -3
  202. machineconfig/settings/yazi/init.lua +57 -0
  203. machineconfig/settings/yazi/keymap_linux.toml +79 -0
  204. machineconfig/settings/yazi/keymap_windows.toml +78 -0
  205. machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
  206. machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
  207. machineconfig/settings/yazi/yazi.toml +13 -0
  208. machineconfig/setup_linux/__init__.py +10 -0
  209. machineconfig/setup_linux/apps_desktop.sh +89 -0
  210. machineconfig/setup_linux/apps_gui.sh +64 -0
  211. machineconfig/setup_linux/{nix → others}/cli_installation.sh +9 -29
  212. machineconfig/setup_linux/ssh/openssh_all.sh +25 -0
  213. machineconfig/setup_linux/ssh/openssh_wsl.sh +38 -0
  214. machineconfig/setup_linux/uv.sh +15 -0
  215. machineconfig/setup_linux/web_shortcuts/interactive.sh +26 -6
  216. machineconfig/setup_mac/__init__.py +16 -0
  217. machineconfig/setup_mac/apps_gui.sh +248 -0
  218. machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
  219. machineconfig/setup_mac/uv.sh +36 -0
  220. machineconfig/setup_windows/__init__.py +8 -0
  221. machineconfig/setup_windows/others/power_options.ps1 +7 -0
  222. machineconfig/setup_windows/ssh/add-sshkey.ps1 +29 -0
  223. machineconfig/setup_windows/ssh/add_identity.ps1 +11 -0
  224. machineconfig/setup_windows/ssh/openssh-server.ps1 +37 -0
  225. machineconfig/setup_windows/uv.ps1 +10 -0
  226. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +27 -10
  227. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +16 -0
  228. machineconfig/utils/accessories.py +7 -5
  229. machineconfig/utils/cloud/onedrive/README.md +139 -0
  230. machineconfig/utils/code.py +133 -106
  231. machineconfig/utils/files/art/fat_croco.txt +10 -0
  232. machineconfig/utils/files/art/halfwit_croco.txt +9 -0
  233. machineconfig/utils/files/art/happy_croco.txt +22 -0
  234. machineconfig/utils/files/art/water_croco.txt +11 -0
  235. machineconfig/utils/files/ascii_art.py +1 -1
  236. machineconfig/utils/files/dbms.py +257 -0
  237. machineconfig/utils/files/headers.py +11 -14
  238. machineconfig/utils/files/ouch/__init__.py +0 -0
  239. machineconfig/utils/files/ouch/decompress.py +45 -0
  240. machineconfig/utils/files/read.py +10 -18
  241. machineconfig/utils/installer_utils/installer_class.py +68 -126
  242. machineconfig/utils/installer_utils/{installer.py → installer_cli.py} +109 -117
  243. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +31 -81
  244. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +44 -74
  245. machineconfig/utils/io.py +77 -23
  246. machineconfig/utils/links.py +254 -162
  247. machineconfig/utils/meta.py +255 -0
  248. machineconfig/utils/notifications.py +1 -1
  249. machineconfig/utils/options.py +13 -3
  250. machineconfig/utils/path_extended.py +46 -100
  251. machineconfig/utils/path_helper.py +75 -22
  252. machineconfig/utils/procs.py +50 -70
  253. machineconfig/utils/scheduler.py +94 -97
  254. machineconfig/utils/scheduling.py +0 -3
  255. machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
  256. machineconfig/utils/schemas/layouts/layout_types.py +1 -1
  257. machineconfig/utils/source_of_truth.py +3 -6
  258. machineconfig/utils/ssh.py +742 -264
  259. machineconfig/utils/ssh_utils/utils.py +0 -0
  260. machineconfig/utils/terminal.py +2 -113
  261. machineconfig/utils/tst.py +20 -0
  262. machineconfig/utils/upgrade_packages.py +109 -28
  263. machineconfig/utils/ve.py +11 -4
  264. machineconfig-7.66.dist-info/METADATA +124 -0
  265. machineconfig-7.66.dist-info/RECORD +451 -0
  266. machineconfig-7.66.dist-info/entry_points.txt +15 -0
  267. machineconfig/cluster/sessions_managers/ffile.py +0 -4
  268. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -49
  269. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -85
  270. machineconfig/jobs/linux/msc/cli_agents.sh +0 -16
  271. machineconfig/jobs/python/python_ve_symlink.py +0 -37
  272. machineconfig/jobs/python/vscode/api.py +0 -57
  273. machineconfig/jobs/python/vscode/sync_code.py +0 -73
  274. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -14
  275. machineconfig/jobs/windows/start_terminal.ps1 +0 -6
  276. machineconfig/jobs/windows/startup_file.cmd +0 -2
  277. machineconfig/profile/create.py +0 -303
  278. machineconfig/profile/shell.py +0 -176
  279. machineconfig/scripts/cloud/init.sh +0 -119
  280. machineconfig/scripts/linux/agents +0 -2
  281. machineconfig/scripts/linux/choose_wezterm_theme +0 -3
  282. machineconfig/scripts/linux/cloud_copy +0 -2
  283. machineconfig/scripts/linux/cloud_mount +0 -2
  284. machineconfig/scripts/linux/cloud_repo_sync +0 -2
  285. machineconfig/scripts/linux/cloud_sync +0 -2
  286. machineconfig/scripts/linux/croshell +0 -3
  287. machineconfig/scripts/linux/devops +0 -2
  288. machineconfig/scripts/linux/fire +0 -2
  289. machineconfig/scripts/linux/ftpx +0 -2
  290. machineconfig/scripts/linux/fzf2g +0 -21
  291. machineconfig/scripts/linux/fzffg +0 -25
  292. machineconfig/scripts/linux/gh_models +0 -2
  293. machineconfig/scripts/linux/initai +0 -2
  294. machineconfig/scripts/linux/kill_process +0 -2
  295. machineconfig/scripts/linux/scheduler +0 -2
  296. machineconfig/scripts/linux/sessions +0 -2
  297. machineconfig/scripts/linux/share_smb +0 -1
  298. machineconfig/scripts/linux/start_slidev +0 -2
  299. machineconfig/scripts/linux/start_terminals +0 -3
  300. machineconfig/scripts/linux/warp-cli.sh +0 -122
  301. machineconfig/scripts/linux/wifi_conn +0 -2
  302. machineconfig/scripts/linux/z_ls +0 -104
  303. machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
  304. machineconfig/scripts/python/cloud_repo_sync.py +0 -190
  305. machineconfig/scripts/python/count_lines_frontend.py +0 -16
  306. machineconfig/scripts/python/dotfile.py +0 -78
  307. machineconfig/scripts/python/fire_agents_helper_types.py +0 -12
  308. machineconfig/scripts/python/get_zellij_cmd.py +0 -15
  309. machineconfig/scripts/python/gh_models.py +0 -104
  310. machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -116
  311. machineconfig/scripts/python/repos.py +0 -132
  312. machineconfig/scripts/python/repos_helper_action.py +0 -378
  313. machineconfig/scripts/python/snapshot.py +0 -25
  314. machineconfig/scripts/python/start_terminals.py +0 -121
  315. machineconfig/scripts/python/t4.py +0 -17
  316. machineconfig/scripts/windows/agents.ps1 +0 -1
  317. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
  318. machineconfig/scripts/windows/cloud_copy.ps1 +0 -1
  319. machineconfig/scripts/windows/cloud_mount.ps1 +0 -1
  320. machineconfig/scripts/windows/cloud_repo_sync.ps1 +0 -1
  321. machineconfig/scripts/windows/cloud_sync.ps1 +0 -1
  322. machineconfig/scripts/windows/croshell.ps1 +0 -1
  323. machineconfig/scripts/windows/devops.ps1 +0 -1
  324. machineconfig/scripts/windows/dotfile.ps1 +0 -1
  325. machineconfig/scripts/windows/fire.ps1 +0 -1
  326. machineconfig/scripts/windows/ftpx.ps1 +0 -1
  327. machineconfig/scripts/windows/gpt.ps1 +0 -1
  328. machineconfig/scripts/windows/grep.ps1 +0 -2
  329. machineconfig/scripts/windows/initai.ps1 +0 -1
  330. machineconfig/scripts/windows/kill_process.ps1 +0 -1
  331. machineconfig/scripts/windows/nano.ps1 +0 -3
  332. machineconfig/scripts/windows/pomodoro.ps1 +0 -1
  333. machineconfig/scripts/windows/reload_path.ps1 +0 -3
  334. machineconfig/scripts/windows/scheduler.ps1 +0 -1
  335. machineconfig/scripts/windows/sessions.ps1 +0 -1
  336. machineconfig/scripts/windows/snapshot.ps1 +0 -1
  337. machineconfig/scripts/windows/start_slidev.ps1 +0 -1
  338. machineconfig/scripts/windows/start_terminals.ps1 +0 -1
  339. machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
  340. machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
  341. machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
  342. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  343. machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +0 -57
  344. machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -11
  345. machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -52
  346. machineconfig/setup_windows/web_shortcuts/all.ps1 +0 -18
  347. machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +0 -36
  348. machineconfig/setup_windows/web_shortcuts/croshell.ps1 +0 -16
  349. machineconfig/setup_windows/web_shortcuts/ssh.ps1 +0 -11
  350. machineconfig/utils/ai/generate_file_checklist.py +0 -68
  351. machineconfig-5.15.dist-info/METADATA +0 -188
  352. machineconfig-5.15.dist-info/RECORD +0 -415
  353. machineconfig-5.15.dist-info/entry_points.txt +0 -18
  354. machineconfig/cluster/sessions_managers/{utils → helpers}/load_balancer_helper.py +0 -0
  355. machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
  356. machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
  357. machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
  358. machineconfig/{jobs/python → scripts/python/helpers_agents}/__init__.py +0 -0
  359. machineconfig/scripts/python/{helpers → helpers_agents/agentic_frameworks}/__init__.py +0 -0
  360. machineconfig/scripts/python/{fire_agents_help_search.py → helpers_agents/fire_agents_help_search.py} +0 -0
  361. machineconfig/scripts/python/{fire_agents_load_balancer.py → helpers_agents/fire_agents_load_balancer.py} +0 -0
  362. machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_cloud/__init__.py} +0 -0
  363. machineconfig/scripts/python/{helpers → helpers_cloud}/cloud_helpers.py +1 -1
  364. /machineconfig/scripts/python/{helpers → helpers_cloud}/helpers5.py +0 -0
  365. /machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_croshell/__init__.py} +0 -0
  366. /machineconfig/scripts/python/{pomodoro.py → helpers_croshell/pomodoro.py} +0 -0
  367. /machineconfig/scripts/python/{scheduler.py → helpers_croshell/scheduler.py} +0 -0
  368. /machineconfig/scripts/python/{viewer.py → helpers_croshell/viewer.py} +0 -0
  369. /machineconfig/scripts/python/{viewer_template.py → helpers_croshell/viewer_template.py} +0 -0
  370. /machineconfig/scripts/python/{fire_jobs_streamlit_helper.py → helpers_devops/__init__.py} +0 -0
  371. /machineconfig/scripts/{windows/share_nfs.ps1 → python/helpers_devops/themes/__init__.py} +0 -0
  372. /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
  373. /machineconfig/scripts/python/{cloud_manager.py → helpers_fire_command/cloud_manager.py} +0 -0
  374. /machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/skrg +0 -0
  375. /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfb.ps1 +0 -0
  376. /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfg.ps1 +0 -0
  377. /machineconfig/scripts/{windows → python/helpers_msearch/scripts_windows}/fzfrga.bat +0 -0
  378. /machineconfig/scripts/{linux → python/nw}/mount_drive +0 -0
  379. /machineconfig/scripts/python/{mount_nw_drive.py → nw/mount_nw_drive.py} +0 -0
  380. /machineconfig/scripts/{linux → python/nw}/mount_smb +0 -0
  381. /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
  382. /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
  383. /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
  384. /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
  385. /machineconfig/setup_linux/{web_shortcuts → others}/android.sh +0 -0
  386. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
  387. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
  388. {machineconfig-5.15.dist-info → machineconfig-7.66.dist-info}/WHEEL +0 -0
  389. {machineconfig-5.15.dist-info → machineconfig-7.66.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,45 @@
1
+
2
+
3
+ from pathlib import Path
4
+ from zipfile import ZipFile, BadZipFile
5
+ from typing import Union
6
+
7
+
8
+ def decompress_and_remove_zip(zip_path: Union[str, Path]) -> None:
9
+ """
10
+ Decompress a ZIP file and remove it after extraction.
11
+
12
+ Args:
13
+ zip_path (Union[str, Path]): Path to the ZIP file.
14
+
15
+ Raises:
16
+ FileNotFoundError: If the zip file does not exist.
17
+ BadZipFile: If the file is not a valid ZIP archive.
18
+ PermissionError: If the file cannot be deleted due to permission issues.
19
+ Exception: For other unexpected errors.
20
+ """
21
+ zip_path = Path(zip_path)
22
+
23
+ if not zip_path.exists():
24
+ raise FileNotFoundError(f"The file '{zip_path}' does not exist.")
25
+
26
+ if not zip_path.is_file():
27
+ raise FileNotFoundError(f"The path '{zip_path}' is not a file.")
28
+
29
+ extract_dir = zip_path.parent
30
+
31
+ try:
32
+ with ZipFile(zip_path, 'r') as zip_ref:
33
+ zip_ref.extractall(extract_dir)
34
+ except BadZipFile as e:
35
+ raise BadZipFile(f"The file '{zip_path}' is not a valid zip archive.") from e
36
+ except Exception as e:
37
+ raise Exception(f"Failed to extract '{zip_path}': {e}") from e
38
+
39
+ try:
40
+ zip_path.unlink()
41
+ except PermissionError as e:
42
+ raise PermissionError(f"Permission denied when deleting '{zip_path}'.") from e
43
+ except Exception as e:
44
+ raise Exception(f"Failed to delete '{zip_path}': {e}") from e
45
+
@@ -12,18 +12,16 @@ class Read:
12
12
  suffix = Path(path).suffix[1:]
13
13
  if suffix == "": raise ValueError(f"File type could not be inferred from suffix. Suffix is empty. Path: {path}")
14
14
  if suffix in ("sqlite", "sqlite3", "db", "duckdb"):
15
- # from crocodile.database import DBMS
16
- # if suffix == "duckdb": pass
17
- # res = DBMS.from_local_db(path=path)
18
- # print(res.describe_db())
19
- # return res
20
- raise NotImplementedError("Reading database files is not implemented yet. Use `crocodile.database.DBMS` to connect to the database file.")
15
+ from machineconfig.utils.files.dbms import DBMS
16
+ res = DBMS.from_local_db(path=path)
17
+ print(res.describe_db())
18
+ return res
21
19
  try: return getattr(Read, suffix)(str(path), **kwargs)
22
20
  except AttributeError as err:
23
21
  if "type object 'Read' has no attribute" not in str(err): raise AttributeError(err) from err
24
22
  if suffix in ('eps', 'jpg', 'jpeg', 'pdf', 'pgf', 'png', 'ps', 'raw', 'rgba', 'svg', 'svgz', 'tif', 'tiff'):
25
23
  import matplotlib.pyplot as pyplot
26
- return pyplot.imread(path, **kwargs) # from: plt.gcf().canvas.get_supported_filetypes().keys():
24
+ return pyplot.imread(str(path), **kwargs) # from: plt.gcf().canvas.get_supported_filetypes().keys():
27
25
  if suffix == "parquet":
28
26
  import polars as pl
29
27
  return pl.read_parquet(path, **kwargs)
@@ -39,17 +37,11 @@ class Read:
39
37
  raise ImportError(err) from err2
40
38
  @staticmethod
41
39
  def json(path: 'Path', r: bool = False, **kwargs: Any) -> Any: # return could be list or dict etc
42
- import json
43
- try:
44
- mydict = json.loads(Path(path).read_text(encoding='utf-8'), **kwargs)
45
- except Exception:
46
- import pyjson5
47
- mydict = pyjson5.loads(Path(path).read_text(encoding='utf-8'), **kwargs) # file has C-style comments.
48
- _ = r
49
- return mydict
40
+ from machineconfig.utils.io import read_json
41
+ return read_json(path, r=r, **kwargs)
50
42
  @staticmethod
51
43
  def yaml(path: 'Path', r: bool = False) -> Any: # return could be list or dict etc
52
- import yaml # type: ignore
44
+ import yaml
53
45
  with open(str(path), "r", encoding="utf-8") as file:
54
46
  mydict = yaml.load(file, Loader=yaml.FullLoader)
55
47
  _ = r
@@ -63,8 +55,8 @@ class Read:
63
55
  return res
64
56
  @staticmethod
65
57
  def toml(path: 'Path'):
66
- import toml
67
- return toml.loads(Path(path).read_text(encoding='utf-8'))
58
+ import tomllib
59
+ return tomllib.loads(Path(path).read_text(encoding='utf-8'))
68
60
  @staticmethod
69
61
  def npy(path: 'Path', **kwargs: Any):
70
62
  import numpy as np
@@ -1,18 +1,33 @@
1
- from machineconfig.utils.path_extended import PathExtended
2
- from machineconfig.utils.installer_utils.installer_abc import find_move_delete_linux, find_move_delete_windows
3
- from machineconfig.utils.source_of_truth import INSTALL_TMP_DIR, INSTALL_VERSION_ROOT, 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