machineconfig 6.23__py3-none-any.whl → 8.12__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 (402) hide show
  1. machineconfig/cluster/remote/cloud_manager.py +1 -1
  2. machineconfig/cluster/remote/distribute.py +0 -1
  3. machineconfig/cluster/remote/file_manager.py +0 -2
  4. machineconfig/cluster/sessions_managers/{utils → helpers}/enhanced_command_runner.py +4 -6
  5. machineconfig/cluster/sessions_managers/utils/load_balancer.py +1 -1
  6. machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
  7. machineconfig/cluster/sessions_managers/wt_local.py +16 -221
  8. machineconfig/cluster/sessions_managers/wt_local_manager.py +55 -193
  9. machineconfig/cluster/sessions_managers/wt_remote_manager.py +42 -198
  10. machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
  11. machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
  12. machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
  13. machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
  14. machineconfig/cluster/sessions_managers/zellij_local.py +3 -3
  15. machineconfig/cluster/sessions_managers/zellij_local_manager.py +5 -3
  16. machineconfig/cluster/sessions_managers/zellij_remote.py +2 -2
  17. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +3 -2
  18. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +2 -2
  19. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -7
  20. machineconfig/cluster/sessions_managers/{helpers → zellij_utils}/zellij_local_helper_with_panes.py +1 -1
  21. machineconfig/jobs/installer/check_installations.py +0 -1
  22. machineconfig/jobs/installer/installer_data.json +1408 -201
  23. machineconfig/jobs/installer/linux_scripts/q.sh +10 -7
  24. machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
  25. machineconfig/jobs/installer/package_groups.py +63 -92
  26. machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
  27. machineconfig/jobs/installer/python_scripts/boxes.py +61 -0
  28. machineconfig/jobs/installer/{custom_dev → python_scripts}/brave.py +5 -3
  29. machineconfig/jobs/installer/python_scripts/cloudflare_warp_cli.py +23 -0
  30. machineconfig/jobs/installer/{custom_dev → python_scripts}/code.py +4 -1
  31. machineconfig/jobs/installer/{custom_dev → python_scripts}/dubdb_adbc.py +1 -1
  32. machineconfig/jobs/installer/{custom → python_scripts}/hx.py +75 -18
  33. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerdfont.py +2 -2
  34. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerfont_windows_helper.py +27 -22
  35. machineconfig/jobs/installer/python_scripts/sysabc.py +139 -0
  36. machineconfig/jobs/installer/{custom_dev → python_scripts}/wezterm.py +2 -19
  37. machineconfig/jobs/installer/{custom_dev → python_scripts}/winget.py +10 -14
  38. machineconfig/jobs/installer/python_scripts/yazi.py +121 -0
  39. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nfs +0 -1
  40. machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +13 -0
  41. machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +4 -0
  42. machineconfig/jobs/scripts_dynamic/a.py +25 -0
  43. machineconfig/logger.py +0 -1
  44. machineconfig/profile/create_helper.py +56 -18
  45. machineconfig/profile/create_links.py +2 -1
  46. machineconfig/profile/create_links_export.py +64 -18
  47. machineconfig/profile/create_shell_profile.py +90 -132
  48. machineconfig/profile/mapper.toml +18 -8
  49. machineconfig/scripts/__init__.py +0 -4
  50. machineconfig/scripts/linux/wrap_mcfg +46 -0
  51. machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
  52. machineconfig/scripts/python/agents.py +82 -60
  53. machineconfig/scripts/python/ai/initai.py +1 -19
  54. machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
  55. machineconfig/scripts/python/ai/{command_runner → scripts}/command_runner.sh +1 -1
  56. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +1 -1
  57. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
  58. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
  59. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
  60. machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +5 -5
  61. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +4 -0
  62. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
  63. machineconfig/scripts/python/ai/solutions/generic.py +1 -1
  64. machineconfig/scripts/python/ai/{generate_files.py → utils/generate_files.py} +2 -2
  65. machineconfig/scripts/python/ai/{vscode_tasks.py → utils/vscode_tasks.py} +7 -2
  66. machineconfig/scripts/python/cloud.py +14 -9
  67. machineconfig/scripts/python/croshell.py +135 -117
  68. machineconfig/scripts/python/devops.py +48 -25
  69. machineconfig/scripts/python/devops_navigator.py +1 -5
  70. machineconfig/scripts/python/env_manager/env_manager_tui.py +204 -0
  71. machineconfig/scripts/python/env_manager/path_manager_tui.py +18 -9
  72. machineconfig/scripts/python/fire_jobs.py +127 -118
  73. machineconfig/scripts/python/ftpx.py +44 -17
  74. machineconfig/scripts/python/helpers/ast_search.py +74 -0
  75. machineconfig/scripts/python/helpers/qr_code.py +166 -0
  76. machineconfig/scripts/python/helpers/repo_rag.py +325 -0
  77. machineconfig/scripts/python/helpers/symantic_search.py +25 -0
  78. machineconfig/scripts/python/{helpers_fire → helpers_agents}/agentic_frameworks/fire_crush.json +1 -1
  79. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
  80. machineconfig/scripts/python/{helpers_fire → helpers_agents}/agentic_frameworks/fire_cursor_agents.py +3 -4
  81. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
  82. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
  83. machineconfig/scripts/python/{helpers_fire → helpers_agents}/fire_agents_help_launch.py +37 -15
  84. machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +41 -0
  85. machineconfig/scripts/python/helpers_agents/privacy/configs/aichat/config.yaml +5 -0
  86. machineconfig/scripts/python/helpers_agents/privacy/configs/aider/.aider.conf.yml +2 -0
  87. machineconfig/scripts/python/helpers_agents/privacy/configs/copilot/config.yml +1 -0
  88. machineconfig/scripts/python/helpers_agents/privacy/configs/crush/crush.json +10 -0
  89. machineconfig/scripts/python/helpers_agents/privacy/configs/gemini/settings.json +12 -0
  90. machineconfig/scripts/python/helpers_agents/privacy/privacy.py +109 -0
  91. machineconfig/scripts/python/helpers_agents/templates/prompt.txt +10 -0
  92. machineconfig/scripts/python/helpers_agents/templates/template.sh +34 -0
  93. machineconfig/scripts/python/{cloud_helpers → helpers_cloud}/cloud_copy.py +28 -21
  94. machineconfig/scripts/python/{cloud_helpers → helpers_cloud}/cloud_mount.py +19 -17
  95. machineconfig/scripts/python/{cloud_helpers → helpers_cloud}/cloud_sync.py +12 -11
  96. machineconfig/scripts/python/{cloud_helpers → helpers_cloud}/helpers2.py +1 -1
  97. machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
  98. machineconfig/scripts/python/{croshell_helpers → helpers_croshell}/start_slidev.py +6 -7
  99. machineconfig/scripts/python/helpers_devops/cli_config.py +105 -0
  100. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
  101. machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
  102. machineconfig/scripts/python/helpers_devops/cli_nw.py +221 -0
  103. machineconfig/scripts/python/{devops_helpers → helpers_devops}/cli_repos.py +60 -36
  104. machineconfig/scripts/python/helpers_devops/cli_self.py +172 -0
  105. machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
  106. machineconfig/scripts/python/helpers_devops/cli_share_server.py +142 -0
  107. machineconfig/scripts/python/{devops_helpers/cli_terminal.py → helpers_devops/cli_share_terminal.py} +15 -17
  108. machineconfig/scripts/python/{devops_helpers → helpers_devops}/devops_backup_retrieve.py +7 -10
  109. machineconfig/scripts/python/{devops_helpers → helpers_devops}/devops_status.py +7 -19
  110. machineconfig/scripts/python/{devops_helpers → helpers_devops}/devops_update_repos.py +1 -1
  111. machineconfig/scripts/python/helpers_devops/run_script.py +168 -0
  112. machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
  113. machineconfig/scripts/python/{devops_helpers → helpers_devops}/themes/choose_wezterm_theme.py +1 -1
  114. machineconfig/scripts/python/{helpers_fire/helpers4.py → helpers_fire_command/file_wrangler.py} +57 -20
  115. machineconfig/scripts/python/helpers_fire_command/fire_jobs_args_helper.py +2 -0
  116. machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +26 -16
  117. machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
  118. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +3 -3
  119. machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
  120. machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
  121. machineconfig/scripts/python/{helper_navigator → helpers_navigator}/command_builder.py +1 -1
  122. machineconfig/scripts/python/{helper_navigator → helpers_navigator}/command_detail.py +1 -1
  123. machineconfig/scripts/python/{helper_navigator → helpers_navigator}/command_tree.py +160 -23
  124. machineconfig/scripts/python/{helper_navigator → helpers_navigator}/main_app.py +5 -5
  125. machineconfig/scripts/python/helpers_network/address.py +176 -0
  126. machineconfig/scripts/python/helpers_network/address_switch.py +78 -0
  127. machineconfig/scripts/python/{nw → helpers_network}/mount_nfs.py +2 -2
  128. machineconfig/scripts/python/{nw → helpers_network}/mount_ssh.py +1 -1
  129. machineconfig/scripts/python/{nw/devops_add_identity.py → helpers_network/ssh_add_identity.py} +35 -1
  130. machineconfig/scripts/python/{nw/devops_add_ssh_key.py → helpers_network/ssh_add_ssh_key.py} +26 -7
  131. machineconfig/scripts/python/{nw → helpers_network}/ssh_debug_linux.py +7 -7
  132. machineconfig/scripts/python/{nw → helpers_network}/ssh_debug_windows.py +4 -4
  133. machineconfig/scripts/python/{nw → helpers_network}/wifi_conn.py +1 -53
  134. machineconfig/scripts/python/helpers_repos/action.py +209 -0
  135. machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
  136. machineconfig/scripts/python/{repos_helpers → helpers_repos}/clone.py +0 -1
  137. machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +80 -37
  138. machineconfig/scripts/python/{repos_helpers → helpers_repos}/entrypoint.py +5 -5
  139. machineconfig/scripts/python/helpers_repos/grource.py +2 -2
  140. machineconfig/scripts/python/{repos_helpers → helpers_repos}/record.py +3 -2
  141. machineconfig/scripts/python/helpers_repos/repo_analyzer_1.py +160 -0
  142. machineconfig/scripts/python/{repos_helpers/count_lines.py → helpers_repos/repo_analyzer_2.py} +113 -192
  143. machineconfig/scripts/python/{repos_helpers → helpers_repos}/sync.py +5 -5
  144. machineconfig/scripts/python/{sessions_helpers → helpers_sessions}/sessions_multiprocess.py +19 -13
  145. machineconfig/scripts/python/helpers_utils/download.py +150 -0
  146. machineconfig/scripts/python/helpers_utils/pdf.py +96 -0
  147. machineconfig/scripts/python/helpers_utils/python.py +187 -0
  148. machineconfig/scripts/python/interactive.py +26 -35
  149. machineconfig/scripts/python/{entry.py → mcfg_entry.py} +24 -10
  150. machineconfig/scripts/python/msearch.py +72 -0
  151. machineconfig/scripts/python/sessions.py +101 -38
  152. machineconfig/scripts/python/terminal.py +136 -0
  153. machineconfig/scripts/python/utils.py +62 -0
  154. machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
  155. machineconfig/settings/broot/conf.toml +1 -1
  156. machineconfig/settings/helix/config.toml +16 -0
  157. machineconfig/settings/helix/languages.toml +13 -4
  158. machineconfig/settings/helix/yazi-picker.sh +12 -0
  159. machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
  160. machineconfig/settings/lf/linux/exe/previewer.sh +3 -2
  161. machineconfig/settings/lf/linux/lfrc +10 -11
  162. machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
  163. machineconfig/settings/lf/windows/lfrc +15 -17
  164. machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
  165. machineconfig/settings/linters/.ruff.toml +1 -1
  166. machineconfig/settings/marimo/marimo.toml +80 -0
  167. machineconfig/settings/marimo/snippets/globalize.py +34 -0
  168. machineconfig/settings/shells/bash/init.sh +57 -10
  169. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
  170. machineconfig/settings/shells/nushell/config.nu +2 -35
  171. machineconfig/settings/shells/nushell/env.nu +45 -6
  172. machineconfig/settings/shells/nushell/init.nu +314 -0
  173. machineconfig/settings/shells/pwsh/init.ps1 +59 -23
  174. machineconfig/settings/shells/starship/starship.toml +16 -0
  175. machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
  176. machineconfig/settings/shells/wt/settings.json +32 -17
  177. machineconfig/settings/shells/zsh/init.sh +89 -0
  178. machineconfig/settings/television/cable_unix/alias.toml +8 -0
  179. machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
  180. machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
  181. machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
  182. machineconfig/settings/television/cable_unix/channels.toml +19 -0
  183. machineconfig/settings/television/cable_unix/dirs.toml +13 -0
  184. machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
  185. machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
  186. machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
  187. machineconfig/settings/television/cable_unix/env.toml +17 -0
  188. machineconfig/settings/television/cable_unix/files.toml +11 -0
  189. machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
  190. machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
  191. machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
  192. machineconfig/settings/television/cable_unix/git-log.toml +12 -0
  193. machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
  194. machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
  195. machineconfig/settings/television/cable_unix/guix.toml +20 -0
  196. machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
  197. machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
  198. machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
  199. machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
  200. machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
  201. machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
  202. machineconfig/settings/television/cable_unix/procs.toml +20 -0
  203. machineconfig/settings/television/cable_unix/text.toml +17 -0
  204. machineconfig/settings/television/cable_unix/tldr.toml +18 -0
  205. machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
  206. machineconfig/settings/television/cable_windows/alias.toml +7 -0
  207. machineconfig/settings/television/cable_windows/dirs.toml +13 -0
  208. machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
  209. machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
  210. machineconfig/settings/television/cable_windows/env.toml +17 -0
  211. machineconfig/settings/television/cable_windows/files.toml +14 -0
  212. machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
  213. machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
  214. machineconfig/settings/television/cable_windows/git-log.toml +11 -0
  215. machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
  216. machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
  217. machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
  218. machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
  219. machineconfig/settings/television/cable_windows/text.toml +17 -0
  220. machineconfig/settings/yazi/init.lua +61 -0
  221. machineconfig/settings/yazi/keymap_linux.toml +94 -0
  222. machineconfig/settings/yazi/keymap_windows.toml +78 -0
  223. machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
  224. machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
  225. machineconfig/settings/yazi/theme.toml +4 -0
  226. machineconfig/settings/yazi/yazi_linux.toml +84 -0
  227. machineconfig/settings/yazi/yazi_windows.toml +58 -0
  228. machineconfig/settings/zellij/layouts/st.kdl +39 -8
  229. machineconfig/setup_linux/__init__.py +2 -2
  230. machineconfig/setup_linux/apps_desktop.sh +8 -27
  231. machineconfig/setup_linux/web_shortcuts/interactive.sh +27 -11
  232. machineconfig/setup_linux/web_shortcuts/live_from_github.sh +31 -0
  233. machineconfig/setup_mac/__init__.py +16 -0
  234. machineconfig/setup_mac/apps_gui.sh +248 -0
  235. machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
  236. machineconfig/setup_mac/uv.sh +36 -0
  237. machineconfig/setup_windows/__init__.py +3 -5
  238. machineconfig/setup_windows/ssh/openssh-server.ps1 +1 -1
  239. machineconfig/setup_windows/uv.ps1 +8 -1
  240. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +26 -10
  241. machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +30 -0
  242. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
  243. machineconfig/utils/accessories.py +7 -5
  244. machineconfig/utils/code.py +143 -167
  245. machineconfig/utils/files/art/fat_croco.txt +10 -0
  246. machineconfig/utils/files/art/halfwit_croco.txt +9 -0
  247. machineconfig/utils/files/art/happy_croco.txt +22 -0
  248. machineconfig/utils/files/art/water_croco.txt +11 -0
  249. machineconfig/utils/files/ascii_art.py +1 -1
  250. machineconfig/utils/files/headers.py +6 -11
  251. machineconfig/utils/files/read.py +3 -9
  252. machineconfig/utils/installer_utils/github_release_bulk.py +156 -119
  253. machineconfig/utils/installer_utils/install_from_url.py +183 -0
  254. machineconfig/utils/installer_utils/installer_class.py +44 -101
  255. machineconfig/utils/installer_utils/installer_cli.py +175 -0
  256. machineconfig/utils/installer_utils/installer_helper.py +129 -0
  257. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +39 -87
  258. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +17 -63
  259. machineconfig/utils/io.py +77 -4
  260. machineconfig/utils/links.py +56 -38
  261. machineconfig/utils/meta.py +235 -145
  262. machineconfig/utils/options.py +46 -18
  263. machineconfig/utils/options_tv.py +119 -0
  264. machineconfig/utils/path_extended.py +46 -97
  265. machineconfig/utils/path_helper.py +76 -23
  266. machineconfig/utils/procs.py +10 -23
  267. machineconfig/utils/scheduler.py +84 -115
  268. machineconfig/utils/scheduling.py +0 -3
  269. machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
  270. machineconfig/utils/schemas/layouts/layout_types.py +1 -1
  271. machineconfig/utils/ssh.py +214 -476
  272. machineconfig/utils/ssh_utils/abc.py +5 -0
  273. machineconfig/utils/ssh_utils/copy_from_here.py +111 -0
  274. machineconfig/utils/ssh_utils/copy_to_here.py +303 -0
  275. machineconfig/utils/ssh_utils/utils.py +142 -0
  276. machineconfig/utils/ssh_utils/wsl.py +210 -0
  277. machineconfig/utils/terminal.py +3 -113
  278. machineconfig/utils/upgrade_packages.py +114 -28
  279. machineconfig/utils/ve.py +12 -4
  280. machineconfig-8.12.dist-info/METADATA +132 -0
  281. machineconfig-8.12.dist-info/RECORD +504 -0
  282. {machineconfig-6.23.dist-info → machineconfig-8.12.dist-info}/entry_points.txt +5 -1
  283. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
  284. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
  285. machineconfig/jobs/linux/msc/cli_agents.sh +0 -16
  286. machineconfig/jobs/python/python_ve_symlink.py +0 -37
  287. machineconfig/jobs/python/vscode/api.py +0 -57
  288. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -12
  289. machineconfig/jobs/windows/archive/openssh-server_add_key.ps1 +0 -7
  290. machineconfig/jobs/windows/archive/openssh-server_copy-ssh-id.ps1 +0 -14
  291. machineconfig/scripts/linux/fzf2g +0 -21
  292. machineconfig/scripts/linux/fzfag +0 -17
  293. machineconfig/scripts/linux/fzffg +0 -25
  294. machineconfig/scripts/linux/fzfrga +0 -21
  295. machineconfig/scripts/linux/other/share_smb +0 -1
  296. machineconfig/scripts/linux/other/switch_ip +0 -20
  297. machineconfig/scripts/linux/skrg +0 -4
  298. machineconfig/scripts/linux/warp-cli.sh +0 -122
  299. machineconfig/scripts/linux/z_ls +0 -104
  300. machineconfig/scripts/python/ai/command_runner/prompt.txt +0 -9
  301. machineconfig/scripts/python/devops_helpers/cli_config.py +0 -81
  302. machineconfig/scripts/python/devops_helpers/cli_config_dotfile.py +0 -84
  303. machineconfig/scripts/python/devops_helpers/cli_data.py +0 -18
  304. machineconfig/scripts/python/devops_helpers/cli_nw.py +0 -73
  305. machineconfig/scripts/python/devops_helpers/cli_self.py +0 -117
  306. machineconfig/scripts/python/devops_helpers/cli_share_server.py +0 -104
  307. machineconfig/scripts/python/helper_navigator/__init__.py +0 -20
  308. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_crush.py +0 -37
  309. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_gemini.py +0 -44
  310. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_qwen.py +0 -43
  311. machineconfig/scripts/python/helpers_fire/fire_agents_helper_types.py +0 -30
  312. machineconfig/scripts/python/helpers_fire/prompt.txt +0 -2
  313. machineconfig/scripts/python/helpers_fire/template.sh +0 -15
  314. machineconfig/scripts/python/helpers_repos/secure_repo.py +0 -15
  315. machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
  316. machineconfig/scripts/python/nw/wsl_windows_transfer.py +0 -66
  317. machineconfig/scripts/python/repos_helpers/action.py +0 -378
  318. machineconfig/scripts/python/repos_helpers/count_lines_frontend.py +0 -17
  319. machineconfig/scripts/windows/fzfb.ps1 +0 -3
  320. machineconfig/scripts/windows/fzfg.ps1 +0 -2
  321. machineconfig/scripts/windows/fzfrga.bat +0 -20
  322. machineconfig/scripts/windows/mounts/mount_ssh.ps1 +0 -13
  323. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  324. machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
  325. machineconfig/settings/lf/windows/tst.ps1 +0 -1
  326. machineconfig/settings/shells/pwsh/profile.ps1 +0 -0
  327. machineconfig/settings/yazi/keymap.toml +0 -0
  328. machineconfig/settings/yazi/yazi.toml +0 -4
  329. machineconfig/setup_linux/apps.sh +0 -66
  330. machineconfig/setup_linux/nix/cli_installation.sh +0 -137
  331. machineconfig/setup_linux/ssh/openssh_all.sh +0 -25
  332. machineconfig/setup_linux/ssh/openssh_wsl.sh +0 -38
  333. machineconfig/setup_windows/apps.ps1 +0 -62
  334. machineconfig/setup_windows/others/obs.ps1 +0 -4
  335. machineconfig/setup_windows/ssh/add_identity.ps1 +0 -11
  336. machineconfig/setup_windows/wt_and_pwsh/__init__.py +0 -0
  337. machineconfig/utils/installer_utils/installer.py +0 -225
  338. machineconfig-6.23.dist-info/METADATA +0 -84
  339. machineconfig-6.23.dist-info/RECORD +0 -428
  340. machineconfig/cluster/sessions_managers/{utils → helpers}/load_balancer_helper.py +0 -0
  341. machineconfig/cluster/sessions_managers/{helpers → zellij_utils}/zellij_local_helper.py +0 -0
  342. machineconfig/cluster/sessions_managers/{helpers → zellij_utils}/zellij_local_helper_restart.py +0 -0
  343. machineconfig/cluster/sessions_managers/{helpers → zellij_utils}/zellij_local_manager_helper.py +0 -0
  344. machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
  345. machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +0 -0
  346. machineconfig/jobs/installer/{custom_dev → python_scripts}/__init__.py +0 -0
  347. machineconfig/jobs/installer/{custom_dev → python_scripts}/alacritty.py +0 -0
  348. machineconfig/jobs/installer/{custom_dev → python_scripts}/bypass_paywall.py +0 -0
  349. machineconfig/jobs/installer/{custom_dev → python_scripts}/cursor.py +0 -0
  350. machineconfig/jobs/installer/{custom_dev → python_scripts}/espanso.py +0 -0
  351. machineconfig/jobs/installer/{custom → python_scripts}/gh.py +0 -0
  352. machineconfig/jobs/installer/{custom_dev → python_scripts}/goes.py +0 -0
  353. machineconfig/jobs/installer/{custom_dev → python_scripts}/lvim.py +0 -0
  354. machineconfig/jobs/installer/{custom_dev → python_scripts}/redis.py +0 -0
  355. machineconfig/{setup_linux/web_shortcuts → jobs/scripts/bash_scripts}/android.sh +0 -0
  356. machineconfig/jobs/{linux/msc → scripts/bash_scripts}/lid.sh +0 -0
  357. machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/mint_keyboard_shortcuts.sh +0 -0
  358. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_drive +0 -0
  359. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nw_drive +0 -0
  360. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_smb +0 -0
  361. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_cloud.sh +0 -0
  362. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_nfs +0 -0
  363. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/start_docker +0 -0
  364. machineconfig/{scripts → jobs/scripts/powershell_scripts}/Restore-ThunderbirdProfile.ps1 +0 -0
  365. machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/docker.ps1 +0 -0
  366. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nfs.ps1 +0 -0
  367. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nw.ps1 +0 -0
  368. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_smb.ps1 +0 -0
  369. machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/power_options.ps1 +0 -0
  370. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_cloud.cmd +0 -0
  371. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_smb.ps1 +0 -0
  372. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/unlock_bitlocker.ps1 +0 -0
  373. machineconfig/{jobs/python → scripts/python/ai/utils}/__init__.py +0 -0
  374. machineconfig/scripts/python/{cloud_helpers → helpers_agents}/__init__.py +0 -0
  375. machineconfig/scripts/python/{croshell_helpers → helpers_agents/agentic_frameworks}/__init__.py +0 -0
  376. machineconfig/scripts/python/{helpers_fire → helpers_agents}/fire_agents_help_search.py +0 -0
  377. machineconfig/scripts/python/{helpers_fire → helpers_agents}/fire_agents_load_balancer.py +0 -0
  378. machineconfig/scripts/python/{helpers_fire → helpers_agents/templates}/template.ps1 +0 -0
  379. machineconfig/scripts/python/{devops_helpers → helpers_cloud}/__init__.py +0 -0
  380. machineconfig/scripts/python/{cloud_helpers → helpers_cloud}/cloud_helpers.py +1 -1
  381. /machineconfig/scripts/python/{cloud_helpers → helpers_cloud}/helpers5.py +0 -0
  382. /machineconfig/scripts/python/{devops_helpers/themes → helpers_croshell}/__init__.py +0 -0
  383. /machineconfig/scripts/python/{croshell_helpers → helpers_croshell}/pomodoro.py +0 -0
  384. /machineconfig/scripts/python/{croshell_helpers → helpers_croshell}/scheduler.py +0 -0
  385. /machineconfig/scripts/python/{croshell_helpers → helpers_croshell}/viewer.py +0 -0
  386. /machineconfig/scripts/python/{croshell_helpers → helpers_croshell}/viewer_template.py +0 -0
  387. /machineconfig/scripts/python/{helpers_fire → helpers_devops}/__init__.py +0 -0
  388. /machineconfig/scripts/python/{helpers_fire/agentic_frameworks → helpers_devops/themes}/__init__.py +0 -0
  389. /machineconfig/scripts/python/{devops_helpers → helpers_devops}/themes/choose_pwsh_theme.ps1 +0 -0
  390. /machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
  391. /machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_fire_command/f.py} +0 -0
  392. /machineconfig/scripts/python/{helper_navigator → helpers_navigator}/data_models.py +0 -0
  393. /machineconfig/scripts/python/{helper_navigator → helpers_navigator}/search_bar.py +0 -0
  394. /machineconfig/scripts/python/{helpers_repos → helpers_network}/__init__.py +0 -0
  395. /machineconfig/scripts/python/{nw → helpers_network}/mount_nw_drive.py +0 -0
  396. /machineconfig/scripts/python/{nw → helpers_network}/onetimeshare.py +0 -0
  397. /machineconfig/scripts/python/{repos_helpers → helpers_repos}/update.py +0 -0
  398. /machineconfig/scripts/python/{nw → helpers_sessions}/__init__.py +0 -0
  399. /machineconfig/{scripts/python/sessions_helpers → settings/wt}/__init__.py +0 -0
  400. /machineconfig/{setup_windows/wt_and_pwsh → settings/wt}/set_wt_settings.py +0 -0
  401. {machineconfig-6.23.dist-info → machineconfig-8.12.dist-info}/WHEEL +0 -0
  402. {machineconfig-6.23.dist-info → machineconfig-8.12.dist-info}/top_level.txt +0 -0
