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
@@ -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
@@ -8,39 +9,40 @@ from typing import TypedDict, Literal
8
9
  console = Console()
9
10
 
10
11
 
11
- class SymlinkResult(TypedDict):
12
- action: Literal[
13
- "already_linked",
14
- "relinking",
15
- "fixing_broken_link",
16
- "identical_files",
17
- "backing_up_source",
18
- "backing_up_target",
19
- "relinking_to_new_target",
20
- "moving_to_target",
21
- "new_link",
22
- "new_link_and_target",
23
- "linking",
24
- "error"
25
- ]
26
- details: str
12
+ ActionType = Literal[
13
+ "already_linked",
14
+ "relinking",
15
+ "fixing_broken_link",
16
+ "identical_files",
17
+ "backupConfigDefaultPath",
18
+ "backing_up_source",
19
+ "backing_up_target",
20
+ "relink2newSelfManagedPath",
21
+ "relinking_to_new_target",
22
+ "move2selfManagedPath",
23
+ "moving_to_target",
24
+ "new_link",
25
+ "newLinkAndSelfManagedPath",
26
+ "new_link_and_target",
27
+ "linking",
28
+ "copying",
29
+ "error"
30
+ ]
31
+
27
32
 
33
+ class OperationResult(TypedDict):
34
+ action: ActionType
35
+ details: str
28
36
 
29
- class CopyResult(TypedDict):
30
- action: Literal[
31
- "already_linked",
32
- "relinking",
33
- "fixing_broken_link",
34
- "backing_up_source",
35
- "backing_up_target",
36
- "relinking_to_new_target",
37
- "moving_to_target",
38
- "new_link",
39
- "new_link_and_target",
40
- "copying",
41
- "error"
42
- ]
37
+ class OperationRecord(TypedDict):
38
+ action: ActionType
43
39
  details: str
40
+ program: str
41
+ file_key: str
42
+ defaultPath: str
43
+ selfManaged: str
44
+ operation: str
45
+ status: str
44
46
 
45
47
 
46
48
  def files_are_identical(file1: PathExtended, file2: PathExtended) -> bool:
@@ -79,200 +81,290 @@ def build_links(target_paths: list[tuple[PLike, str]], repo_root: PLike):
79
81
  tmp_results_root.mkdir(parents=True, exist_ok=True)
80
82
  target_dirs_filtered.append((tmp_results_root, "tmp_results"))
81
83
 
84
+ links_dir = repo_root_obj.joinpath("links")
85
+ links_dir.mkdir(parents=True, exist_ok=True)
86
+
82
87
  for a_target_path, a_name in target_dirs_filtered:
83
- links_path = repo_root_obj.joinpath("links", a_name)
84
- links_path.symlink_to(target=a_target_path)
88
+ links_path = links_dir.joinpath(a_name)
89
+ if links_path.exists() or links_path.is_symlink():
90
+ if links_path.is_symlink() and links_path.resolve() == a_target_path.resolve():
91
+ continue
92
+ links_path.unlink(missing_ok=True)
93
+ try:
94
+ links_path.symlink_to(target=a_target_path)
95
+ except OSError as ex:
96
+ console.print(Panel(f"❌ Failed to create symlink {links_path} -> {a_target_path}: {ex}", title="Symlink Error", expand=False))
85
97
 
86
98
 
87
- def symlink_func(this: PathExtended, to_this: PathExtended, prioritize_to_this: bool) -> SymlinkResult:
88
- """helper function. creates a symlink from `this` to `to_this`.
99
+ def symlink_map(config_file_default_path: PathExtended, self_managed_config_file_path: PathExtended,
100
+ on_conflict: ON_CONFLICT_STRICT
101
+ ) -> OperationResult:
102
+ """helper function. creates a symlink from `config_file_default_path` to `self_managed_config_file_path`.
89
103
 
90
104
  Returns a dict with 'action' and 'details' keys describing what was done.
91
105
 
