machineconfig 1.97__py3-none-any.whl → 2.1__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.
- machineconfig/cluster/cloud_manager.py +22 -29
- machineconfig/cluster/data_transfer.py +2 -3
- machineconfig/cluster/distribute.py +0 -2
- machineconfig/cluster/file_manager.py +4 -5
- machineconfig/cluster/job_params.py +1 -4
- machineconfig/cluster/loader_runner.py +8 -11
- machineconfig/cluster/remote_machine.py +4 -5
- machineconfig/cluster/script_execution.py +2 -2
- machineconfig/cluster/script_notify_upon_completion.py +0 -1
- machineconfig/cluster/sessions_managers/archive/create_zellij_template.py +4 -6
- machineconfig/cluster/sessions_managers/archive/session_managers.py +0 -1
- machineconfig/cluster/sessions_managers/enhanced_command_runner.py +35 -75
- machineconfig/cluster/sessions_managers/wt_local.py +113 -185
- machineconfig/cluster/sessions_managers/wt_local_manager.py +127 -197
- machineconfig/cluster/sessions_managers/wt_remote.py +60 -67
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +110 -149
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +61 -64
- machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py +72 -172
- machineconfig/cluster/sessions_managers/wt_utils/remote_executor.py +27 -60
- machineconfig/cluster/sessions_managers/wt_utils/session_manager.py +58 -137
- machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +46 -74
- machineconfig/cluster/sessions_managers/zellij_local.py +91 -147
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +165 -190
- machineconfig/cluster/sessions_managers/zellij_remote.py +51 -58
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +40 -46
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +19 -17
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +30 -31
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +64 -134
- machineconfig/cluster/sessions_managers/zellij_utils/remote_executor.py +7 -11
- machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py +27 -55
- machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +14 -13
- machineconfig/cluster/templates/cli_click.py +0 -1
- machineconfig/cluster/templates/cli_gooey.py +0 -2
- machineconfig/cluster/templates/cli_trogon.py +0 -1
- machineconfig/cluster/templates/run_cloud.py +0 -1
- machineconfig/cluster/templates/run_cluster.py +0 -1
- machineconfig/cluster/templates/run_remote.py +0 -1
- machineconfig/cluster/templates/utils.py +27 -11
- machineconfig/jobs/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/linux/msc/cli_agents.sh +16 -0
- machineconfig/jobs/python/check_installations.py +9 -9
- machineconfig/jobs/python/create_bootable_media.py +0 -2
- machineconfig/jobs/python/python_cargo_build_share.py +2 -2
- machineconfig/jobs/python/python_ve_symlink.py +9 -11
- machineconfig/jobs/python/tasks.py +0 -1
- machineconfig/jobs/python/vscode/api.py +5 -5
- machineconfig/jobs/python/vscode/link_ve.py +20 -21
- machineconfig/jobs/python/vscode/select_interpreter.py +28 -29
- machineconfig/jobs/python/vscode/sync_code.py +14 -18
- machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/python_custom_installers/archive/ngrok.py +15 -15
- machineconfig/jobs/python_custom_installers/dev/aider.py +10 -18
- machineconfig/jobs/python_custom_installers/dev/alacritty.py +12 -21
- machineconfig/jobs/python_custom_installers/dev/brave.py +13 -22
- machineconfig/jobs/python_custom_installers/dev/bypass_paywall.py +13 -20
- machineconfig/jobs/python_custom_installers/dev/code.py +17 -24
- machineconfig/jobs/python_custom_installers/dev/cursor.py +10 -21
- machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +12 -11
- machineconfig/jobs/python_custom_installers/dev/espanso.py +19 -23
- machineconfig/jobs/python_custom_installers/dev/goes.py +9 -16
- machineconfig/jobs/python_custom_installers/dev/lvim.py +13 -21
- machineconfig/jobs/python_custom_installers/dev/nerdfont.py +15 -22
- machineconfig/jobs/python_custom_installers/dev/redis.py +15 -23
- machineconfig/jobs/python_custom_installers/dev/wezterm.py +15 -22
- machineconfig/jobs/python_custom_installers/dev/winget.py +32 -50
- machineconfig/jobs/python_custom_installers/docker.py +15 -24
- machineconfig/jobs/python_custom_installers/gh.py +18 -26
- machineconfig/jobs/python_custom_installers/hx.py +33 -17
- machineconfig/jobs/python_custom_installers/warp-cli.py +15 -23
- machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/python_generic_installers/config.json +412 -389
- machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/python_windows_installers/dev/config.json +1 -1
- machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +1 -1
- machineconfig/jobs/windows/msc/cli_agents.bat +0 -0
- machineconfig/jobs/windows/msc/cli_agents.ps1 +0 -0
- machineconfig/jobs/windows/start_terminal.ps1 +1 -1
- machineconfig/logger.py +50 -0
- machineconfig/profile/create.py +50 -36
- machineconfig/profile/create_hardlinks.py +33 -26
- machineconfig/profile/shell.py +87 -60
- machineconfig/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/cloud/init.sh +2 -2
- machineconfig/scripts/linux/checkout_versions +1 -1
- machineconfig/scripts/linux/choose_wezterm_theme +1 -1
- machineconfig/scripts/linux/cloud_copy +1 -1
- machineconfig/scripts/linux/cloud_manager +1 -1
- machineconfig/scripts/linux/cloud_mount +1 -1
- machineconfig/scripts/linux/cloud_repo_sync +1 -1
- machineconfig/scripts/linux/cloud_sync +1 -1
- machineconfig/scripts/linux/croshell +1 -1
- machineconfig/scripts/linux/devops +3 -5
- machineconfig/scripts/linux/fire +2 -1
- machineconfig/scripts/linux/fire_agents +3 -3
- machineconfig/scripts/linux/ftpx +1 -1
- machineconfig/scripts/linux/gh_models +1 -1
- machineconfig/scripts/linux/kill_process +1 -1
- machineconfig/scripts/linux/mcinit +2 -2
- machineconfig/scripts/linux/repos +1 -1
- machineconfig/scripts/linux/scheduler +1 -1
- machineconfig/scripts/linux/start_slidev +1 -1
- machineconfig/scripts/linux/start_terminals +1 -1
- machineconfig/scripts/linux/url2md +1 -1
- machineconfig/scripts/linux/warp-cli.sh +122 -0
- machineconfig/scripts/linux/wifi_conn +1 -1
- machineconfig/scripts/python/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/croshell.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_jobs.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/__init__.py +0 -0
- machineconfig/scripts/python/ai/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/generate_files.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/mcinit.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/chatmodes/Thinking-Beast-Mode.chatmode.md +337 -0
- machineconfig/scripts/python/ai/chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md +644 -0
- machineconfig/scripts/python/ai/chatmodes/deepResearch.chatmode.md +81 -0
- machineconfig/scripts/python/ai/configs/.gemini/settings.json +81 -0
- machineconfig/scripts/python/ai/generate_files.py +84 -0
- machineconfig/scripts/python/ai/instructions/python/dev.instructions.md +45 -0
- machineconfig/scripts/python/ai/mcinit.py +107 -0
- machineconfig/scripts/python/ai/prompts/allLintersAndTypeCheckers.prompt.md +5 -0
- machineconfig/scripts/python/ai/prompts/research-report-skeleton.prompt.md +38 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +52 -0
- machineconfig/scripts/python/archive/tmate_conn.py +5 -5
- machineconfig/scripts/python/archive/tmate_start.py +3 -3
- machineconfig/scripts/python/choose_wezterm_theme.py +2 -2
- machineconfig/scripts/python/cloud_copy.py +20 -19
- machineconfig/scripts/python/cloud_mount.py +10 -8
- machineconfig/scripts/python/cloud_repo_sync.py +15 -15
- machineconfig/scripts/python/cloud_sync.py +1 -1
- machineconfig/scripts/python/croshell.py +18 -16
- machineconfig/scripts/python/devops.py +6 -6
- machineconfig/scripts/python/devops_add_identity.py +9 -7
- machineconfig/scripts/python/devops_add_ssh_key.py +19 -19
- machineconfig/scripts/python/devops_backup_retrieve.py +14 -14
- machineconfig/scripts/python/devops_devapps_install.py +3 -3
- machineconfig/scripts/python/devops_update_repos.py +141 -53
- machineconfig/scripts/python/dotfile.py +3 -3
- machineconfig/scripts/python/fire_agents.py +202 -41
- machineconfig/scripts/python/fire_jobs.py +20 -21
- machineconfig/scripts/python/ftpx.py +4 -3
- machineconfig/scripts/python/gh_models.py +94 -94
- machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-313.pyc +0 -0
- machineconfig/scripts/python/helpers/cloud_helpers.py +3 -3
- machineconfig/scripts/python/helpers/helpers2.py +3 -3
- machineconfig/scripts/python/helpers/helpers4.py +8 -7
- machineconfig/scripts/python/helpers/helpers5.py +7 -7
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +2 -2
- machineconfig/scripts/python/mount_nfs.py +4 -3
- machineconfig/scripts/python/mount_nw_drive.py +4 -4
- machineconfig/scripts/python/mount_ssh.py +4 -3
- machineconfig/scripts/python/repos.py +9 -9
- machineconfig/scripts/python/scheduler.py +1 -1
- machineconfig/scripts/python/start_slidev.py +9 -8
- machineconfig/scripts/python/start_terminals.py +1 -1
- machineconfig/scripts/python/viewer.py +40 -40
- machineconfig/scripts/python/wifi_conn.py +65 -66
- machineconfig/scripts/python/wsl_windows_transfer.py +2 -2
- machineconfig/scripts/windows/checkout_version.ps1 +1 -3
- machineconfig/scripts/windows/choose_wezterm_theme.ps1 +1 -3
- machineconfig/scripts/windows/cloud_copy.ps1 +2 -6
- machineconfig/scripts/windows/cloud_manager.ps1 +1 -1
- machineconfig/scripts/windows/cloud_repo_sync.ps1 +1 -2
- machineconfig/scripts/windows/cloud_sync.ps1 +2 -2
- machineconfig/scripts/windows/croshell.ps1 +2 -2
- machineconfig/scripts/windows/devops.ps1 +1 -4
- machineconfig/scripts/windows/dotfile.ps1 +1 -3
- machineconfig/scripts/windows/fire.ps1 +1 -1
- machineconfig/scripts/windows/ftpx.ps1 +2 -2
- machineconfig/scripts/windows/gpt.ps1 +1 -1
- machineconfig/scripts/windows/kill_process.ps1 +1 -2
- machineconfig/scripts/windows/mcinit.ps1 +2 -2
- machineconfig/scripts/windows/mount_nfs.ps1 +1 -1
- machineconfig/scripts/windows/mount_ssh.ps1 +1 -1
- machineconfig/scripts/windows/pomodoro.ps1 +1 -1
- machineconfig/scripts/windows/py2exe.ps1 +1 -3
- machineconfig/scripts/windows/repos.ps1 +1 -1
- machineconfig/scripts/windows/scheduler.ps1 +1 -1
- machineconfig/scripts/windows/snapshot.ps1 +2 -2
- machineconfig/scripts/windows/start_slidev.ps1 +1 -1
- machineconfig/scripts/windows/start_terminals.ps1 +1 -1
- machineconfig/scripts/windows/wifi_conn.ps1 +1 -1
- machineconfig/scripts/windows/wsl_windows_transfer.ps1 +1 -3
- machineconfig/settings/lf/linux/lfrc +1 -1
- machineconfig/settings/linters/.ruff.toml +2 -2
- machineconfig/settings/linters/.ruff_cache/.gitignore +2 -0
- machineconfig/settings/linters/.ruff_cache/CACHEDIR.TAG +1 -0
- machineconfig/settings/lvim/windows/archive/config_additional.lua +1 -1
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +71 -71
- machineconfig/settings/shells/wt/settings.json +8 -8
- machineconfig/settings/svim/linux/init.toml +1 -1
- machineconfig/settings/svim/windows/init.toml +1 -1
- machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -54
- machineconfig/setup_linux/web_shortcuts/interactive.sh +6 -6
- machineconfig/setup_linux/web_shortcuts/tmp.sh +2 -0
- machineconfig/setup_windows/web_shortcuts/all.ps1 +2 -2
- machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +1 -1
- machineconfig/setup_windows/web_shortcuts/croshell.ps1 +1 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +5 -5
- machineconfig/setup_windows/wt_and_pwsh/install_fonts.ps1 +51 -15
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +75 -18
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +52 -42
- machineconfig/utils/ai/browser_user_wrapper.py +5 -5
- machineconfig/utils/ai/generate_file_checklist.py +19 -22
- machineconfig/utils/ai/url2md.py +5 -3
- machineconfig/utils/cloud/onedrive/setup_oauth.py +5 -4
- machineconfig/utils/cloud/onedrive/transaction.py +192 -227
- machineconfig/utils/code.py +71 -43
- machineconfig/utils/installer.py +77 -85
- machineconfig/utils/installer_utils/installer_abc.py +29 -17
- machineconfig/utils/installer_utils/installer_class.py +188 -83
- machineconfig/utils/io_save.py +3 -15
- machineconfig/utils/links.py +22 -11
- machineconfig/utils/notifications.py +197 -0
- machineconfig/utils/options.py +38 -25
- machineconfig/utils/path.py +18 -6
- machineconfig/utils/path_reduced.py +637 -316
- machineconfig/utils/procs.py +69 -63
- machineconfig/utils/scheduling.py +11 -13
- machineconfig/utils/ssh.py +351 -0
- machineconfig/utils/terminal.py +225 -0
- machineconfig/utils/utils.py +13 -12
- machineconfig/utils/utils2.py +43 -10
- machineconfig/utils/utils5.py +242 -46
- machineconfig/utils/ve.py +11 -6
- {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/METADATA +15 -9
- {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/RECORD +232 -235
- machineconfig/cluster/self_ssh.py +0 -57
- machineconfig/jobs/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python/archive/python_tools.txt +0 -12
- machineconfig/jobs/python/vscode/__pycache__/select_interpreter.cpython-311.pyc +0 -0
- machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/jobs/python_generic_installers/update.py +0 -3
- machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/profile/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/profile/__pycache__/create.cpython-311.pyc +0 -0
- machineconfig/profile/__pycache__/shell.cpython-311.pyc +0 -0
- machineconfig/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/linux/activate_ve +0 -87
- machineconfig/scripts/python/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/cloud_copy.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/cloud_mount.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/cloud_sync.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/croshell.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_backup_retrieve.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_agents.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_jobs.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/get_zellij_cmd.cpython-311.pyc +0 -0
- machineconfig/scripts/python/__pycache__/repos.cpython-311.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/init.cpython-311.pyc +0 -0
- machineconfig/scripts/python/ai/init.py +0 -56
- machineconfig/scripts/python/ai/rules/python/dev.md +0 -31
- machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/cloud_helpers.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers2.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-311.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/repo_sync_helpers.cpython-311.pyc +0 -0
- machineconfig/scripts/windows/activate_ve.ps1 +0 -54
- {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/WHEEL +0 -0
- {machineconfig-1.97.dist-info → machineconfig-2.1.dist-info}/top_level.txt +0 -0
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
CC
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from machineconfig.utils.path_reduced import
|
|
6
|
-
from
|
|
5
|
+
from machineconfig.utils.path_reduced import PathExtended as PathExtended
|
|
6
|
+
from tenacity import retry, stop_after_attempt, wait_chain, wait_fixed
|
|
7
7
|
import getpass
|
|
8
8
|
import argparse
|
|
9
9
|
import os
|
|
@@ -18,19 +18,19 @@ from machineconfig.utils.utils2 import pprint
|
|
|
18
18
|
|
|
19
19
|
console = Console()
|
|
20
20
|
|
|
21
|
-
@
|
|
21
|
+
@retry(stop=stop_after_attempt(3), wait=wait_chain(wait_fixed(1), wait_fixed(4), wait_fixed(9)))
|
|
22
22
|
def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] = None) -> None:
|
|
23
23
|
console.print(Panel("🚀 Secure File Downloader", title="[bold blue]Downloader[/bold blue]", border_style="blue"))
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
folder_obj = PathExtended.cwd() if folder is None else PathExtended(folder)
|
|
26
26
|
print(f"📂 Target folder: {folder_obj}")
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
if os.environ.get("DECRYPTION_PASSWORD") is not None:
|
|
29
29
|
print("🔑 Using password from environment variables")
|
|
30
30
|
pwd = str(os.environ.get("DECRYPTION_PASSWORD"))
|
|
31
31
|
else:
|
|
32
32
|
pwd = getpass.getpass(prompt="🔑 Enter decryption password: ")
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
if url is None:
|
|
35
35
|
if os.environ.get("SHARE_URL") is not None:
|
|
36
36
|
url = os.environ.get("SHARE_URL")
|
|
@@ -38,21 +38,22 @@ def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] =
|
|
|
38
38
|
print("🔗 Using URL from environment variables")
|
|
39
39
|
else:
|
|
40
40
|
url = input("🔗 Enter share URL: ")
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
console.print(Panel("📡 Downloading from URL...", title="[bold blue]Download[/bold blue]", border_style="blue"))
|
|
43
43
|
with Progress(transient=True) as progress:
|
|
44
44
|
_task = progress.add_task("Downloading... ", total=None)
|
|
45
45
|
url_obj = PathExtended(url).download(folder=folder_obj)
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
console.print(Panel(f"📥 Downloaded file: {url_obj}", title="[bold green]Success[/bold green]", border_style="green"))
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
console.print(Panel("🔐 Decrypting and extracting...", title="[bold blue]Processing[/bold blue]", border_style="blue"))
|
|
50
50
|
with Progress(transient=True) as progress:
|
|
51
51
|
_task = progress.add_task("Decrypting... ", total=None)
|
|
52
52
|
tmp_folder = PathExtended.tmpdir(prefix="tmp_unzip")
|
|
53
53
|
try:
|
|
54
54
|
res = url_obj.decrypt(pwd=pwd, inplace=True).unzip(inplace=True, folder=tmp_folder)
|
|
55
|
-
res.search("*")
|
|
55
|
+
for x in res.search("*"):
|
|
56
|
+
x.move(folder=folder_obj, overwrite=True)
|
|
56
57
|
finally:
|
|
57
58
|
# Clean up temporary folder
|
|
58
59
|
if tmp_folder.exists():
|
|
@@ -61,7 +62,7 @@ def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] =
|
|
|
61
62
|
|
|
62
63
|
def arg_parser() -> None:
|
|
63
64
|
console.print(Panel("☁️ Cloud Copy Utility", title="[bold blue]Cloud Copy[/bold blue]", border_style="blue", width=152))
|
|
64
|
-
|
|
65
|
+
|
|
65
66
|
parser = argparse.ArgumentParser(description='🚀 Cloud CLI. It wraps rclone with sane defaults for optimum type time.')
|
|
66
67
|
|
|
67
68
|
# positional argument
|
|
@@ -105,40 +106,40 @@ def arg_parser() -> None:
|
|
|
105
106
|
|
|
106
107
|
console.print(Panel("🔍 Parsing source and target paths...", title="[bold blue]Info[/bold blue]", border_style="blue"))
|
|
107
108
|
cloud, source, target = parse_cloud_source_target(args=args_obj, source=source, target=target)
|
|
108
|
-
|
|
109
|
+
|
|
109
110
|
console.print(Panel("⚙️ Configuration:", title="[bold blue]Config[/bold blue]", border_style="blue"))
|
|
110
111
|
pprint(args_obj.__dict__, "CLI config")
|
|
111
112
|
|
|
112
113
|
if args_obj.key is not None:
|
|
113
114
|
console.print(Panel("❌ Key-based encryption is not supported yet", title="[bold red]Error[/bold red]", border_style="red"))
|
|
114
115
|
raise ValueError("Key-based encryption is not supported yet.")
|
|
115
|
-
|
|
116
|
+
|
|
116
117
|
if cloud in source:
|
|
117
118
|
console.print(Panel(f"📥 DOWNLOADING FROM CLOUD\n☁️ Cloud: {cloud}\n📂 Source: {source.replace(cloud + ':', '')}\n🎯 Target: {target}", title="[bold blue]Download[/bold blue]", border_style="blue", width=152))
|
|
118
|
-
|
|
119
|
+
|
|
119
120
|
PathExtended(target).from_cloud(cloud=cloud, remotepath=source.replace(cloud + ":", ""),
|
|
120
121
|
unzip=args_obj.zip, decrypt=args_obj.encrypt, pwd=args_obj.pwd,
|
|
121
122
|
overwrite=args_obj.overwrite,
|
|
122
123
|
rel2home=args_obj.rel2home, os_specific=args_obj.os_specific, root=args_obj.root, strict=False,
|
|
123
124
|
)
|
|
124
125
|
console.print(Panel("✅ Download completed successfully", title="[bold green]Success[/bold green]", border_style="green", width=152))
|
|
125
|
-
|
|
126
|
+
|
|
126
127
|
elif cloud in target:
|
|
127
128
|
console.print(Panel(f"📤 UPLOADING TO CLOUD\n☁️ Cloud: {cloud}\n📂 Source: {source}\n🎯 Target: {target.replace(cloud + ':', '')}", title="[bold blue]Upload[/bold blue]", border_style="blue", width=152))
|
|
128
|
-
|
|
129
|
+
|
|
129
130
|
res = PathExtended(source).to_cloud(cloud=cloud, remotepath=target.replace(cloud + ":", ""),
|
|
130
131
|
zip=args_obj.zip, encrypt=args_obj.encrypt, pwd=args_obj.pwd,
|
|
131
132
|
rel2home=args_obj.rel2home, root=args_obj.root, os_specific=args_obj.os_specific, strict=False,
|
|
132
133
|
share=args_obj.share)
|
|
133
134
|
console.print(Panel("✅ Upload completed successfully", title="[bold green]Success[/bold green]", border_style="green", width=152))
|
|
134
|
-
|
|
135
|
+
|
|
135
136
|
if args_obj.share:
|
|
136
137
|
fname = f".share_url_{cloud}"
|
|
137
138
|
if PathExtended(source).is_dir(): share_url_path = PathExtended(source).joinpath(fname)
|
|
138
139
|
else: share_url_path = PathExtended(source).with_suffix(fname)
|
|
139
|
-
share_url_path.write_text(res.as_url_str())
|
|
140
|
+
share_url_path.write_text(res.as_url_str(), encoding="utf-8")
|
|
140
141
|
console.print(Panel(f"🔗 SHARE URL GENERATED\n📝 URL file: {share_url_path}\n🌍 {res.as_url_str()}", title="[bold blue]Share[/bold blue]", border_style="blue", width=152))
|
|
141
|
-
else:
|
|
142
|
+
else:
|
|
142
143
|
console.print(Panel(f"❌ ERROR: Cloud '{cloud}' not found in source or target", title="[bold red]Error[/bold red]", border_style="red", width=152))
|
|
143
144
|
raise ValueError(f"Cloud `{cloud}` not found in source or target.")
|
|
144
145
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from machineconfig.utils.utils import PROGRAM_PATH, choose_one_option
|
|
6
6
|
from machineconfig.utils.utils2 import read_ini
|
|
7
|
-
from machineconfig.utils.path_reduced import
|
|
7
|
+
from machineconfig.utils.path_reduced import PathExtended as PathExtended
|
|
8
8
|
|
|
9
9
|
import platform
|
|
10
10
|
import argparse
|
|
@@ -28,13 +28,15 @@ def get_rclone_config():
|
|
|
28
28
|
def get_mprocs_mount_txt(cloud: str, rclone_cmd: str, cloud_brand: str): # cloud_brand = config[cloud]["type"]
|
|
29
29
|
header = f"{' ' + cloud + ' | ' + cloud_brand + ' '}".center(50, "=")
|
|
30
30
|
if platform.system() == "Windows":
|
|
31
|
-
sub_text_path = PathExtended.tmpfile(suffix=".ps1")
|
|
31
|
+
sub_text_path = PathExtended.tmpfile(suffix=".ps1")
|
|
32
|
+
sub_text_path.parent.mkdir(parents=True, exist_ok=True)
|
|
33
|
+
sub_text_path.write_text(f"""
|
|
32
34
|
echo "{header}"
|
|
33
35
|
iex 'rclone about {cloud}:'
|
|
34
36
|
echo 'See {DEFAULT_MOUNT}/{cloud} for the mounted cloud'
|
|
35
37
|
|
|
36
38
|
echo ''
|
|
37
|
-
""")
|
|
39
|
+
""", encoding="utf-8")
|
|
38
40
|
txt = f"""
|
|
39
41
|
cd ~
|
|
40
42
|
mprocs "powershell {sub_text_path}" "{rclone_cmd}" "btm" "timeout 2 & cd {DEFAULT_MOUNT} & lf" "timeout 2 & cd {DEFAULT_MOUNT} & pwsh" "pwsh" --names "info,service,monitor,explorer,main,terminal"
|
|
@@ -49,7 +51,7 @@ def mount(cloud: Optional[str], network: Optional[str], destination: Optional[st
|
|
|
49
51
|
# draw header box dynamically
|
|
50
52
|
title = "☁️ Cloud Mount Utility"
|
|
51
53
|
console.print(Panel(title, title_align="left", border_style="blue"))
|
|
52
|
-
|
|
54
|
+
|
|
53
55
|
config = get_rclone_config()
|
|
54
56
|
if cloud is None:
|
|
55
57
|
res = choose_one_option(msg="which cloud", options=config.sections(), header="CLOUD MOUNT", default=None)
|
|
@@ -62,7 +64,7 @@ def mount(cloud: Optional[str], network: Optional[str], destination: Optional[st
|
|
|
62
64
|
mount_loc = PathExtended(DEFAULT_MOUNT).expanduser().joinpath(cloud)
|
|
63
65
|
else:
|
|
64
66
|
mount_loc = PathExtended(destination)
|
|
65
|
-
|
|
67
|
+
|
|
66
68
|
mount_info = f"📂 Mount location: {mount_loc}"
|
|
67
69
|
console.print(Panel(mount_info, border_style="blue"))
|
|
68
70
|
|
|
@@ -81,7 +83,7 @@ def mount(cloud: Optional[str], network: Optional[str], destination: Optional[st
|
|
|
81
83
|
pass
|
|
82
84
|
else: raise ValueError("unsupported platform")
|
|
83
85
|
|
|
84
|
-
elif network and platform.system() == "Windows":
|
|
86
|
+
elif network and platform.system() == "Windows":
|
|
85
87
|
mount_loc = "X: --network-mode"
|
|
86
88
|
print(f"🔌 Setting up network mount at {mount_loc}")
|
|
87
89
|
else: raise ValueError("network mount only supported on windows")
|
|
@@ -130,7 +132,7 @@ zellij action move-focus up
|
|
|
130
132
|
"""
|
|
131
133
|
else: raise ValueError("unsupported platform")
|
|
132
134
|
# print(f"running command: \n{txt}")
|
|
133
|
-
PROGRAM_PATH.write_text(txt)
|
|
135
|
+
PROGRAM_PATH.write_text(txt, encoding="utf-8")
|
|
134
136
|
# draw success box dynamically
|
|
135
137
|
title1 = "✅ Cloud mount command prepared successfully"
|
|
136
138
|
title2 = "🔄 Running mount process..."
|
|
@@ -141,7 +143,7 @@ def main():
|
|
|
141
143
|
# draw main title box dynamically
|
|
142
144
|
main_title = "☁️ RCLONE CLOUD MOUNT"
|
|
143
145
|
console.print(Panel(main_title, title_align="left", border_style="blue"))
|
|
144
|
-
|
|
146
|
+
|
|
145
147
|
parser = argparse.ArgumentParser(description='mount cloud')
|
|
146
148
|
parser.add_argument('cloud', nargs='?', type=str, default=None, help='cloud to mount')
|
|
147
149
|
parser.add_argument('destination', nargs='?', type=str, default=None, help='destination to mount')
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""utils"""
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
import git
|
|
4
|
-
from machineconfig.utils.path_reduced import
|
|
5
|
-
from
|
|
5
|
+
from machineconfig.utils.path_reduced import PathExtended as PathExtended
|
|
6
|
+
from machineconfig.utils.terminal import Terminal
|
|
6
7
|
from machineconfig.utils.utils2 import randstr, read_ini
|
|
7
8
|
|
|
8
9
|
from machineconfig.scripts.python.helpers.repo_sync_helpers import fetch_dotfiles
|
|
@@ -13,7 +14,6 @@ import argparse
|
|
|
13
14
|
from typing import Optional, Literal
|
|
14
15
|
from rich.console import Console
|
|
15
16
|
from rich.panel import Panel
|
|
16
|
-
# from rich.text import Text
|
|
17
17
|
|
|
18
18
|
console = Console()
|
|
19
19
|
|
|
@@ -31,14 +31,14 @@ def main(cloud: Optional[str] = None, path: Optional[str] = None, message: Optio
|
|
|
31
31
|
console.print(Panel(f"❌ ERROR: No cloud profile found\nLocation: {DEFAULTS_PATH}\nPlease set one up or provide one via the --cloud flag.", title="Error", border_style="red"))
|
|
32
32
|
return ""
|
|
33
33
|
else: cloud_resolved = cloud
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
# repo_root = PathExtended(args.repo).expanduser().absolute()
|
|
36
36
|
repo_local_root = PathExtended.cwd() if path is None else PathExtended(path).expanduser().absolute()
|
|
37
37
|
repo_local_obj = git.Repo(repo_local_root, search_parent_directories=True)
|
|
38
38
|
repo_local_root = PathExtended(repo_local_obj.working_dir) # cwd might have been in a sub directory of repo_root, so its better to redefine it.
|
|
39
39
|
CONFIG_PATH.joinpath("remote").mkdir(parents=True, exist_ok=True)
|
|
40
40
|
repo_remote_root = CONFIG_PATH.joinpath("remote", repo_local_root.rel2home()) # .delete(sure=True)
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
try:
|
|
43
43
|
console.print(Panel("📥 DOWNLOADING REMOTE REPOSITORY", title_align="left", border_style="blue"))
|
|
44
44
|
remote_path = repo_local_root.get_remote_path(rel2home=True, os_specific=False, root="myhome") + ".zip.enc"
|
|
@@ -47,7 +47,7 @@ def main(cloud: Optional[str] = None, path: Optional[str] = None, message: Optio
|
|
|
47
47
|
console.print(Panel("🆕 Remote repository doesn't exist\n📤 Creating new remote and exiting...", title_align="left", border_style="green"))
|
|
48
48
|
repo_local_root.to_cloud(cloud=cloud_resolved, zip=True, encrypt=True, rel2home=True, pwd=pwd, os_specific=False)
|
|
49
49
|
return ""
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
repo_remote_obj = git.Repo(repo_remote_root)
|
|
52
52
|
if repo_remote_obj.is_dirty():
|
|
53
53
|
console.print(Panel(f"⚠️ WARNING: REMOTE REPOSITORY IS DIRTY\nLocation: {repo_remote_root}\nPlease commit or stash changes before proceeding.", title="Warning", border_style="yellow"))
|
|
@@ -92,7 +92,7 @@ git pull originEnc master
|
|
|
92
92
|
from machineconfig.scripts.python.helpers.repo_sync_helpers import delete_remote_repo_copy_and_push_local as func
|
|
93
93
|
func(remote_repo=r'{str(repo_remote_root)}', local_repo=r'{str(repo_local_root)}', cloud=r'{cloud_resolved}')
|
|
94
94
|
"""
|
|
95
|
-
shell_file_1 = get_shell_file_executing_python_script(python_script=program_1_py,
|
|
95
|
+
shell_file_1 = get_shell_file_executing_python_script(python_script=program_1_py, ve_path=str(Path.home().joinpath("code", "crocodile", ".venv")))
|
|
96
96
|
# ================================================================================
|
|
97
97
|
|
|
98
98
|
option2 = 'Delete local repo and replace it with remote copy:'
|
|
@@ -114,7 +114,7 @@ sudo chmod +x $HOME/dotfiles/scripts/linux -R
|
|
|
114
114
|
from machineconfig.scripts.python.helper.repo_sync_helpers import inspect_repos as func
|
|
115
115
|
func(repo_local_root=r'{str(repo_local_root)}', repo_remote_root=r'{str(repo_remote_root)}')
|
|
116
116
|
"""
|
|
117
|
-
shell_file_3 = get_shell_file_executing_python_script(python_script=program_3_py,
|
|
117
|
+
shell_file_3 = get_shell_file_executing_python_script(python_script=program_3_py, ve_path=str(Path.home().joinpath("code", "crocodile", ".venv")))
|
|
118
118
|
# ================================================================================
|
|
119
119
|
|
|
120
120
|
option4 = 'Remove problematic rclone file from repo and replace with remote:'
|
|
@@ -129,7 +129,7 @@ git commit -am "finished merging"
|
|
|
129
129
|
# ================================================================================
|
|
130
130
|
|
|
131
131
|
console.print(Panel("🔄 RESOLVE MERGE CONFLICT\nChoose an option to resolve the conflict:", title_align="left", border_style="blue"))
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
print(f"• 1️⃣ {option1:75} 👉 {shell_file_1}")
|
|
134
134
|
print(f"• 2️⃣ {option2:75} 👉 {shell_file_2}")
|
|
135
135
|
print(f"• 3️⃣ {option3:75} 👉 {shell_file_3}")
|
|
@@ -139,18 +139,18 @@ git commit -am "finished merging"
|
|
|
139
139
|
match action:
|
|
140
140
|
case "ask":
|
|
141
141
|
choice = choose_one_option(options=[option1, option2, option3, option4], fzf=False)
|
|
142
|
-
if choice == option1: program_content = shell_file_1.read_text()
|
|
142
|
+
if choice == option1: program_content = shell_file_1.read_text(encoding="utf-8")
|
|
143
143
|
elif choice == option2: program_content = program_2
|
|
144
|
-
elif choice == option3: program_content = shell_file_3.read_text()
|
|
144
|
+
elif choice == option3: program_content = shell_file_3.read_text(encoding="utf-8")
|
|
145
145
|
elif choice == option4: program_content = program_4
|
|
146
146
|
else: raise NotImplementedError(f"Choice {choice} not implemented.")
|
|
147
|
-
case "pushLocalMerge": program_content = shell_file_1.read_text()
|
|
147
|
+
case "pushLocalMerge": program_content = shell_file_1.read_text(encoding="utf-8")
|
|
148
148
|
case "overwriteLocal": program_content = program_2
|
|
149
|
-
case "InspectRepos": program_content = shell_file_3.read_text()
|
|
149
|
+
case "InspectRepos": program_content = shell_file_3.read_text(encoding="utf-8")
|
|
150
150
|
case "RemoveLocalRclone": program_content = program_4
|
|
151
|
-
case _:
|
|
151
|
+
case _:
|
|
152
152
|
raise ValueError(f"Unknown action: {action}")
|
|
153
|
-
PROGRAM_PATH.write_text(program_content)
|
|
153
|
+
PROGRAM_PATH.write_text(program_content, encoding="utf-8")
|
|
154
154
|
return program_content
|
|
155
155
|
|
|
156
156
|
def args_parser():
|
|
@@ -75,7 +75,7 @@ def args_parser():
|
|
|
75
75
|
cmd_line = f"{rclone_cmd[:65]}..."
|
|
76
76
|
console.print(Panel(f"{title}\n{cmd_line}", title="[bold blue]Command[/bold blue]", expand=False))
|
|
77
77
|
|
|
78
|
-
PROGRAM_PATH.write_text(txt)
|
|
78
|
+
PROGRAM_PATH.write_text(txt, encoding="utf-8")
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
if __name__ == '__main__':
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env -S uv run --project
|
|
2
|
+
|
|
1
3
|
"""
|
|
2
4
|
croshell
|
|
3
5
|
"""
|
|
4
6
|
|
|
5
7
|
import argparse
|
|
6
|
-
from machineconfig.utils.path_reduced import
|
|
8
|
+
from machineconfig.utils.path_reduced import PathExtended as PathExtended
|
|
7
9
|
from machineconfig.utils.utils2 import randstr
|
|
8
10
|
from machineconfig.utils.utils import PROGRAM_PATH, display_options
|
|
9
11
|
from machineconfig.utils.ve import get_ve_path_and_ipython_profile, get_ve_activate_line
|
|
@@ -18,7 +20,7 @@ console = Console()
|
|
|
18
20
|
|
|
19
21
|
def add_print_header_pycode(path: str, title: str):
|
|
20
22
|
return f"""
|
|
21
|
-
# from machineconfig.utils.path_reduced import P as PathExtended
|
|
23
|
+
# from machineconfig.utils.path_reduced import P as PathExtended
|
|
22
24
|
from crocodile.file_management import P as PathExtended
|
|
23
25
|
pycode = PathExtended(r'{path}').read_text(encoding="utf-8")
|
|
24
26
|
pycode = pycode.split("except Exception: print(pycode)")[2]
|
|
@@ -112,7 +114,7 @@ def build_parser():
|
|
|
112
114
|
elif args.fzf:
|
|
113
115
|
text = "🔍 Searching for Python files..."
|
|
114
116
|
console.print(Panel(text, title="[bold blue]Info[/bold blue]"))
|
|
115
|
-
options = PathExtended.cwd().search("*.py", r=True)
|
|
117
|
+
options = [str(item) for item in PathExtended.cwd().search("*.py", r=True)]
|
|
116
118
|
file = display_options(msg="Choose a python file to run", options=options, fzf=True, multi=False, )
|
|
117
119
|
assert isinstance(file, str)
|
|
118
120
|
program = PathExtended(file).read_text(encoding='utf-8')
|
|
@@ -128,16 +130,16 @@ def build_parser():
|
|
|
128
130
|
|
|
129
131
|
elif args.read != "":
|
|
130
132
|
if args.streamlit_viewer:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
#!/bin/bash
|
|
137
|
-
. $HOME/scripts/activate_ve '
|
|
138
|
-
streamlit run {py_file_path}
|
|
139
|
-
"""
|
|
140
|
-
|
|
133
|
+
# text = "📊 STARTING STREAMLIT VIEWER"
|
|
134
|
+
# console.print(Panel(text, title="[bold blue]Info[/bold blue]"))
|
|
135
|
+
# from machineconfig.scripts.python.viewer import run
|
|
136
|
+
# py_file_path = run(data_path=args.read, data=None, get_figure=None)
|
|
137
|
+
# final_program = f"""
|
|
138
|
+
# #!/bin/bash
|
|
139
|
+
# . $HOME/scripts/activate_ve '.venv'
|
|
140
|
+
# streamlit run {py_file_path}
|
|
141
|
+
# """
|
|
142
|
+
# PROGRAM_PATH.write_text(data=final_program, encoding="utf-8")
|
|
141
143
|
return None
|
|
142
144
|
file = PathExtended(str(args.read).lstrip()).expanduser().absolute()
|
|
143
145
|
program = get_read_data_pycode(str(file))
|
|
@@ -173,7 +175,7 @@ print_logo(logo="crocodile")
|
|
|
173
175
|
ve_root_from_file, ipython_profile = get_ve_path_and_ipython_profile(PathExtended(file))
|
|
174
176
|
ipython_profile = ipython_profile if ipython_profile is not None else "default"
|
|
175
177
|
# ve_activateion_line = get_ve_activate_line(ve_name=args.ve or ve_profile_suggested, a_path=str(PathExtended.cwd()))
|
|
176
|
-
activate_ve_line = get_ve_activate_line(ve_root=args.ve or ve_root_from_file or "$HOME/
|
|
178
|
+
activate_ve_line = get_ve_activate_line(ve_root=args.ve or ve_root_from_file or "$HOME/code/machineconfig/.venv")
|
|
177
179
|
final_program = f"""
|
|
178
180
|
#!/bin/bash
|
|
179
181
|
|
|
@@ -187,7 +189,7 @@ print_logo(logo="crocodile")
|
|
|
187
189
|
if interpreter == "ipython":
|
|
188
190
|
fire_line += f" {interactivity} --profile {ipython_profile} --no-banner"
|
|
189
191
|
fire_line += f" {str(pyfile)}"
|
|
190
|
-
|
|
192
|
+
|
|
191
193
|
final_program += fire_line
|
|
192
194
|
|
|
193
195
|
title = "🚀 LAUNCHING SCRIPT"
|
|
@@ -196,7 +198,7 @@ print_logo(logo="crocodile")
|
|
|
196
198
|
launch_message = f"{title} {PROGRAM_PATH}\n{text1}\n{text2}"
|
|
197
199
|
console.print(Panel(Text(launch_message, justify="left"), expand=False, border_style="blue"))
|
|
198
200
|
|
|
199
|
-
PROGRAM_PATH.write_text(data=final_program)
|
|
201
|
+
PROGRAM_PATH.write_text(data=final_program, encoding="utf-8")
|
|
200
202
|
# (PROGRAM_PATH + ".py").write_text(str(pyfile), encoding='utf-8')
|
|
201
203
|
|
|
202
204
|
# if platform.system() == "Windows":
|
|
@@ -33,7 +33,7 @@ class Options(Enum):
|
|
|
33
33
|
def args_parser():
|
|
34
34
|
# Print header
|
|
35
35
|
console.print(Panel("🛠️ DevOps Tool Suite", title_align="left", border_style="blue", width=BOX_WIDTH))
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
import argparse
|
|
38
38
|
parser = argparse.ArgumentParser()
|
|
39
39
|
new_line = "\n\n"
|
|
@@ -67,7 +67,7 @@ def display_task_success(success: str) -> None:
|
|
|
67
67
|
def main(which: Optional[str] = None):
|
|
68
68
|
PROGRAM_PATH.delete(sure=True, verbose=False)
|
|
69
69
|
console.print(Panel("🚀 Initializing DevOps operation...", width=BOX_WIDTH, border_style="blue"))
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
options = [op.value for op in Options]
|
|
72
72
|
if which is None:
|
|
73
73
|
try:
|
|
@@ -128,7 +128,7 @@ def main(which: Optional[str] = None):
|
|
|
128
128
|
console.print(Panel("💾 Creating backup...", width=BOX_WIDTH, border_style="blue"))
|
|
129
129
|
from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve as helper
|
|
130
130
|
program = helper(direction="BACKUP")
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
elif choice_key == Options.retreive.value:
|
|
133
133
|
console.print(Panel("📥 Retrieving backup...", width=BOX_WIDTH, border_style="blue"))
|
|
134
134
|
from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve as helper
|
|
@@ -145,14 +145,14 @@ def main(which: Optional[str] = None):
|
|
|
145
145
|
from machineconfig.scripts.python.cloud_repo_sync import main as helper, PathExtended
|
|
146
146
|
program = helper(cloud=None, path=str(PathExtended.home() / "dotfiles"), pwd=None, action="ask")
|
|
147
147
|
|
|
148
|
-
else:
|
|
148
|
+
else:
|
|
149
149
|
console.print(Panel("❌ ERROR: Invalid choice", title_align="left", border_style="red", width=BOX_WIDTH))
|
|
150
150
|
raise ValueError(f"Unimplemented choice: {choice_key}")
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
if program:
|
|
153
153
|
console.print(Panel("📜 Preparing shell script...", width=BOX_WIDTH, border_style="blue"))
|
|
154
154
|
write_shell_script_to_default_program_path(program=program, display=True, preserve_cwd=True, desc="🔧 Shell script prepared by Python.", execute=True if which is not None else False)
|
|
155
|
-
else:
|
|
155
|
+
else:
|
|
156
156
|
write_shell_script_to_default_program_path(program="echo '✨ Done.'", display=False, desc="🔧 Shell script prepared by Python.", preserve_cwd=True, execute=False)
|
|
157
157
|
|
|
158
158
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
# from platform import system
|
|
6
|
-
from machineconfig.utils.path_reduced import
|
|
6
|
+
from machineconfig.utils.path_reduced import PathExtended as PathExtended, modify_text
|
|
7
7
|
from machineconfig.utils.options import display_options
|
|
8
8
|
from rich.panel import Panel
|
|
9
9
|
from rich.text import Text
|
|
@@ -17,14 +17,14 @@ def main():
|
|
|
17
17
|
|
|
18
18
|
print(Panel("🔍 Searching for existing SSH keys...", expand=False))
|
|
19
19
|
|
|
20
|
-
private_keys = PathExtended.home().joinpath(".ssh").search("*.pub")
|
|
21
|
-
|
|
20
|
+
private_keys = [x.with_name(x.stem) for x in PathExtended.home().joinpath(".ssh").search("*.pub")]
|
|
21
|
+
private_keys = [x for x in private_keys if x.exists()]
|
|
22
22
|
if private_keys:
|
|
23
23
|
print(Panel(f"✅ Found {len(private_keys)} SSH private key(s)", expand=False))
|
|
24
24
|
else:
|
|
25
25
|
print(Panel("⚠️ No SSH private keys found", expand=False))
|
|
26
26
|
|
|
27
|
-
choice = display_options(msg="Path to private key to be used when ssh'ing: ", options=
|
|
27
|
+
choice = display_options(msg="Path to private key to be used when ssh'ing: ", options=[str(x) for x in private_keys] + ["I have the path to the key file", "I want to paste the key itself"])
|
|
28
28
|
|
|
29
29
|
if choice == "I have the path to the key file":
|
|
30
30
|
print(Panel("📄 Please enter the path to your private key file", expand=False))
|
|
@@ -34,7 +34,9 @@ def main():
|
|
|
34
34
|
elif choice == "I want to paste the key itself":
|
|
35
35
|
print(Panel("📋 Please provide a filename and paste the private key content", expand=False))
|
|
36
36
|
key_filename = input("📝 File name (default: my_pasted_key): ") or "my_pasted_key"
|
|
37
|
-
path_to_key = PathExtended.home().joinpath(f".ssh/{key_filename}")
|
|
37
|
+
path_to_key = PathExtended.home().joinpath(f".ssh/{key_filename}")
|
|
38
|
+
path_to_key.parent.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
path_to_key.write_text(input("🔑 Paste the private key here: "), encoding="utf-8")
|
|
38
40
|
print(Panel(f"💾 Key saved to: {path_to_key}", expand=False))
|
|
39
41
|
|
|
40
42
|
elif isinstance(choice, str):
|
|
@@ -55,7 +57,7 @@ def main():
|
|
|
55
57
|
# - If file doesn't exist, seed content with txt_search
|
|
56
58
|
# - Then run modify_text to replace/append accordingly and write back
|
|
57
59
|
if config_path.exists():
|
|
58
|
-
current = config_path.read_text()
|
|
60
|
+
current = config_path.read_text(encoding="utf-8")
|
|
59
61
|
print(Panel("✏️ Updated existing SSH config file", expand=False))
|
|
60
62
|
else:
|
|
61
63
|
current = txt
|
|
@@ -68,7 +70,7 @@ def main():
|
|
|
68
70
|
notfound_append=True,
|
|
69
71
|
prepend=True,
|
|
70
72
|
)
|
|
71
|
-
config_path.write_text(new_content)
|
|
73
|
+
config_path.write_text(new_content, encoding="utf-8")
|
|
72
74
|
|
|
73
75
|
panel_complete = Panel(
|
|
74
76
|
Text(
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from platform import system
|
|
6
6
|
from machineconfig.utils.utils import LIBRARY_ROOT, display_options
|
|
7
|
-
from machineconfig.utils.path_reduced import
|
|
7
|
+
from machineconfig.utils.path_reduced import PathExtended as PathExtended
|
|
8
8
|
from rich.console import Console
|
|
9
9
|
from rich.panel import Panel
|
|
10
10
|
from rich import box # Import box
|
|
@@ -28,11 +28,11 @@ def get_add_ssh_key_script(path_to_key: PathExtended):
|
|
|
28
28
|
|
|
29
29
|
if authorized_keys.exists():
|
|
30
30
|
split = "\n"
|
|
31
|
-
keys_text = authorized_keys.read_text().split(split)
|
|
31
|
+
keys_text = authorized_keys.read_text(encoding="utf-8").split(split)
|
|
32
32
|
key_count = len([k for k in keys_text if k.strip()])
|
|
33
33
|
console.print(Panel(f"🔍 Current SSH authorization status\n✅ Found {key_count} authorized key(s)", title="[bold blue]Status[/bold blue]"))
|
|
34
34
|
|
|
35
|
-
if path_to_key.read_text() in authorized_keys.read_text():
|
|
35
|
+
if path_to_key.read_text(encoding="utf-8") in authorized_keys.read_text(encoding="utf-8"):
|
|
36
36
|
console.print(Panel(f"⚠️ Key already authorized\nKey: {path_to_key.name}\nStatus: Already present in authorized_keys file\nNo action required", title="[bold yellow]Warning[/bold yellow]"))
|
|
37
37
|
program = ""
|
|
38
38
|
else:
|
|
@@ -41,7 +41,7 @@ def get_add_ssh_key_script(path_to_key: PathExtended):
|
|
|
41
41
|
program = f"cat {path_to_key} >> ~/.ssh/authorized_keys"
|
|
42
42
|
elif system() == "Windows":
|
|
43
43
|
program_path = LIBRARY_ROOT.joinpath("setup_windows/openssh-server_add-sshkey.ps1")
|
|
44
|
-
program = program_path.expanduser().read_text()
|
|
44
|
+
program = program_path.expanduser().read_text(encoding="utf-8")
|
|
45
45
|
place_holder = r'$sshfile = "$env:USERPROFILE\.ssh\pubkey.pub"'
|
|
46
46
|
assert place_holder in program, f"This section performs string manipulation on the script {program_path} to add the key to the authorized_keys file. The script has changed and the string {place_holder} is not found."
|
|
47
47
|
program = program.replace(place_holder, f'$sshfile = "{path_to_key}"')
|
|
@@ -53,7 +53,7 @@ def get_add_ssh_key_script(path_to_key: PathExtended):
|
|
|
53
53
|
program = f"cat {path_to_key} > ~/.ssh/authorized_keys"
|
|
54
54
|
else:
|
|
55
55
|
program_path = LIBRARY_ROOT.joinpath("setup_windows/openssh-server_add-sshkey.ps1")
|
|
56
|
-
program = PathExtended(program_path).expanduser().read_text().replace('$sshfile=""', f'$sshfile="{path_to_key}"')
|
|
56
|
+
program = PathExtended(program_path).expanduser().read_text(encoding="utf-8").replace('$sshfile=""', f'$sshfile="{path_to_key}"')
|
|
57
57
|
console.print(Panel("🔧 Configured PowerShell script for Windows\n📝 Set key path in script", title="[bold blue]Configuration[/bold blue]"))
|
|
58
58
|
|
|
59
59
|
if system() == "Linux":
|
|
@@ -70,47 +70,47 @@ sudo service ssh --full-restart
|
|
|
70
70
|
|
|
71
71
|
def main():
|
|
72
72
|
console.print(Panel("🔐 SSH PUBLIC KEY AUTHORIZATION TOOL", box=box.DOUBLE_EDGE, title_align="left"))
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
console.print(Panel("🔍 Searching for public keys...", title="[bold blue]SSH Setup[/bold blue]", border_style="blue"))
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
pub_keys = PathExtended.home().joinpath(".ssh").search("*.pub")
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
if pub_keys:
|
|
79
79
|
console.print(Panel(f"✅ Found {len(pub_keys)} public key(s)", title="[bold green]Status[/bold green]", border_style="green"))
|
|
80
80
|
else:
|
|
81
81
|
console.print(Panel("⚠️ No public keys found", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
all_keys_option = f"all pub keys available ({len(pub_keys)})"
|
|
84
84
|
i_have_path_option = "I have the path to the key file"
|
|
85
85
|
i_paste_option = "I want to paste the key itself"
|
|
86
|
-
|
|
87
|
-
res = display_options("Which public key to add? ", options=
|
|
86
|
+
|
|
87
|
+
res = display_options("Which public key to add? ", options=[str(x) for x in pub_keys] + [all_keys_option, i_have_path_option, i_paste_option])
|
|
88
88
|
assert isinstance(res, str), f"Got {res} of type {type(res)} instead of str."
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
if res == all_keys_option:
|
|
91
91
|
console.print(Panel(f"🔄 Processing all {len(pub_keys)} public keys...", title="[bold blue]Processing[/bold blue]", border_style="blue"))
|
|
92
|
-
program = "\n\n\n".join(
|
|
93
|
-
|
|
92
|
+
program = "\n\n\n".join([get_add_ssh_key_script(key) for key in pub_keys])
|
|
93
|
+
|
|
94
94
|
elif res == i_have_path_option:
|
|
95
95
|
console.print(Panel("📂 Please provide the path to your public key", title="[bold blue]Input Required[/bold blue]", border_style="blue"))
|
|
96
96
|
key_path = PathExtended(input("📋 Path: ")).expanduser().absolute()
|
|
97
97
|
console.print(Panel(f"📄 Using key from path: {key_path}", title="[bold blue]Info[/bold blue]", border_style="blue"))
|
|
98
98
|
program = get_add_ssh_key_script(key_path)
|
|
99
|
-
|
|
99
|
+
|
|
100
100
|
elif res == i_paste_option:
|
|
101
101
|
console.print(Panel("📋 Please provide a filename and paste the public key content", title="[bold blue]Input Required[/bold blue]", border_style="blue"))
|
|
102
102
|
key_filename = input("📝 File name (default: my_pasted_key.pub): ") or "my_pasted_key.pub"
|
|
103
103
|
key_path = PathExtended.home().joinpath(f".ssh/{key_filename}")
|
|
104
|
-
key_path.write_text(input("🔑 Paste the public key here: "))
|
|
104
|
+
key_path.write_text(input("🔑 Paste the public key here: "), encoding="utf-8")
|
|
105
105
|
console.print(Panel(f"💾 Key saved to: {key_path}", title="[bold green]Success[/bold green]", border_style="green"))
|
|
106
106
|
program = get_add_ssh_key_script(key_path)
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
else:
|
|
109
109
|
console.print(Panel(f"🔑 Using selected key: {PathExtended(res).name}", title="[bold blue]Info[/bold blue]", border_style="blue"))
|
|
110
110
|
program = get_add_ssh_key_script(PathExtended(res))
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
console.print(Panel("🚀 SSH KEY AUTHORIZATION READY\nRun the generated script to apply changes", box=box.DOUBLE_EDGE, title_align="left"))
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
return program
|
|
115
115
|
|
|
116
116
|
|