@@ -7,23 +7,28 @@ import subprocess
7
7
  import platform
8
8
 
9
9
 
10
- def find_move_delete_windows(downloaded_file_path: PathExtended, exe_name: Optional[str] = None, delete: bool = True, rename_to: Optional[str] = None):
11
- print("🔍 PROCESSING WINDOWS EXECUTABLE 🔍")
12
- if exe_name is not None and ".exe" in exe_name:
13
- exe_name = exe_name.replace(".exe", "")
10
+ def find_move_delete_windows(downloaded_file_path: PathExtended, tool_name: Optional[str], delete: bool, rename_to: Optional[str]):
11
+ # print("🔍 PROCESSING WINDOWS EXECUTABLE 🔍")
12
+ # if exe_name is not None and len(exe_name.split("+")) > 1:
13
+ # last_result = None
14
+ # for a_binary in [x.strip() for x in exe_name.split("+") if x.strip() != ""]:
15
+ # last_result = find_move_delete_windows(downloaded_file_path=downloaded_file_path, exe_name=a_binary, delete=delete, rename_to=rename_to)
16
+ # return last_result
17
+ if tool_name is not None and ".exe" in tool_name:
18
+ tool_name = tool_name.replace(".exe", "")
14
19
  if downloaded_file_path.is_file():