92
- this: exists AND to_this exists AND this is a symlink pointing to to_this ===> Resolution: AUTO: do nothing, already linked correctly.
93
- this: exists AND to_this exists AND this is a symlink pointing to somewhere else ===> Resolution: AUTO: delete this symlink, create symlink to to_this
94
- this: exists AND to_this exists AND this is a concrete path ===> Resolution: DANGER: If files are identical (same hash), delete `this` and create symlink to `to_this`. Otherwise, two options: 1) prioritize `this`: to_this is backed up as to_this.orig_<randstr()>, to_this is deleted, and symlink is created from this to to_this as normal; 2) prioritize `to_this`: `this` is backed up as this.orig_<randstr()>, `this` is deleted, and symlink is created from this to to_this as normal.
95
-
96
- this: exists AND to_this doesn't exist AND this is a symlink pointing to somewhere else ===> Resolution: AUTO: delete this symlink, create symlink to to_this (touch to_this)
97
- this: exists AND to_this doesn't exist AND this is a symlink pointing to to_this ===> Resolution: AUTO: delete this symlink, create symlink to to_this (touch to_this)
98
- this: exists AND to_this doesn't exist AND this is a concrete path ===> Resolution: AUTO: move this to to_this, then create symlink from this to to_this.
106
+ on_conflict strategies:
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
99
112
 
100
- this: doesn't exist AND to_this exists ===> Resolution: AUTO: create link from this to to_this
101
- this: doesn't exist AND to_this doesn't exist ===> Resolution: AUTO: create link from this to to_this (touch to_this)
113
+ Note: `config_file_default_path` is the default system location, `self_managed_config_file_path` is the self-managed config location
102
114
 
103
115
  """
104
- this = PathExtended(this).expanduser().absolute()
105
- to_this = PathExtended(to_this).expanduser().absolute()
116
+ config_file_default_path = PathExtended(config_file_default_path).expanduser().absolute()
117
+ self_managed_config_file_path = PathExtended(self_managed_config_file_path).expanduser().absolute()
118
+
119
+ if config_file_default_path.resolve() == self_managed_config_file_path.resolve():
120
+ raise ValueError(f"config_file_default_path and self_managed_config_file_path resolve to the same location: {config_file_default_path.resolve()}")
121
+
106
122
  action_taken = ""
107
123
  details = ""
108
124
 
125
+ # Handle broken symlinks first - they exist as symlinks but point to non-existent targets
126
+ if config_file_default_path.is_symlink() and not config_file_default_path.exists():
127
+ action_taken = "fixing_broken_link"
128
+ details = "Removed broken symlink and will create new one"
129
+ console.print(Panel(f"🔄 FIXING BROKEN LINK | Removing broken symlink {config_file_default_path}, will create link to {self_managed_config_file_path}", title="Fixing Broken Link", expand=False))
130
+ config_file_default_path.unlink()
131
+
109
132
  # Case analysis based on docstring
110
- if this.exists():
111
- if to_this.exists():
112
- if this.is_symlink():
133
+ if config_file_default_path.exists():
134
+ if self_managed_config_file_path.exists():
135
+ if config_file_default_path.is_symlink():
113
136
  # Check if symlink already points to correct target
114
137
  try:
115
- if this.readlink().resolve() == to_this.resolve():
116
- # Case: this exists AND to_this exists AND this is a symlink pointing to to_this
138
+ if config_file_default_path.resolve() == self_managed_config_file_path.resolve():
139
+ # Case: config_file_default_path exists AND self_managed_config_file_path exists AND config_file_default_path is a symlink pointing to self_managed_config_file_path
117
140
  action_taken = "already_linked"
118
141
  details = "Symlink already correctly points to target"
119
- console.print(Panel(f"✅ ALREADY LINKED | {this} ➡️ {to_this}", title="Already Linked", expand=False))
142
+ console.print(Panel(f"✅ ALREADY LINKED | {config_file_default_path} ➡️ {self_managed_config_file_path}", title="Already Linked", expand=False))
120
143
  return {"action": action_taken, "details": details}
121
144
  else:
122
- # Case: this exists AND to_this exists AND this is a symlink pointing to somewhere else
145
+ # Case: config_file_default_path exists AND self_managed_config_file_path exists AND config_file_default_path is a symlink pointing to somewhere else
123
146
  action_taken = "relinking"
124
147
  details = "Updated existing symlink to point to new target"
125
- console.print(Panel(f"🔄 RELINKING | Updating symlink from {this} ➡️ {to_this}", title="Relinking", expand=False))
126
- this.delete(sure=True)
148
+ console.print(Panel(f"🔄 RELINKING | Updating symlink from {config_file_default_path} ➡️ {self_managed_config_file_path}", title="Relinking", expand=False))
149
+ config_file_default_path.delete(sure=True)
127
150
  except OSError:
128
151
  # Broken symlink case
129
152
  action_taken = "fixing_broken_link"
130
153
  details = "Removed broken symlink and will create new one"
131
- console.print(Panel(f"🔄 FIXING BROKEN LINK | Fixing broken symlink from {this} ➡️ {to_this}", title="Fixing Broken Link", expand=False))
132
- this.delete(sure=True)
154
+ console.print(Panel(f"🔄 FIXING BROKEN LINK | Fixing broken symlink from {config_file_default_path} ➡️ {self_managed_config_file_path}", title="Fixing Broken Link", expand=False))
155
+ config_file_default_path.delete(sure=True)
133
156
  else:
134
- # Case: this exists AND to_this exists AND this is a concrete path
135
- if files_are_identical(this, to_this):
157
+ # Case: config_file_default_path exists AND self_managed_config_file_path exists AND config_file_default_path is a concrete path
158
+ if files_are_identical(config_file_default_path, self_managed_config_file_path):
136
159
  # Files are identical, just delete this and create symlink
137
160
  action_taken = "identical_files"
138
- details = "Files identical, removed source and will create symlink"
139
- console.print(Panel(f"🔗 IDENTICAL FILES | Files are identical, deleting {this} and creating symlink to {to_this}", title="Identical Files", expand=False))
140
- this.delete(sure=True)
161
+ details = "Files identical, removed config_file_default_path and will create symlink"
162
+ console.print(Panel(f"🔗 IDENTICAL FILES | Files are identical, deleting {config_file_default_path} and creating symlink to {self_managed_config_file_path}", title="Identical Files", expand=False))
163
+ config_file_default_path.delete(sure=True)
141
164
  else:
142
- # Files are different, use prioritization logic
143
- if prioritize_to_this:
144
- # prioritize `to_this`: `this` is backed up, `this` is deleted, symlink created
145
- backup_name = f"{this}.orig_{randstr()}"
146
- action_taken = "backing_up_source"
147
- details = f"Backed up source to {backup_name}, prioritizing target"
148
- console.print(Panel(f"📦 BACKING UP | Moving {this} to {backup_name}, prioritizing {to_this}", title="Backing Up", expand=False))
149
- this.move(path=backup_name)
150
- else:
151
- # prioritize `this`: to_this is backed up, to_this is deleted, this content moved to to_this location
152
- backup_name = f"{to_this}.orig_{randstr()}"
153
- action_taken = "backing_up_target"
154
- details = f"Backed up target to {backup_name}, prioritizing source"
155
- console.print(Panel(f"📦 BACKING UP | Moving {to_this} to {backup_name}, prioritizing {this}", title="Backing Up", expand=False))
156
- to_this.move(path=backup_name)
157
- this.move(path=to_this)
165
+ # Files are different, use on_conflict strategy
166
+ import subprocess
167
+ command = f"""delta --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)
158
201
  else:
159
- # to_this doesn't exist
160
- if this.is_symlink():
161
- # Case: this exists AND to_this doesn't exist AND this is a symlink (pointing anywhere)
162
- action_taken = "relinking_to_new_target"
163
- details = "Removed existing symlink, will create target and new symlink"
164
- console.print(Panel(f"🔄 RELINKING | Updating symlink from {this} ➡️ {to_this}", title="Relinking", expand=False))
165
- this.delete(sure=True)
166
- # Create to_this
167
- to_this.parent.mkdir(parents=True, exist_ok=True)
168
- to_this.touch()
202
+ # self_managed_config_file_path doesn't exist
203
+ if config_file_default_path.is_symlink():
204
+ # Case: config_file_default_path exists AND self_managed_config_file_path doesn't exist AND config_file_default_path is a symlink (pointing anywhere)
205
+ action_taken = "relink2newSelfManagedPath"
206
+ details = "Removed existing symlink, will create self_managed_config_file_path and new symlink"
207
+ console.print(Panel(f"🔄 RELINKING | Updating symlink from {config_file_default_path} ➡️ {self_managed_config_file_path}", title="Relinking", expand=False))
208
+ config_file_default_path.delete(sure=True)
209
+ # Create self_managed_config_file_path
210
+ self_managed_config_file_path.parent.mkdir(parents=True, exist_ok=True)
211
+ self_managed_config_file_path.touch()
169
212
  else:
170
- # Case: this exists AND to_this doesn't exist AND this is a concrete path
171
- action_taken = "moving_to_target"
172
- details = "Moved source to target location, will create symlink"
173
- console.print(Panel(f"📁 MOVING | Moving {this} to {to_this}, then creating symlink", title="Moving", expand=False))
174
- this.move(path=to_this)
213
+ # Case: config_file_default_path exists AND self_managed_config_file_path doesn't exist AND config_file_default_path is a concrete path
214
+ action_taken = "move2selfManagedPath"
215
+ details = "Moved config_file_default_path to self_managed_config_file_path location, will create symlink"
216
+ console.print(Panel(f"📁 MOVING | Moving {config_file_default_path} to {self_managed_config_file_path}, then creating symlink", title="Moving", expand=False))
217
+ config_file_default_path.move(path=self_managed_config_file_path)
175
218
  else:
176
- # this doesn't exist
177
- if to_this.exists():
178
- # Case: this doesn't exist AND to_this exists
219
+ # config_file_default_path doesn't exist
220
+ if self_managed_config_file_path.exists():
221
+ # Case: config_file_default_path doesn't exist AND self_managed_config_file_path exists
179
222
  action_taken = "new_link"
180
- details = "Creating new symlink to existing target"
181
- console.print(Panel(f"🆕 NEW LINK | Creating new symlink from {this} ➡️ {to_this}", title="New Link", expand=False))
223
+ details = "Creating new symlink to existing self_managed_config_file_path"
224
+ console.print(Panel(f"🆕 NEW LINK | Creating new symlink from {config_file_default_path} ➡️ {self_managed_config_file_path}", title="New Link", expand=False))
182
225
  else:
183
- # Case: this doesn't exist AND to_this doesn't exist
184
- action_taken = "new_link_and_target"
185
- details = "Creating target file and new symlink"
186
- console.print(Panel(f"🆕 NEW LINK & TARGET | Creating {to_this} and symlink from {this} ➡️ {to_this}", title="New Link & Target", expand=False))
187
- to_this.parent.mkdir(parents=True, exist_ok=True)
188
- to_this.touch()
226
+ # Case: config_file_default_path doesn't exist AND self_managed_config_file_path doesn't exist
227
+ action_taken = "newLinkAndSelfManagedPath"
228
+ details = "Creating self_managed_config_file_path file and new symlink"
229
+ console.print(Panel(f"🆕 NEW LINK & TARGET | Creating {self_managed_config_file_path} and symlink from {config_file_default_path} ➡️ {self_managed_config_file_path}", title="New Link & Target", expand=False))
230
+ self_managed_config_file_path.parent.mkdir(parents=True, exist_ok=True)
231
+ self_managed_config_file_path.touch()
189
232
 
190
233
  # Create the symlink
191
234
  try:
192
- action_taken = action_taken or "linking"
193
- details = details or "Creating symlink"
194
- console.print(Panel(f"🔗 LINKING | Creating symlink from {this} ➡️ {to_this}", title="Linking", expand=False))
195
- PathExtended(this).symlink_to(target=to_this, verbose=True, overwrite=True)
235
+ if not action_taken:
236
+ action_taken = "linking"
237
+ details = "Creating symlink"
238
+ console.print(Panel(f"🔗 LINKING | Creating symlink from {config_file_default_path} ➡️ {self_managed_config_file_path}", title="Linking", expand=False))
239
+ PathExtended(config_file_default_path).symlink_to(target=self_managed_config_file_path, verbose=True, overwrite=False)
196
240
  return {"action": action_taken, "details": details}