15
20
  exe = downloaded_file_path
16
21
  print(f"📄 Found direct executable file: {exe}")
17
22
  else:
18
23
  print(f"🔎 Searching for executable in: {downloaded_file_path}")
19
- if exe_name is None:
24
+ if tool_name is None:
20
25
  exe = downloaded_file_path.search("*.exe", r=True)[0]
21
26
  print(f"✅ Found executable: {exe}")
22
27
  else:
23
- tmp = downloaded_file_path.search(f"{exe_name}.exe", r=True)
28
+ tmp = downloaded_file_path.search(f"{tool_name}.exe", r=True)
24
29
  if len(tmp) == 1:
25
30
  exe = tmp[0]
26
- print(f"✅ Found exact match for {exe_name}.exe: {exe}")
31
+ print(f"✅ Found exact match for {tool_name}.exe: {exe}")
27
32
  else:
28
33
  search_res = downloaded_file_path.search("*.exe", r=True)
29
34
  if len(search_res) == 0:
@@ -52,7 +57,13 @@ def find_move_delete_windows(downloaded_file_path: PathExtended, exe_name: Optio
52
57
  return exe_new_location
53
58
 
54
59
 
55
- def find_move_delete_linux(downloaded: PathExtended, tool_name: str, delete: Optional[bool] = True, rename_to: Optional[str] = None):
60
+ def find_move_delete_linux(downloaded: PathExtended, tool_name: Optional[str], delete: bool, rename_to: Optional[str]):
61
+ # if len(tool_name.split("+")) > 1:
62
+ # last_result = None
63
+ # for a_binary in [x.strip() for x in tool_name.split("+") if x.strip() != ""]:
64
+ # last_result = find_move_delete_linux(downloaded=downloaded, tool_name=a_binary, delete=False, rename_to=rename_to)
65
+ # return last_result
66
+
56
67
  print("🔍 PROCESSING LINUX EXECUTABLE 🔍")
57
68
  if downloaded.is_file():
58
69
  exe = downloaded
@@ -64,16 +75,24 @@ def find_move_delete_linux(downloaded: PathExtended, tool_name: str, delete: Opt
64
75
  exe = res[0]
65
76
  print(f"✅ Found match for pattern '*{tool_name}*': {exe}")
66
77
  else:
67
- exe_search_res = downloaded.search(tool_name, folders=False, r=True)
68
- if len(exe_search_res) == 0:
69
- print(f"❌ ERROR: No search results for `{tool_name}` in `{downloaded}`")
70
- raise IndexError(f"No executable found in {downloaded}")
71
- elif len(exe_search_res) == 1:
72
- exe = exe_search_res[0]
73
- print(f"✅ Found exact match for '{tool_name}': {exe}")
74
- else:
75
- exe = max(exe_search_res, key=lambda x: x.size("kb"))
78
+ if tool_name is None: # no tool name provided, get the largest executable
79
+ search_res = downloaded.search("*", folders=False, files=True, r=True)
80
+ if len(search_res) == 0:
81
+ print(f"❌ ERROR: No search results in `{downloaded}`")
82
+ raise IndexError(f"No executable found in {downloaded}")
83
+ exe = max(search_res, key=lambda x: x.size("kb"))
76
84
  print(f"✅ Selected largest executable ({exe.size('kb')} KB): {exe}")
85
+ else:
86
+ exe_search_res = downloaded.search(tool_name, folders=False, r=True)
87
+ if len(exe_search_res) == 0:
88
+ print(f"❌ ERROR: No search results for `{tool_name}` in `{downloaded}`")
89
+ raise IndexError(f"No executable found in {downloaded}")
90
+ elif len(exe_search_res) == 1:
91
+ exe = exe_search_res[0]
92
+ print(f"✅ Found exact match for '{tool_name}': {exe}")
93
+ else:
94
+ exe = max(exe_search_res, key=lambda x: x.size("kb"))
95
+ print(f"✅ Selected largest executable ({exe.size('kb')} KB): {exe}")
77
96
 
78
97
  if rename_to and exe.name != rename_to:
79
98
  print(f"🏷️ Renaming '{exe.name}' to '{rename_to}'")
@@ -141,11 +160,12 @@ def check_tool_exists(tool_name: str) -> bool:
141
160
  return npm_check
142
161
  else:
143
162
  raise NotImplementedError(f"platform {platform.system()} not implemented")
144
- def is_executable_in_path(executable_name: str) -> bool:
163
+
164
+ def is_executable_in_path(name: str) -> bool:
145
165
  import os
146
166
  path_dirs = os.environ['PATH'].split(os.pathsep)
147
167
  for path_dir in path_dirs:
148
- path_to_executable = os.path.join(path_dir, executable_name)
168
+ path_to_executable = os.path.join(path_dir, name)
149
169
  if os.path.isfile(path_to_executable) and os.access(path_to_executable, os.X_OK): return True
150
170
  return False
151
171
 
@@ -190,71 +210,3 @@ def check_if_installed_already(exe_name: str, version: Optional[str], use_cache:
190
210
  return ("⚠️ NotInstalled", "None", version or "unknown")
191
211
 
192
212
 
193
- def parse_apps_installer_linux(txt: str) -> dict[str, tuple[str, str]]:
194
- """Parse Linux shell installation scripts into logical chunks.
195
-
196
- Splits scripts by # --GROUP:<name>:<description> comment signatures into a dictionary
197
- mapping block names to (description, shell script content) tuples.
198
-
199
- Returns:
200
- dict[str, tuple[str, str]]: Dictionary mapping block/section names to (description, installation_script) tuples
201
- """
202
- chunks = txt.split('# --GROUP:')
203
- res: dict[str, tuple[str, str]] = {}
204
-
205
- for chunk in chunks[1:]: # Skip first empty chunk before first group
206
- lines = chunk.split('\n')
207
- # First line contains the group name and description in format "NAME:DESCRIPTION"
208
- group_line = lines[0].strip()
209
-
210
- # Extract group name and description
211
- if ':' in group_line:
212
- parts = group_line.split(':', 1) # Split only on first colon
213
- group_name = parts[0].strip()
214
- group_description = parts[1].strip() if len(parts) > 1 else ""
215
- else:
216
- group_name = group_line
217
- group_description = ""
218
-
219
- # Rest is the content
220
- content = '\n'.join(lines[1:]).strip()
221
-
222
- if group_name and content:
223
- res[group_name] = (group_description, content)
224
-
225
- return res
226
-
227
-
228
- def parse_apps_installer_windows(txt: str) -> dict[str, tuple[str, str]]:
229
- """Parse Windows PowerShell installation scripts into logical chunks.
230
-
231
- Splits scripts by # --GROUP:<name>:<description> comment signatures into a dictionary
232
- mapping block names to (description, PowerShell script content) tuples.
233
-
234
- Returns:
235
- dict[str, tuple[str, str]]: Dictionary mapping block/section names to (description, installation_script) tuples
236
- """
237
- chunks = txt.split('# --GROUP:')
238
- res: dict[str, tuple[str, str]] = {}
239
-
240
- for chunk in chunks[1:]: # Skip first chunk before first group
241
- lines = chunk.split('\n')
242
- # First line contains the group name and description in format "NAME:DESCRIPTION"
243
- group_line = lines[0].strip()
244
-
245
- # Extract group name and description
246
- if ':' in group_line:
247
- parts = group_line.split(':', 1) # Split only on first colon
248
- group_name = parts[0].strip()
249
- group_description = parts[1].strip() if len(parts) > 1 else ""
250
- else:
251
- group_name = group_line
252
- group_description = ""
253
-
254
- # Rest is the content
255
- content = '\n'.join(lines[1:]).strip()
256
-
257
- if group_name and content:
258
- res[group_name] = (group_description, content)
259
-
260
- return res
@@ -1,11 +1,11 @@
1
1
  """package manager"""
2
2
 
3
- from machineconfig.utils.installer_utils.installer_abc import check_if_installed_already, parse_apps_installer_linux, parse_apps_installer_windows
3
+ from machineconfig.utils.installer_utils.installer_locator_utils import check_if_installed_already
4
4
  from machineconfig.utils.installer_utils.installer_class import Installer
5
5
  from machineconfig.utils.schemas.installer.installer_types import InstallerData, InstallerDataFiles, get_normalized_arch, get_os_name, OPERATING_SYSTEMS, CPU_ARCHITECTURES
6
- from machineconfig.jobs.installer.package_groups import PACKAGE_GROUPS, PACKAGE_GROUP2NAMES
6
+ from machineconfig.jobs.installer.package_groups import PACKAGE_GROUP2NAMES
7
7
  from machineconfig.utils.path_extended import PathExtended
8
- from machineconfig.utils.source_of_truth import INSTALL_VERSION_ROOT, LINUX_INSTALL_PATH, LIBRARY_ROOT
8
+ from machineconfig.utils.source_of_truth import INSTALL_VERSION_ROOT, LINUX_INSTALL_PATH
9
9
  from machineconfig.utils.io import read_json
10
10
 
11
11
  from rich.console import Console
@@ -18,7 +18,7 @@ from joblib import Parallel, delayed
18
18
  def check_latest():
19
19
  console = Console() # Added console initialization
20
20
  console.print(Panel("🔍 CHECKING FOR LATEST VERSIONS", title="Status", expand=False)) # Replaced print with Panel
21
- installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL"])
21
+ installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["termabc"])
22
22
  installers_github = []
23
23
  for inst__ in installers:
24
24
  app_name = inst__["appName"]
@@ -91,9 +91,12 @@ def get_installed_cli_apps():
91
91
  return apps
92
92
 
93
93
 
94
- def get_installers(os: OPERATING_SYSTEMS, arch: CPU_ARCHITECTURES, which_cats: Optional[list[PACKAGE_GROUPS]]) -> list[InstallerData]:
95
- print("🔍 LOADING INSTALLER CONFIGURATIONS 🔍")
96
- res_all = get_all_installer_data_files()
94
+ def get_installers(os: OPERATING_SYSTEMS, arch: CPU_ARCHITECTURES, which_cats: Optional[list[str]]) -> list[InstallerData]:
95
+ import machineconfig.jobs.installer as module
96
+ from pathlib import Path
97
+ res_raw: InstallerDataFiles = read_json(Path(module.__file__).parent.joinpath("installer_data.json"))
98
+ res_all: list[InstallerData] = res_raw["installers"]
99
+
97
100
  acceptable_apps_names: list[str] | None = None
98
101
  if which_cats is not None:
99
102
  acceptable_apps_names = []
@@ -106,40 +109,17 @@ def get_installers(os: OPERATING_SYSTEMS, arch: CPU_ARCHITECTURES, which_cats: O
106
109
  if acceptable_apps_names is not None:
107
110
  if installer_data["appName"] not in acceptable_apps_names:
108
111
  continue
109
- if installer_data["fileNamePattern"][arch][os] is None:
110
- continue
112
+ try:
113
+ if installer_data["fileNamePattern"][arch][os] is None:
114
+ continue
115
+ except KeyError as ke:
116
+ print(f"❌ ERROR: Missing key in installer data: {ke}")
117
+ print(f"Installer data: {installer_data}")
118
+ raise KeyError(f"Missing key in installer data: {ke}")
111
119
  all_installers.append(installer_data)
112
- print(f"✅ Loaded {len(all_installers)} installer configurations")
113
120
  return all_installers
114
121
 
115
122
 
116
- def get_all_installer_data_files() -> list[InstallerData]:
117
- print("📂 LOADING CONFIGURATION FILES 📂")
118
- import machineconfig.jobs.installer as module
119
- from pathlib import Path
120
-
121
- print("📂 Loading configuration files...")
122
- res_raw: InstallerDataFiles = read_json(Path(module.__file__).parent.joinpath("installer_data.json"))
123
- res_final: list[InstallerData] = res_raw["installers"]
124
- print(f"Loaded: {len(res_final)} installer categories")
125
- return res_final
126
-
127
-
128
- def dynamically_extract_installers_system_groups_from_scripts():
129
- res_final: list[InstallerData] = []
130
- from platform import system
131
- if system() == "Windows":
132
- options_system = parse_apps_installer_windows(LIBRARY_ROOT.joinpath("setup_windows/apps.ps1").read_text(encoding="utf-8"))
133
- elif system() == "Linux" or system() == "Darwin":
134
- options_system = parse_apps_installer_linux(LIBRARY_ROOT.joinpath("setup_linux/apps.sh").read_text(encoding="utf-8"))
135
- else:
136
- raise NotImplementedError(f"❌ System {system()} not supported")
137
- os_name = get_os_name()
138
- for group_name, (docs, script) in options_system.items():
139
- item: InstallerData = {"appName": group_name, "doc": docs, "repoURL": "CMD", "fileNamePattern": {"amd64": {os_name: script}, "arm64": {os_name: script}}}
140
- res_final.append(item)
141
- return res_final
142
-
143
123
 
144
124
  def install_bulk(installers_data: list[InstallerData], safe: bool = False, jobs: int = 10, fresh: bool = False):
145
125
  print("🚀 BULK INSTALLATION PROCESS 🚀")
@@ -147,33 +127,8 @@ def install_bulk(installers_data: list[InstallerData], safe: bool = False, jobs:
147
127
  print("🧹 Fresh install requested - clearing version cache...")
148
128
  PathExtended(INSTALL_VERSION_ROOT).delete(sure=True)
149
129
  print("✅ Version cache cleared")
150
-
151
130
  if safe:
152
131
  pass
153
- # print("⚠️ Safe installation mode activated...")
154
- # from machineconfig.jobs.python.check_installations import APP_SUMMARY_PATH
155
- # if platform.system().lower() == "windows":
156
- # print("🪟 Moving applications to Windows Apps folder...")
157
- # # PathExtended.get_env().WindowsPaths().WindowsApps)
158
- # folder = PathExtended.home().joinpath("AppData/Local/Microsoft/WindowsApps")
159
- # apps_dir.search("*").apply(lambda app: app.move(folder=folder))
160
- # elif platform.system().lower() in ["linux", "darwin"]:
161
- # system_name = "Linux" if platform.system().lower() == "linux" else "macOS"
162
- # print(f"🐧 Moving applications to {system_name} bin folder...")
163
- # if platform.system().lower() == "linux":
164
- # install_path = LINUX_INSTALL_PATH
165
- # else: # Darwin/macOS
166
- # install_path = "/usr/local/bin"
167
- # Terminal().run(f"sudo mv {apps_dir.as_posix()}/* {install_path}/").capture().print_if_unsuccessful(desc=f"MOVING executable to {install_path}", strict_err=True, strict_returncode=True)
168
- # else:
169
- # error_msg = f"❌ ERROR: System {platform.system()} not supported"
170
- # print(error_msg)
171
- # raise NotImplementedError(error_msg)
172
-
173
- # apps_dir.delete(sure=True)
174
- # print(f"✅ Safe installation completed\n{'='*80}")
175
- # return None
176
-
177
132
  print(f"🚀 Starting installation of {len(installers_data)} packages...")
178
133
  print("📦 INSTALLING FIRST PACKAGE 📦")
179
134
  Installer(installers_data[0]).install(version=None)
@@ -215,7 +170,6 @@ def get_machineconfig_version() -> str:
215
170
  from importlib.metadata import PackageNotFoundError, version as _pkg_version
216
171
  from pathlib import Path
217
172
  import tomllib
218
-
219
173
  name: str = "machineconfig"
220
174
  try:
221
175
  return _pkg_version(name)
machineconfig/utils/io.py CHANGED
@@ -1,4 +1,3 @@
1
- from __future__ import annotations
2
1
 
3
2
  from typing import Any, Union, Optional, Mapping
4
3
  from pathlib import Path
@@ -61,9 +60,14 @@ def read_json(path: "Path", r: bool = False, **kwargs: Any) -> Any: # return co
61
60
  try:
62
61
  mydict = json.loads(Path(path).read_text(encoding="utf-8"), **kwargs)
63
62
  except Exception:
64
- import pyjson5
65
-
66
- mydict = pyjson5.loads(Path(path).read_text(encoding="utf-8"), **kwargs) # file has C-style comments.
63
+ import re
64
+ def remove_comments(text: str) -> str:
65
+ # remove all // single-line comments
66
+ text = re.sub(r'//.*', '', text)
67
+ # remove all /* … */ block comments (non-greedy)
68
+ text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL)
69
+ return text
70
+ mydict = json.loads(remove_comments(Path(path).read_text(encoding="utf-8")), **kwargs)
67
71
  _ = r
68
72
  return mydict
69
73
 
@@ -72,3 +76,72 @@ def from_pickle(path: Path) -> Any:
72
76
  import pickle
73
77
 
74
78
  return pickle.loads(path.read_bytes())
79
+
80
+
81
+ def pwd2key(password: str, salt: Optional[bytes] = None, iterations: int = 10) -> bytes: # Derive a secret key from a given password and salt"""
82
+ import base64
83
+ if salt is None:
84
+ import hashlib
85
+ m = hashlib.sha256()
86
+ m.update(password.encode(encoding="utf-8"))
87
+ return base64.urlsafe_b64encode(s=m.digest()) # make url-safe bytes required by Ferent.
88
+ from cryptography.hazmat.primitives import hashes
89
+ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
90
+ return base64.urlsafe_b64encode(PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=iterations, backend=None).derive(password.encode()))
91
+
92
+
93
+ def encrypt(msg: bytes, key: Optional[bytes] = None, pwd: Optional[str] = None, salted: bool = True, iteration: Optional[int] = None, gen_key: bool = False) -> bytes:
94
+ import base64
95
+ from cryptography.fernet import Fernet
96
+
97
+ salt, iteration = None, None
98
+ if pwd is not None: # generate it from password
99
+ assert (key is None) and (type(pwd) is str), "❌ You can either pass key or pwd, or none of them, but not both."
100
+ import secrets
101
+ iteration = iteration or secrets.randbelow(exclusive_upper_bound=1_000_000)
102
+ salt = secrets.token_bytes(nbytes=16) if salted else None
103
+ key_resolved = pwd2key(password=pwd, salt=salt, iterations=iteration)
104
+ elif key is None:
105
+ if gen_key:
106
+ key_resolved = Fernet.generate_key()
107
+ Path.home().joinpath("dotfiles/creds/data/encrypted_files_key.bytes").write_bytes(key_resolved)
108
+ else:
109
+ try:
110
+ key_resolved = Path.home().joinpath("dotfiles/creds/data/encrypted_files_key.bytes").read_bytes()
111
+ print(f"⚠️ Using key from: {Path.home().joinpath('dotfiles/creds/data/encrypted_files_key.bytes')}")
112
+ except FileNotFoundError as err:
113
+ print("\n" * 3, "~" * 50, """Consider Loading up your dotfiles or pass `gen_key=True` to make and save one.""", "~" * 50, "\n" * 3)
114
+ raise FileNotFoundError(err) from err
115
+ elif isinstance(key, (str, Path)):
116
+ key_resolved = Path(key).read_bytes() # a path to a key file was passed, read it:
117
+ elif type(key) is bytes:
118
+ key_resolved = key # key passed explicitly
119
+ else:
120
+ raise TypeError("❌ Key must be either a path, bytes object or None.")
121
+ code = Fernet(key=key_resolved).encrypt(msg)
122
+ if pwd is not None and salt is not None and iteration is not None:
123
+ return base64.urlsafe_b64encode(b"%b%b%b" % (salt, iteration.to_bytes(4, "big"), base64.urlsafe_b64decode(code)))
124
+ return code
125
+
126
+
127
+ def decrypt(token: bytes, key: Optional[bytes] = None, pwd: Optional[str] = None, salted: bool = True) -> bytes:
128
+ import base64
129
+ if pwd is not None:
130
+ assert key is None, "❌ You can either pass key or pwd, or none of them, but not both."
131
+ if salted:
132
+ decoded = base64.urlsafe_b64decode(token)
133
+ salt, iterations, token = decoded[:16], decoded[16:20], base64.urlsafe_b64encode(decoded[20:])
134
+ key_resolved = pwd2key(password=pwd, salt=salt, iterations=int.from_bytes(bytes=iterations, byteorder="big"))
135
+ else:
136
+ key_resolved = pwd2key(password=pwd) # trailing `;` prevents IPython from caching the result.
137
+ elif type(key) is bytes:
138
+ assert pwd is None, "❌ You can either pass key or pwd, or none of them, but not both."
139
+ key_resolved = key # passsed explicitly
140
+ elif key is None:
141
+ key_resolved = Path.home().joinpath("dotfiles/creds/data/encrypted_files_key.bytes").read_bytes() # read from file
142
+ elif isinstance(key, (str, Path)):
143
+ key_resolved = Path(key).read_bytes() # passed a path to a file containing kwy
144
+ else:
145
+ raise TypeError(f"❌ Key must be either str, P, Path, bytes or None. Recieved: {type(key)}")
146
+ from cryptography.fernet import Fernet
147
+ return Fernet(key=key_resolved).decrypt(token)
@@ -1,4 +1,5 @@
1
1
  from machineconfig.utils.path_extended import PathExtended, PLike
2
+ from machineconfig.profile.create_links_export import ON_CONFLICT_STRICT
2
3
  from machineconfig.utils.accessories import randstr
3
4
  from rich.console import Console
4
5
  from rich.panel import Panel
@@ -96,18 +97,18 @@ def build_links(target_paths: list[tuple[PLike, str]], repo_root: PLike):
96
97
 
97
98
 
98
99
  def symlink_map(config_file_default_path: PathExtended, self_managed_config_file_path: PathExtended,
99
- on_conflict: Literal["throwError", "overwriteSelfManaged", "backupSelfManaged", "overwriteDefaultPath", "backupDefaultPath"]
100
+ on_conflict: ON_CONFLICT_STRICT
100
101
  ) -> OperationResult:
101
102
  """helper function. creates a symlink from `config_file_default_path` to `self_managed_config_file_path`.
102
103
 
103
104
  Returns a dict with 'action' and 'details' keys describing what was done.
104
105
 
105
106
  on_conflict strategies:
106
- - throwError: Raise exception when files differ
107
- - overwriteSelfManaged: Delete self_managed_config_file_path (self-managed), move config_file_default_path to self_managed_config_file_path, create symlink
108
- - backupSelfManaged: Backup self_managed_config_file_path (self-managed), move config_file_default_path to self_managed_config_file_path, create symlink
109
- - overwriteDefaultPath: Delete config_file_default_path (default path), create symlink to self_managed_config_file_path
110
- - backupDefaultPath: Backup config_file_default_path (default path), create symlink to self_managed_config_file_path
107
+ - throw-error: Raise exception when files differ
108
+ - overwrite-self-managed: Delete self_managed_config_file_path (self-managed), move config_file_default_path to self_managed_config_file_path, create symlink
109
+ - backup-self-managed: Backup self_managed_config_file_path (self-managed), move config_file_default_path to self_managed_config_file_path, create symlink
110
+ - overwrite-default-path: Delete config_file_default_path (default path), create symlink to self_managed_config_file_path
111
+ - backup-default-path: Backup config_file_default_path (default path), create symlink to self_managed_config_file_path
111
112
 
112
113
  Note: `config_file_default_path` is the default system location, `self_managed_config_file_path` is the self-managed config location
113
114
 
@@ -162,32 +163,41 @@ def symlink_map(config_file_default_path: PathExtended, self_managed_config_file
162
163
  config_file_default_path.delete(sure=True)
163
164
  else:
164
165
  # Files are different, use on_conflict strategy
165
- if on_conflict == "throwError":
166
- raise RuntimeError(f"Conflict detected: {config_file_default_path} and {self_managed_config_file_path} both exist with different content")
167
- elif on_conflict == "overwriteSelfManaged":
168
- action_taken = "backing_up_target"
169
- details = "Overwriting self-managed config, moving default path to self-managed location"
170
- console.print(Panel(f"📦 OVERWRITE SELF-MANAGED | Deleting {self_managed_config_file_path}, moving {config_file_default_path} to {self_managed_config_file_path}", title="Overwrite Self-Managed", expand=False))
171
- self_managed_config_file_path.delete(sure=True)
172
- config_file_default_path.move(path=self_managed_config_file_path)
173
- elif on_conflict == "backupSelfManaged":
174
- backup_name = f"{self_managed_config_file_path}.orig_{randstr()}"
175
- action_taken = "backing_up_target"
176
- details = f"Backed up self-managed config to {backup_name}"
177
- console.print(Panel(f"📦 BACKUP SELF-MANAGED | Moving {self_managed_config_file_path} to {backup_name}, moving {config_file_default_path} to {self_managed_config_file_path}", title="Backup Self-Managed", expand=False))
178
- self_managed_config_file_path.move(path=backup_name)
179
- config_file_default_path.move(path=self_managed_config_file_path)
180
- elif on_conflict == "overwriteDefaultPath":
181
- action_taken = "backupConfigDefaultPath"
182
- details = "Overwriting default path, creating symlink to self-managed config"
183
- console.print(Panel(f"📦 OVERWRITE DEFAULT | Deleting {config_file_default_path}, creating symlink to {self_managed_config_file_path}", title="Overwrite Default", expand=False))
184
- config_file_default_path.delete(sure=True)
185
- elif on_conflict == "backupDefaultPath":
186
- backup_name = f"{config_file_default_path}.orig_{randstr()}"
187
- action_taken = "backupConfigDefaultPath"
188
- details = f"Backed up default path to {backup_name}"
189
- console.print(Panel(f"📦 BACKUP DEFAULT | Moving {config_file_default_path} to {backup_name}, creating symlink to {self_managed_config_file_path}", title="Backup Default", expand=False))
190
- config_file_default_path.move(path=backup_name)
166
+ import subprocess
167
+ command = f"""delta --paging never --side-by-side "{config_file_default_path}" "{self_managed_config_file_path}" """
168
+ try:
169
+ console.print(Panel(f"🆘 CONFLICT DETECTED | Showing diff between {config_file_default_path} and {self_managed_config_file_path}", title="Conflict Detected", expand=False))
170
+ subprocess.run(command, shell=True, check=True)
171
+ except Exception:
172
+ console.print(Panel("⚠️ Could not show diff using 'delta'. Please install 'delta' for better diff visualization.", title="Delta Not Found", expand=False))
173
+
174
+ match on_conflict:
175
+ case "throw-error":
176
+ raise RuntimeError(f"Conflict detected: {config_file_default_path} and {self_managed_config_file_path} both exist with different content")
177
+ case "overwrite-self-managed":
178
+ action_taken = "backing_up_target"
179
+ details = "Overwriting self-managed config, moving default path to self-managed location"
180
+ console.print(Panel(f"📦 OVERWRITE SELF-MANAGED | Deleting {self_managed_config_file_path}, moving {config_file_default_path} to {self_managed_config_file_path}", title="Overwrite Self-Managed", expand=False))
181
+ self_managed_config_file_path.delete(sure=True)
182
+ config_file_default_path.move(path=self_managed_config_file_path)
183
+ case "backup-self-managed":
184
+ backup_name = f"{self_managed_config_file_path}.orig_{randstr()}"
185
+ action_taken = "backing_up_target"
186
+ details = f"Backed up self-managed config to {backup_name}"
187
+ console.print(Panel(f"📦 BACKUP SELF-MANAGED | Moving {self_managed_config_file_path} to {backup_name}, moving {config_file_default_path} to {self_managed_config_file_path}", title="Backup Self-Managed", expand=False))
188
+ self_managed_config_file_path.move(path=backup_name)
189
+ config_file_default_path.move(path=self_managed_config_file_path)
190
+ case "overwrite-default-path":
191
+ action_taken = "backupConfigDefaultPath"
192
+ details = "Overwriting default path, creating symlink to self-managed config"
193
+ console.print(Panel(f"📦 OVERWRITE DEFAULT | Deleting {config_file_default_path}, creating symlink to {self_managed_config_file_path}", title="Overwrite Default", expand=False))
194
+ config_file_default_path.delete(sure=True)
195
+ case "backup-default-path":
196
+ backup_name = f"{config_file_default_path}.orig_{randstr()}"
197
+ action_taken = "backupConfigDefaultPath"
198
+ details = f"Backed up default path to {backup_name}"
199
+ console.print(Panel(f"📦 BACKUP DEFAULT | Moving {config_file_default_path} to {backup_name}, creating symlink to {self_managed_config_file_path}", title="Backup Default", expand=False))
200
+ config_file_default_path.move(path=backup_name)
191
201
  else:
192
202
  # self_managed_config_file_path doesn't exist
193
203
  if config_file_default_path.is_symlink():
@@ -235,7 +245,7 @@ def symlink_map(config_file_default_path: PathExtended, self_managed_config_file
235
245
  return {"action": action_taken, "details": details}
236
246
 
237
247
 
238
- def copy_map(config_file_default_path: PathExtended, self_managed_config_file_path: PathExtended, on_conflict: Literal["throwError", "overwriteSelfManaged", "backupSelfManaged", "overwriteDefaultPath", "backupDefaultPath"]) -> OperationResult:
248
+ def copy_map(config_file_default_path: PathExtended, self_managed_config_file_path: PathExtended, on_conflict: ON_CONFLICT_STRICT) -> OperationResult:
239
249
  config_file_default_path = PathExtended(config_file_default_path).expanduser().absolute()
240
250
  self_managed_config_file_path = PathExtended(self_managed_config_file_path).expanduser().absolute()
241
251
 
@@ -282,28 +292,36 @@ def copy_map(config_file_default_path: PathExtended, self_managed_config_file_pa
282
292
  config_file_default_path.delete(sure=True)
283
293
  else:
284
294
  # Files are different, use on_conflict strategy
295
+ import subprocess
296
+ command = f"""delta --paging never --side-by-side "{config_file_default_path}" "{self_managed_config_file_path}" """
297
+ try:
298
+ console.print(Panel(f"🆘 CONFLICT DETECTED | Showing diff between {config_file_default_path} and {self_managed_config_file_path}", title="Conflict Detected", expand=False))
299
+ subprocess.run(command, shell=True, check=True)
300
+ except Exception:
301
+ console.print(Panel("⚠️ Could not show diff using 'delta'. Please install 'delta' for better diff visualization.", title="Delta Not Found", expand=False))
302
+
285
303
  match on_conflict:
286
- case "throwError":
304
+ case "throw-error":
287
305
  raise RuntimeError(f"Conflict detected: {config_file_default_path} and {self_managed_config_file_path} both exist with different content")
288
- case "overwriteSelfManaged":
306
+ case "overwrite-self-managed":
289
307
  action_taken = "backing_up_target"
290
308
  details = "Overwriting self-managed config with default path content"
291
309
  console.print(Panel(f"📦 OVERWRITE SELF-MANAGED | Deleting {self_managed_config_file_path}, moving {config_file_default_path} to {self_managed_config_file_path}", title="Overwrite Self-Managed", expand=False))
292
310
  self_managed_config_file_path.delete(sure=True)
293
311
  config_file_default_path.move(path=self_managed_config_file_path)
294
- case "backupSelfManaged":
312
+ case "backup-self-managed":
295
313
  backup_name = f"{self_managed_config_file_path}.orig_{randstr()}"
296
314
  action_taken = "backing_up_target"
297
315
  details = f"Backed up self-managed config to {backup_name}"
298
316
  console.print(Panel(f"📦 BACKUP SELF-MANAGED | Moving {self_managed_config_file_path} to {backup_name}, moving {config_file_default_path} to {self_managed_config_file_path}", title="Backup Self-Managed", expand=False))
299
317
  self_managed_config_file_path.move(path=backup_name)
300
318
  config_file_default_path.move(path=self_managed_config_file_path)
301
- case "overwriteDefaultPath":
319
+ case "overwrite-default-path":
302
320
  action_taken = "backupConfigDefaultPath"
303
321
  details = "Overwriting default path with self-managed config"
304
322
  console.print(Panel(f"📦 OVERWRITE DEFAULT | Deleting {config_file_default_path}, will copy from {self_managed_config_file_path}", title="Overwrite Default", expand=False))
305
323
  config_file_default_path.delete(sure=True)
306
- case "backupDefaultPath":
324
+ case "backup-default-path":
307
325
  backup_name = f"{config_file_default_path}.orig_{randstr()}"
308
326
  action_taken = "backupConfigDefaultPath"
309
327
  details = f"Backed up default path to {backup_name}"