197
241
  except Exception as ex:
198
242
  action_taken = "error"
199
243
  details = f"Failed to create symlink: {str(ex)}"
200
- console.print(Panel(f"❌ ERROR | Failed at linking {this} ➡️ {to_this}. Reason: {ex}", title="Error", expand=False))
244
+ console.print(Panel(f"❌ ERROR | Failed at linking {config_file_default_path} ➡️ {self_managed_config_file_path}. Reason: {ex}", title="Error", expand=False))
201
245
  return {"action": action_taken, "details": details}
202
246
 
203
247
 
204
- def symlink_copy(this: PathExtended, to_this: PathExtended, prioritize_to_this: bool) -> CopyResult:
205
- this = PathExtended(this).expanduser().absolute()
206
- to_this = PathExtended(to_this).expanduser().absolute()
248
+ def copy_map(config_file_default_path: PathExtended, self_managed_config_file_path: PathExtended, on_conflict: ON_CONFLICT_STRICT) -> OperationResult:
249
+ config_file_default_path = PathExtended(config_file_default_path).expanduser().absolute()
250
+ self_managed_config_file_path = PathExtended(self_managed_config_file_path).expanduser().absolute()
251
+
252
+ if config_file_default_path.resolve() == self_managed_config_file_path.resolve():
253
+ raise ValueError(f"config_file_default_path and self_managed_config_file_path resolve to the same location: {config_file_default_path.resolve()}")
254
+
207
255
  action_taken = ""
208
256
  details = ""
209
257
 
210
- if this.exists():
211
- if to_this.exists():
212
- if this.is_symlink():
258
+ # Handle broken symlinks first - they exist as symlinks but point to non-existent targets
259
+ if config_file_default_path.is_symlink() and not config_file_default_path.exists():
260
+ action_taken = "fixing_broken_link"
261
+ details = "Removed broken symlink and will copy new file"
262
+ console.print(Panel(f"🔄 FIXING BROKEN LINK | Removing broken symlink {config_file_default_path}, will copy from {self_managed_config_file_path}", title="Fixing Broken Link", expand=False))
263
+ config_file_default_path.unlink()
264
+
265
+ match (config_file_default_path.exists(), self_managed_config_file_path.exists()):
266
+ case (True, True):
267
+ # Both files exist
268
+ if config_file_default_path.is_symlink():
213
269
  try:
214
- if this.readlink().resolve() == to_this.resolve():
270
+ if config_file_default_path.resolve() == self_managed_config_file_path.resolve():
215
271
  action_taken = "already_linked"
216
- details = "Symlink already correctly points to target"
217
- console.print(Panel(f"✅ ALREADY LINKED | {this} ➡️ {to_this}", title="Already Linked", expand=False))
272
+ details = "File at default path is already a symlink to self-managed config"
273
+ console.print(Panel(f"✅ ALREADY CORRECT | {config_file_default_path} already points to {self_managed_config_file_path}", title="Already Correct", expand=False))
218
274
  return {"action": action_taken, "details": details}
219
275
  else:
220
276
  action_taken = "relinking"
221
- details = "Updated existing symlink to point to new target"
222
- console.print(Panel(f"🔄 RELINKING | Updating symlink from {this} ➡️ {to_this}", title="Relinking", expand=False))
223
- this.delete(sure=True)
277
+ details = "Removing symlink at default path that points elsewhere"
278
+ console.print(Panel(f"🔄 REMOVING SYMLINK | Removing symlink {config_file_default_path} (points elsewhere), will copy from {self_managed_config_file_path}", title="Removing Symlink", expand=False))
279
+ config_file_default_path.delete(sure=True)
224
280
  except OSError:
225
281
  action_taken = "fixing_broken_link"
226
- details = "Removed broken symlink and will create new one"
227
- console.print(Panel(f"🔄 FIXING BROKEN LINK | Fixing broken symlink from {this} ➡️ {to_this}", title="Fixing Broken Link", expand=False))
228
- this.delete(sure=True)
282
+ details = "Removed broken symlink at default path"
283
+ console.print(Panel(f"🔄 FIXING BROKEN SYMLINK | Removing broken symlink {config_file_default_path}, will copy from {self_managed_config_file_path}", title="Fixing Broken Symlink", expand=False))
284
+ config_file_default_path.delete(sure=True)
229
285
  else:
230
- if prioritize_to_this:
231
- backup_name = f"{this}.orig_{randstr()}"
232
- action_taken = "backing_up_source"
233
- details = f"Backed up source to {backup_name}, prioritizing target"
234
- console.print(Panel(f"📦 BACKING UP | Moving {this} to {backup_name}, prioritizing {to_this}", title="Backing Up", expand=False))
235
- this.move(path=backup_name)
286
+ # Check if files are identical first
287
+ if files_are_identical(config_file_default_path, self_managed_config_file_path):
288
+ # Files are identical, just delete this and proceed with copy
289
+ action_taken = "identical_files"
290
+ details = "Files identical, removed config_file_default_path and will copy"
291
+ console.print(Panel(f"🔗 IDENTICAL FILES | Files are identical, deleting {config_file_default_path} and copying from {self_managed_config_file_path}", title="Identical Files", expand=False))
292
+ config_file_default_path.delete(sure=True)
236
293
  else:
237
- backup_name = f"{to_this}.orig_{randstr()}"
238
- action_taken = "backing_up_target"
239
- details = f"Backed up target to {backup_name}, prioritizing source"
240
- console.print(Panel(f"📦 BACKING UP | Moving {to_this} to {backup_name}, prioritizing {this}", title="Backing Up", expand=False))
241
- to_this.move(path=backup_name)
242
- this.move(path=to_this)
243
- else:
244
- if this.is_symlink():
245
- action_taken = "relinking_to_new_target"
246
- details = "Removed existing symlink, will create target and new symlink"
247
- console.print(Panel(f"🔄 RELINKING | Updating symlink from {this} ➡️ {to_this}", title="Relinking", expand=False))
248
- this.delete(sure=True)
249
- to_this.parent.mkdir(parents=True, exist_ok=True)
250
- to_this.touch()
294
+ # Files are different, use on_conflict strategy
295
+ import subprocess
296
+ command = f"""delta --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
+
303
+ match on_conflict:
304
+ case "throw-error":
305
+ raise RuntimeError(f"Conflict detected: {config_file_default_path} and {self_managed_config_file_path} both exist with different content")
306
+ case "overwrite-self-managed":
307
+ action_taken = "backing_up_target"
308
+ details = "Overwriting self-managed config with default path content"
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))
310
+ self_managed_config_file_path.delete(sure=True)
311
+ config_file_default_path.move(path=self_managed_config_file_path)
312
+ case "backup-self-managed":
313
+ backup_name = f"{self_managed_config_file_path}.orig_{randstr()}"
314
+ action_taken = "backing_up_target"
315
+ details = f"Backed up self-managed config to {backup_name}"
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))
317
+ self_managed_config_file_path.move(path=backup_name)
318
+ config_file_default_path.move(path=self_managed_config_file_path)
319
+ case "overwrite-default-path":
320
+ action_taken = "backupConfigDefaultPath"
321
+ details = "Overwriting default path with self-managed config"
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))
323
+ config_file_default_path.delete(sure=True)
324
+ case "backup-default-path":
325
+ backup_name = f"{config_file_default_path}.orig_{randstr()}"
326
+ action_taken = "backupConfigDefaultPath"
327
+ details = f"Backed up default path to {backup_name}"
328
+ console.print(Panel(f"📦 BACKUP DEFAULT | Moving {config_file_default_path} to {backup_name}, will copy from {self_managed_config_file_path}", title="Backup Default", expand=False))
329
+ config_file_default_path.move(path=backup_name)
330
+ case (True, False):
331
+ # config_file_default_path exists, self_managed_config_file_path doesn't
332
+ if config_file_default_path.is_symlink():
333
+ action_taken = "relink2newSelfManagedPath"
334
+ details = "Removed existing symlink, will create self_managed_config_file_path and copy"
335
+ console.print(Panel(f"🔄 REMOVING SYMLINK | Removing symlink {config_file_default_path}, creating {self_managed_config_file_path}", title="Removing Symlink", expand=False))
336
+ config_file_default_path.delete(sure=True)
337
+ self_managed_config_file_path.parent.mkdir(parents=True, exist_ok=True)
338
+ self_managed_config_file_path.touch()
251
339
  else:
252
- action_taken = "moving_to_target"
253
- details = "Moved source to target location, will copy"
254
- console.print(Panel(f"📁 MOVING | Moving {this} to {to_this}, then copying", title="Moving", expand=False))
255
- this.move(path=to_this)
256
- else:
257
- if to_this.exists():
340
+ action_taken = "move2selfManagedPath"
341
+ details = "Moved config_file_default_path to self_managed_config_file_path location, will copy back"
342
+ console.print(Panel(f"📁 MOVING | Moving {config_file_default_path} to {self_managed_config_file_path}, then copying back", title="Moving", expand=False))
343
+ config_file_default_path.move(path=self_managed_config_file_path)
344
+ case (False, True):
345
+ # config_file_default_path doesn't exist, self_managed_config_file_path does
258
346
  action_taken = "new_link"
259
- details = "Copying existing target to source location"
260
- console.print(Panel(f"🆕 NEW LINK | Copying {to_this} to {this}", title="New Link", expand=False))
261
- else:
262
- action_taken = "new_link_and_target"
263
- details = "Creating target file and copying to source"
264
- console.print(Panel(f"🆕 NEW LINK & TARGET | Creating {to_this} and copying to {this}", title="New Link & Target", expand=False))
265
- to_this.parent.mkdir(parents=True, exist_ok=True)
266
- to_this.touch()
347
+ details = "Copying existing self_managed_config_file_path to config_file_default_path location"
348
+ console.print(Panel(f"🆕 NEW COPY | Copying {self_managed_config_file_path} to {config_file_default_path}", title="New Copy", expand=False))
349
+ case (False, False):
350
+ # Neither exists
351
+ action_taken = "newLinkAndSelfManagedPath"
352
+ details = "Creating self_managed_config_file_path file and copying to config_file_default_path"
353
+ console.print(Panel(f"🆕 NEW FILE & COPY | Creating {self_managed_config_file_path} and copying to {config_file_default_path}", title="New File & Copy", expand=False))
354
+ self_managed_config_file_path.parent.mkdir(parents=True, exist_ok=True)
355
+ self_managed_config_file_path.touch()
267
356
 
268
357
  try:
269
- action_taken = action_taken or "copying"
270
- details = details or "Copying file"
271
- console.print(Panel(f"📋 COPYING | Copying {to_this} to {this}", title="Copying", expand=False))
272
- to_this.copy(path=this, overwrite=True, verbose=True)
358
+ if not action_taken:
359
+ action_taken = "copying"
360
+ details = "Copying file"
361
+ console.print(Panel(f"📋 COPYING | Copying {self_managed_config_file_path} to {config_file_default_path}", title="Copying", expand=False))
362
+ self_managed_config_file_path.copy(path=config_file_default_path, overwrite=True, verbose=True)
273
363
  return {"action": action_taken, "details": details}
274
364
  except Exception as ex:
275
365
  action_taken = "error"
276
366
  details = f"Failed to copy file: {str(ex)}"
277
- console.print(Panel(f"❌ ERROR | Failed at copying {to_this} to {this}. Reason: {ex}", title="Error", expand=False))
367
+ console.print(Panel(f"❌ ERROR | Failed at copying {self_managed_config_file_path} to {config_file_default_path}. Reason: {ex}", title="Error", expand=False))
278
368
  return {"action": action_taken, "details": details}
369
+
370
+