machineconfig 1.5__py3-none-any.whl → 1.8__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/__init__.py +8 -5
- machineconfig/jobs/python/check_installations.py +173 -163
- machineconfig/jobs/python/checkout_version.py +117 -0
- machineconfig/jobs/python/create_bootable_media.py +14 -14
- machineconfig/jobs/python/create_zellij_template.py +59 -56
- machineconfig/jobs/python/python_cargo_build_share.py +50 -45
- machineconfig/jobs/python/python_ve_symlink.py +20 -18
- machineconfig/jobs/python/tasks.py +4 -0
- machineconfig/jobs/script_installer/azure_data_studio.py +22 -0
- machineconfig/jobs/script_installer/bypass_paywall.py +23 -0
- machineconfig/jobs/script_installer/code.py +34 -0
- machineconfig/jobs/script_installer/docker_desktop.py +41 -0
- machineconfig/jobs/script_installer/ngrok.py +29 -0
- machineconfig/jobs/{python_linux_installers → script_installer}/skim.py +21 -19
- machineconfig/jobs/script_installer/wezterm.py +34 -0
- machineconfig/profile/create.py +107 -200
- machineconfig/profile/shell.py +127 -0
- machineconfig/scripts/__init__.py +6 -6
- machineconfig/scripts/python/cloud_copy.py +93 -0
- machineconfig/scripts/python/cloud_manager.py +38 -0
- machineconfig/scripts/python/cloud_mount.py +115 -52
- machineconfig/scripts/python/cloud_repo_sync.py +154 -114
- machineconfig/scripts/python/cloud_sync.py +261 -79
- machineconfig/scripts/python/croshell.py +151 -0
- machineconfig/scripts/python/devops.py +119 -87
- machineconfig/scripts/python/devops_add_identity.py +27 -23
- machineconfig/scripts/python/devops_add_ssh_key.py +70 -55
- machineconfig/scripts/python/devops_backup_retrieve.py +52 -46
- machineconfig/scripts/python/devops_devapps_install.py +120 -91
- machineconfig/scripts/python/devops_update_repos.py +82 -68
- machineconfig/scripts/python/dotfile.py +42 -38
- machineconfig/scripts/python/fire_jobs.py +351 -98
- machineconfig/scripts/python/ftpx.py +82 -0
- machineconfig/scripts/python/mount_nfs.py +54 -3
- machineconfig/scripts/python/mount_nw_drive.py +31 -0
- machineconfig/scripts/python/mount_ssh.py +44 -20
- machineconfig/scripts/python/onetimeshare.py +60 -51
- machineconfig/scripts/python/pomodoro.py +41 -37
- machineconfig/scripts/python/repos.py +195 -128
- machineconfig/scripts/python/scheduler.py +52 -0
- machineconfig/scripts/python/snapshot.py +21 -21
- machineconfig/scripts/python/start_slidev.py +104 -0
- machineconfig/scripts/python/start_terminals.py +97 -0
- machineconfig/scripts/python/wifi_conn.py +90 -71
- machineconfig/scripts/python/{transfer_wsl_win.py → wsl_windows_transfer.py} +47 -39
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +44 -48
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +136 -130
- machineconfig/utils/installer.py +251 -0
- machineconfig/utils/procs.py +114 -64
- machineconfig/utils/scheduling.py +188 -0
- machineconfig/utils/utils.py +353 -249
- machineconfig/utils/ve.py +222 -0
- {machineconfig-1.5.dist-info → machineconfig-1.8.dist-info}/METADATA +140 -110
- machineconfig-1.8.dist-info/RECORD +70 -0
- {machineconfig-1.5.dist-info → machineconfig-1.8.dist-info}/WHEEL +1 -1
- machineconfig/jobs/python/python_linux_installers_all.py +0 -73
- machineconfig/jobs/python/python_ve_installer.py +0 -73
- machineconfig/jobs/python/python_windows_installers_all.py +0 -23
- machineconfig/jobs/python_generic_installers/archive/nvim.py +0 -15
- machineconfig/jobs/python_generic_installers/archive/strongbox.py +0 -32
- machineconfig/jobs/python_generic_installers/archive/vtm.py +0 -25
- machineconfig/jobs/python_generic_installers/broot.py +0 -39
- machineconfig/jobs/python_generic_installers/browsh.py +0 -25
- machineconfig/jobs/python_generic_installers/bw.py +0 -26
- machineconfig/jobs/python_generic_installers/chatgpt.py +0 -24
- machineconfig/jobs/python_generic_installers/cpufetch.py +0 -23
- machineconfig/jobs/python_generic_installers/delta.py +0 -59
- machineconfig/jobs/python_generic_installers/dev/__init__.py +0 -0
- machineconfig/jobs/python_generic_installers/dev/autogpt.py +0 -28
- machineconfig/jobs/python_generic_installers/dev/bw.py +0 -29
- machineconfig/jobs/python_generic_installers/dev/evcxr.py +0 -22
- machineconfig/jobs/python_generic_installers/dev/kondo.py +0 -21
- machineconfig/jobs/python_generic_installers/dev/lvim.py +0 -60
- machineconfig/jobs/python_generic_installers/dev/ngrok.py +0 -35
- machineconfig/jobs/python_generic_installers/dev/opencommit.py +0 -21
- machineconfig/jobs/python_generic_installers/dev/qrcp.py +0 -25
- machineconfig/jobs/python_generic_installers/dev/qrscan.py +0 -16
- machineconfig/jobs/python_generic_installers/dev/rust-analyzer.py +0 -24
- machineconfig/jobs/python_generic_installers/dev/termscp.py +0 -23
- machineconfig/jobs/python_generic_installers/dev/tldr.py +0 -25
- machineconfig/jobs/python_generic_installers/dev/tokei.py +0 -24
- machineconfig/jobs/python_generic_installers/diskonaut.py +0 -26
- machineconfig/jobs/python_generic_installers/dua.py +0 -21
- machineconfig/jobs/python_generic_installers/evcxr.py +0 -21
- machineconfig/jobs/python_generic_installers/gitui.py +0 -23
- machineconfig/jobs/python_generic_installers/gopass.py +0 -19
- machineconfig/jobs/python_generic_installers/helix.py +0 -45
- machineconfig/jobs/python_generic_installers/kondo.py +0 -20
- machineconfig/jobs/python_generic_installers/lf.py +0 -25
- machineconfig/jobs/python_generic_installers/lvim.py +0 -34
- machineconfig/jobs/python_generic_installers/mprocs.py +0 -20
- machineconfig/jobs/python_generic_installers/navi.py +0 -20
- machineconfig/jobs/python_generic_installers/ots.py +0 -26
- machineconfig/jobs/python_generic_installers/ouch.py +0 -25
- machineconfig/jobs/python_generic_installers/pomodoro.py +0 -19
- machineconfig/jobs/python_generic_installers/procs.py +0 -20
- machineconfig/jobs/python_generic_installers/qrcp.py +0 -22
- machineconfig/jobs/python_generic_installers/qrscan.py +0 -14
- machineconfig/jobs/python_generic_installers/rclone.py +0 -21
- machineconfig/jobs/python_generic_installers/rust-analyzer.py +0 -24
- machineconfig/jobs/python_generic_installers/tere.py +0 -26
- machineconfig/jobs/python_generic_installers/termscp.py +0 -23
- machineconfig/jobs/python_generic_installers/tldr.py +0 -24
- machineconfig/jobs/python_generic_installers/tokei.py +0 -21
- machineconfig/jobs/python_generic_installers/vtm.py +0 -26
- machineconfig/jobs/python_generic_installers/watchexec.py +0 -21
- machineconfig/jobs/python_linux_installers/archive/__init__.py +0 -0
- machineconfig/jobs/python_linux_installers/archive/ranger.py +0 -18
- machineconfig/jobs/python_linux_installers/bandwhich.py +0 -11
- machineconfig/jobs/python_linux_installers/bottom.py +0 -17
- machineconfig/jobs/python_linux_installers/btop.py +0 -17
- machineconfig/jobs/python_linux_installers/dev/bandwhich.py +0 -13
- machineconfig/jobs/python_linux_installers/dev/bytehound.py +0 -20
- machineconfig/jobs/python_linux_installers/dev/nnn.py +0 -21
- machineconfig/jobs/python_linux_installers/gotty.py +0 -16
- machineconfig/jobs/python_linux_installers/joshuto.py +0 -28
- machineconfig/jobs/python_linux_installers/mcfly.py +0 -12
- machineconfig/jobs/python_linux_installers/nnn.py +0 -18
- machineconfig/jobs/python_linux_installers/topgrade.py +0 -15
- machineconfig/jobs/python_linux_installers/viu.py +0 -19
- machineconfig/jobs/python_linux_installers/xplr.py +0 -22
- machineconfig/jobs/python_linux_installers/zellij.py +0 -31
- machineconfig/jobs/python_windows_installers/archive/ntop.py +0 -20
- machineconfig/jobs/python_windows_installers/bat.py +0 -16
- machineconfig/jobs/python_windows_installers/boxes.py +0 -19
- machineconfig/jobs/python_windows_installers/bypass_paywall.py +0 -18
- machineconfig/jobs/python_windows_installers/dev/bypass_paywall.py +0 -21
- machineconfig/jobs/python_windows_installers/dev/obs_background_removal_plugin.py +0 -20
- machineconfig/jobs/python_windows_installers/fd.py +0 -17
- machineconfig/jobs/python_windows_installers/fzf.py +0 -19
- machineconfig/jobs/python_windows_installers/obs_background_removal_plugin.py +0 -19
- machineconfig/jobs/python_windows_installers/rg.py +0 -15
- machineconfig/jobs/python_windows_installers/ugrep.py +0 -14
- machineconfig/jobs/python_windows_installers/zoomit.py +0 -20
- machineconfig/jobs/python_windows_installers/zoxide.py +0 -20
- machineconfig/profile/fix_shell_profiles.py +0 -8
- machineconfig/scripts/python/archive/__init__.py +0 -0
- machineconfig/scripts/python/archive/bu_gdrive_rx.py +0 -41
- machineconfig/scripts/python/archive/bu_gdrive_sx.py +0 -40
- machineconfig/scripts/python/archive/bu_onedrive_rx.py +0 -59
- machineconfig/scripts/python/archive/bu_onedrive_sx.py +0 -45
- machineconfig/scripts/python/chatgpt.py +0 -28
- machineconfig/scripts/python/choose_ohmybash_theme.py +0 -25
- machineconfig/scripts/python/choose_ohmyposh_theme.py +0 -40
- machineconfig/scripts/python/cloud_rx.py +0 -42
- machineconfig/scripts/python/cloud_sx.py +0 -40
- machineconfig/scripts/python/ftprx.py +0 -37
- machineconfig/scripts/python/ftpsx.py +0 -36
- machineconfig/scripts/python/im2text.py +0 -15
- machineconfig/scripts/python/tmate_conn.py +0 -28
- machineconfig/scripts/python/tmate_start.py +0 -31
- machineconfig/utils/to_exe.py +0 -7
- machineconfig-1.5.dist-info/RECORD +0 -147
- /machineconfig/jobs/{python_generic_installers/archive → script_installer}/__init__.py +0 -0
- {machineconfig-1.5.dist-info → machineconfig-1.8.dist-info}/top_level.txt +0 -0
machineconfig/profile/create.py
CHANGED
|
@@ -1,200 +1,107 @@
|
|
|
1
|
-
|
|
2
|
-
"""
|
|
3
|
-
This script Takes away all config files from the computer, place them in one directory
|
|
4
|
-
`dotfiles`, and create symlinks to those files from thier original locations.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
from
|
|
10
|
-
|
|
11
|
-
import
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if choice is None:
|
|
110
|
-
choice = display_options(msg="Which directory to add?", options=dirs + ["all", "none"], default="none")
|
|
111
|
-
if str(choice) != "all": dirs = [choice]
|
|
112
|
-
if choice == "none": return
|
|
113
|
-
|
|
114
|
-
addition = PathVar.append_temporarily(dirs=dirs)
|
|
115
|
-
profile_path = profile_path or get_shell_profile_path()
|
|
116
|
-
profile_path.copy(name=profile_path.name + f".orig_" + tb.randstr())
|
|
117
|
-
profile_path.modify_text(addition, addition, replace_line=False, notfound_append=True)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def main_add_sources_to_shell_profile(profile_path=None, choice=None):
|
|
121
|
-
sources = LIBRARY_ROOT.joinpath("profile/sources.toml").readit()[system.lower()]['files']
|
|
122
|
-
|
|
123
|
-
if choice is None:
|
|
124
|
-
choice = display_options(msg="Which patch to add?", options=sources + ["all", "none"], default="none")
|
|
125
|
-
if str(choice) != "all": sources = [choice]
|
|
126
|
-
if choice == "none": return
|
|
127
|
-
|
|
128
|
-
profile_path = profile_path or get_shell_profile_path()
|
|
129
|
-
profile = profile_path.read_text()
|
|
130
|
-
|
|
131
|
-
for a_file in sources:
|
|
132
|
-
file = a_file.replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix())
|
|
133
|
-
file = tb.P(file).collapseuser() # this makes the shell profile interuseable across machines.
|
|
134
|
-
file = file.as_posix() if system == "Linux" else str(file)
|
|
135
|
-
if file not in profile:
|
|
136
|
-
if system == "Windows": profile += f"\n. {file}"
|
|
137
|
-
elif system == "Linux": profile += f"\nsource {file}"
|
|
138
|
-
else: raise ValueError(f"Not implemented for this system {system}")
|
|
139
|
-
else: print(f"SKIPPED source `{file}`, it is already sourced in shell profile.")
|
|
140
|
-
profile_path.write_text(profile)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def main_add_patches_to_shell_profile(profile_path=None, choice=None):
|
|
144
|
-
patches = LIBRARY_ROOT.joinpath(f"profile/patches/{system.lower()}").search()
|
|
145
|
-
|
|
146
|
-
if choice is None:
|
|
147
|
-
choice = display_options(msg="Which patch to add?", options=patches.list + ["all", "none"], default="none")
|
|
148
|
-
if choice == "none": return
|
|
149
|
-
if str(choice) == "all": patches = patches
|
|
150
|
-
else: patches = [choice]
|
|
151
|
-
|
|
152
|
-
profile_path = profile_path or get_shell_profile_path()
|
|
153
|
-
profile = profile_path.read_text()
|
|
154
|
-
|
|
155
|
-
for patch_path in patches:
|
|
156
|
-
patch = patch_path.read_text()
|
|
157
|
-
if patch in profile: print(f"Skipping `{patch_path.name}`; patch already in profile")
|
|
158
|
-
else: profile += "\n" + patch
|
|
159
|
-
|
|
160
|
-
if system == "Linux":
|
|
161
|
-
res = tb.Terminal().run("cat /proc/version").op
|
|
162
|
-
if "microsoft" in res.lower() or "wsl" in res.lower():
|
|
163
|
-
profile += "\ncd ~" # this is to make sure that the current dir is not in the windows file system, which is terribly slow and its a bad idea to be there anyway.
|
|
164
|
-
|
|
165
|
-
profile_path.write_text(profile)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def main(choice=None):
|
|
169
|
-
console = Console()
|
|
170
|
-
print("\n")
|
|
171
|
-
console.rule(f"CREATING SYMLINKS")
|
|
172
|
-
|
|
173
|
-
# the only common choice among all programs below is "all".
|
|
174
|
-
main_symlinks(choice=choice)
|
|
175
|
-
|
|
176
|
-
# print("\n")
|
|
177
|
-
# console.rule(f"ADDING ENV PATH")
|
|
178
|
-
# main_env_path(choice=choice)
|
|
179
|
-
# print("\n")
|
|
180
|
-
# console.rule(f"ADDING SOURCES TO SHELL PROFILE")
|
|
181
|
-
# main_add_sources_to_shell_profile(choice=choice)
|
|
182
|
-
# print("\n")
|
|
183
|
-
# console.rule(f"ADDING PATCHES TO SHELL PROFILE")
|
|
184
|
-
# main_add_patches_to_shell_profile(choice=choice)
|
|
185
|
-
|
|
186
|
-
profile_path = get_shell_profile_path()
|
|
187
|
-
profile = profile_path.read_text()
|
|
188
|
-
source = f". {LIBRARY_ROOT.joinpath('settings/shells/pwsh/init.ps1').collapseuser()}" if system == "Windows" else f"source {LIBRARY_ROOT.joinpath('settings/shells/bash/init.sh')}"
|
|
189
|
-
if source in profile: print(f"Skipping sourcing init script; already in profile")
|
|
190
|
-
else:
|
|
191
|
-
profile += "\n" + source + "\n"
|
|
192
|
-
if system == "Linux":
|
|
193
|
-
res = tb.Terminal().run("cat /proc/version").op
|
|
194
|
-
if "microsoft" in res.lower() or "wsl" in res.lower():
|
|
195
|
-
profile += "\ncd ~" # this is to make sure that the current dir is not in the windows file system, which is terribly slow and its a bad idea to be there anyway.
|
|
196
|
-
profile_path.write_text(profile)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if __name__ == '__main__':
|
|
200
|
-
pass
|
|
1
|
+
|
|
2
|
+
"""
|
|
3
|
+
This script Takes away all config files from the computer, place them in one directory
|
|
4
|
+
`dotfiles`, and create symlinks to those files from thier original locations.
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from crocodile.environment import system, UserName # ProgramFiles, WindowsApps # , exe
|
|
10
|
+
from crocodile.meta import Terminal
|
|
11
|
+
from crocodile.file_management import P
|
|
12
|
+
from machineconfig.utils.utils import symlink, LIBRARY_ROOT, REPO_ROOT, display_options
|
|
13
|
+
from machineconfig.profile.shell import create_default_shell_profile
|
|
14
|
+
# import os
|
|
15
|
+
import subprocess
|
|
16
|
+
from rich.console import Console
|
|
17
|
+
from typing import Optional, Any
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
ERROR_LIST: list[Any] = [] # append to this after every exception captured.
|
|
21
|
+
CONFIG_ROOT = LIBRARY_ROOT.parent.parent.joinpath("settings")
|
|
22
|
+
OTHER_SYSTEM = "windows" if system == "Linux" else "linux"
|
|
23
|
+
SYSTEM = system.lower()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# =================== SYMLINKS ====================================
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def symlink_contents(source_dir: P, target_dir: P, overwrite: bool = True):
|
|
30
|
+
for a_target in target_dir.expanduser().search("*"):
|
|
31
|
+
symlink(this=source_dir.joinpath(a_target.name), to_this=a_target, prioritize_to_this=overwrite)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def main_symlinks(choice: Optional[str] = None):
|
|
35
|
+
symlink_mapper = LIBRARY_ROOT.joinpath("profile/mapper.toml").readit()
|
|
36
|
+
symlink_mapper['wsl_windows']['home']["to_this"] = symlink_mapper['wsl_windows']['home']["to_this"].replace("username", UserName)
|
|
37
|
+
symlink_mapper['wsl_linux']['home']["to_this"] = symlink_mapper['wsl_linux']['home']["to_this"].replace("username", UserName)
|
|
38
|
+
|
|
39
|
+
overwrite = True
|
|
40
|
+
exclude: list[str] = [] # "wsl_linux", "wsl_windows"
|
|
41
|
+
|
|
42
|
+
program_keys_raw: list[str] = list(symlink_mapper.keys())
|
|
43
|
+
program_keys: list[str] = []
|
|
44
|
+
for program_key in program_keys_raw:
|
|
45
|
+
if program_key in exclude or OTHER_SYSTEM in program_key:
|
|
46
|
+
# print(f"Skipping {program_key} for {system}")
|
|
47
|
+
continue
|
|
48
|
+
else: program_keys.append(program_key)
|
|
49
|
+
|
|
50
|
+
program_keys.sort()
|
|
51
|
+
if choice is None:
|
|
52
|
+
choice_selected = display_options(msg="Which symlink to create?", options=program_keys + ["all", "none(EXIT)"], default="none(EXIT)", fzf=True, multi=True)
|
|
53
|
+
assert isinstance(choice_selected, list)
|
|
54
|
+
if len(choice_selected) == 1 and choice_selected[0] == "none(EXIT)": return # terminate function.
|
|
55
|
+
elif len(choice_selected) == 1 and choice_selected[0] == "all": choice_selected = "all" # i.e. program_keys = program_keys
|
|
56
|
+
# overwrite = display_options(msg="Overwrite existing source file?", options=["yes", "no"], default="yes") == "yes"
|
|
57
|
+
from rich.prompt import Confirm
|
|
58
|
+
overwrite = Confirm.ask("Overwrite existing source file?", default=True)
|
|
59
|
+
|
|
60
|
+
else: choice_selected = choice
|
|
61
|
+
|
|
62
|
+
if isinstance(choice_selected, str):
|
|
63
|
+
if str(choice_selected) == "all" and system == "Windows" and not Terminal.is_user_admin():
|
|
64
|
+
print("*" * 200)
|
|
65
|
+
raise RuntimeError(f"Run terminal as admin and try again, otherwise, there will be too many popups for admin requests and no chance to terminate the program.")
|
|
66
|
+
elif choice_selected == "all":
|
|
67
|
+
print(f"{program_keys=}")
|
|
68
|
+
pass # i.e. program_keys = program_keys
|
|
69
|
+
else: program_keys = [choice_selected]
|
|
70
|
+
else: program_keys = choice_selected
|
|
71
|
+
|
|
72
|
+
for program_key in program_keys:
|
|
73
|
+
for file_key, file_map in symlink_mapper[program_key].items():
|
|
74
|
+
this = P(file_map['this'])
|
|
75
|
+
to_this = P(file_map['to_this'].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
|
|
76
|
+
if "contents" in file_map:
|
|
77
|
+
try: symlink_contents(source_dir=this, target_dir=to_this, overwrite=overwrite)
|
|
78
|
+
except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
|
|
79
|
+
else:
|
|
80
|
+
try: symlink(this=this, to_this=to_this, prioritize_to_this=overwrite)
|
|
81
|
+
except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
|
|
82
|
+
|
|
83
|
+
if program_key == "ssh" and system == "Linux": # permissions of ~/dotfiles/.ssh should be adjusted
|
|
84
|
+
try:
|
|
85
|
+
subprocess.run(f"chmod 700 ~/.ssh/", check=True)
|
|
86
|
+
subprocess.run(f"chmod 700 ~/dotfiles/creds/.ssh/", check=True) # may require sudo
|
|
87
|
+
subprocess.run(f"chmod 600 ~/dotfiles/creds/.ssh//*", check=True)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
ERROR_LIST.append(e)
|
|
90
|
+
print("Caught error", e)
|
|
91
|
+
|
|
92
|
+
if system == "Linux": Terminal().run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R')
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def main(choice: Optional[str] = None):
|
|
96
|
+
console = Console()
|
|
97
|
+
print("\n")
|
|
98
|
+
console.rule(f"CREATING SYMLINKS")
|
|
99
|
+
main_symlinks(choice=choice)
|
|
100
|
+
|
|
101
|
+
print("\n")
|
|
102
|
+
console.rule(f"CREATING SYMLINKS")
|
|
103
|
+
create_default_shell_profile()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if __name__ == '__main__':
|
|
107
|
+
pass
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
|
|
2
|
+
"""shell
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from crocodile.environment import PathVar
|
|
6
|
+
from crocodile.core import randstr
|
|
7
|
+
from crocodile.file_management import P
|
|
8
|
+
from crocodile.meta import Terminal
|
|
9
|
+
from machineconfig.utils.utils import LIBRARY_ROOT, REPO_ROOT, display_options
|
|
10
|
+
import platform
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
system = platform.system()
|
|
15
|
+
|
|
16
|
+
# --------------------------------------- SHELL PROFILE --------------------------------------------------------
|
|
17
|
+
# modification of shell profile by additing dirs to PATH
|
|
18
|
+
# Shell profile is either in dotfiles and is synced (as in Windows), hence no need for update, or is updated on the fly (for Linux)
|
|
19
|
+
# for windows it won't change the profile, if the profile was modified already e.g. due to syncing
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def create_default_shell_profile():
|
|
23
|
+
profile_path = get_shell_profile_path()
|
|
24
|
+
profile = profile_path.read_text()
|
|
25
|
+
if system == "Windows": source = f". {LIBRARY_ROOT.joinpath('settings/shells/pwsh/init.ps1').collapseuser().str.replace('~', '$HOME')}"
|
|
26
|
+
else: source = f"source {LIBRARY_ROOT.joinpath('settings/shells/bash/init.sh').collapseuser().str.replace('~', '$HOME')}"
|
|
27
|
+
|
|
28
|
+
if source in profile: print(f"Skipping sourcing init script; already in profile")
|
|
29
|
+
else:
|
|
30
|
+
profile += "\n" + source + "\n"
|
|
31
|
+
if system == "Linux":
|
|
32
|
+
res = Terminal().run("cat /proc/version").op
|
|
33
|
+
if "microsoft" in res.lower() or "wsl" in res.lower():
|
|
34
|
+
profile += "\ncd ~" # this is to make sure that the current dir is not in the windows file system, which is terribly slow and its a bad idea to be there anyway.
|
|
35
|
+
profile_path.create(parents_only=True).write_text(profile)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_shell_profile_path():
|
|
39
|
+
if system == "Windows":
|
|
40
|
+
res = Terminal().run("$profile", shell="pwsh").op2path()
|
|
41
|
+
if isinstance(res, P): profile_path = res
|
|
42
|
+
else: raise ValueError(f"Could not get profile path for Windows. Got {res}")
|
|
43
|
+
elif system == "Linux": profile_path = P("~/.bashrc").expanduser()
|
|
44
|
+
else: raise ValueError(f"Not implemented for this system {system}")
|
|
45
|
+
print(f"Working on shell profile `{profile_path}`")
|
|
46
|
+
return profile_path
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def main_env_path(choice: Optional[str] = None, profile_path: Optional[str] = None):
|
|
50
|
+
env_path = LIBRARY_ROOT.joinpath("profile/env_path.toml").readit()
|
|
51
|
+
dirs = env_path[f'path_{system.lower()}']['extension']
|
|
52
|
+
|
|
53
|
+
print(f"Current PATH: ", "\n============")
|
|
54
|
+
P.get_env().PATH.print()
|
|
55
|
+
|
|
56
|
+
if choice is None:
|
|
57
|
+
tmp = display_options(msg="Which directory to add?", options=dirs + ["all", "none(EXIT)"], default="none(EXIT)")
|
|
58
|
+
assert isinstance(tmp, str), f"Choice must be a string or a list of strings, not {type(choice)}"
|
|
59
|
+
choice = tmp
|
|
60
|
+
if str(choice) != "all": dirs = [choice]
|
|
61
|
+
if choice == "none(EXIT)": return
|
|
62
|
+
|
|
63
|
+
addition = PathVar.append_temporarily(dirs=dirs)
|
|
64
|
+
profile_path_obj = P(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
|
|
65
|
+
profile_path_obj.copy(name=profile_path_obj.name + f".orig_" + randstr())
|
|
66
|
+
profile_path_obj.modify_text(addition, addition, replace_line=False, notfound_append=True)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def main_add_sources_to_shell_profile(profile_path: Optional[str] = None, choice: Optional[str] = None):
|
|
70
|
+
sources: list[str] = LIBRARY_ROOT.joinpath("profile/sources.toml").readit()[system.lower()]['files']
|
|
71
|
+
|
|
72
|
+
if choice is None:
|
|
73
|
+
choice_obj = display_options(msg="Which patch to add?", options=sources + ["all", "none(EXIT)"], default="none(EXIT)", multi=True)
|
|
74
|
+
if isinstance(choice_obj, str):
|
|
75
|
+
if choice_obj == "all": choice = choice_obj
|
|
76
|
+
elif choice_obj == "none(EXIT)": return
|
|
77
|
+
else: sources = [choice_obj]
|
|
78
|
+
else: # isinstance(choice_obj, list):
|
|
79
|
+
sources = choice_obj
|
|
80
|
+
elif choice == "none(EXIT)": return
|
|
81
|
+
|
|
82
|
+
if isinstance(profile_path, str):
|
|
83
|
+
profile_path_obj = P(profile_path)
|
|
84
|
+
else: profile_path_obj = get_shell_profile_path()
|
|
85
|
+
profile = profile_path_obj.read_text()
|
|
86
|
+
|
|
87
|
+
for a_file in sources:
|
|
88
|
+
tmp = a_file.replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix())
|
|
89
|
+
file = P(tmp).collapseuser() # this makes the shell profile interuseable across machines.
|
|
90
|
+
file = file.as_posix() if system == "Linux" else str(file)
|
|
91
|
+
if file not in profile:
|
|
92
|
+
if system == "Windows": profile += f"\n. {file}"
|
|
93
|
+
elif system == "Linux": profile += f"\nsource {file}"
|
|
94
|
+
else: raise ValueError(f"Not implemented for this system {system}")
|
|
95
|
+
else: print(f"SKIPPED source `{file}`, it is already sourced in shell profile.")
|
|
96
|
+
profile_path_obj.write_text(profile)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def main_add_patches_to_shell_profile(profile_path: Optional[str] = None, choice: Optional[str] = None):
|
|
100
|
+
patches: list[str] = list(LIBRARY_ROOT.joinpath(f"profile/patches/{system.lower()}").search().apply(lambda x: x.as_posix()))
|
|
101
|
+
if choice is None:
|
|
102
|
+
choice_chosen = display_options(msg="Which patch to add?", options=list(patches) + ["all", "none(EXIT)"], default="none(EXIT)", multi=False)
|
|
103
|
+
assert isinstance(choice_chosen, str), f"Choice must be a string or a list of strings, not {type(choice)}"
|
|
104
|
+
choice = choice_chosen
|
|
105
|
+
if choice == "none(EXIT)": return None
|
|
106
|
+
elif str(choice) == "all": pass # i.e. patches = patches
|
|
107
|
+
else: patches = [choice]
|
|
108
|
+
|
|
109
|
+
profile_path_obj = P(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
|
|
110
|
+
profile = profile_path_obj.read_text()
|
|
111
|
+
|
|
112
|
+
for patch_path in patches:
|
|
113
|
+
patch_path_obj = P(patch_path)
|
|
114
|
+
patch = patch_path_obj.read_text()
|
|
115
|
+
if patch in profile: print(f"Skipping `{patch_path_obj.name}`; patch already in profile")
|
|
116
|
+
else: profile += "\n" + patch
|
|
117
|
+
|
|
118
|
+
if system == "Linux":
|
|
119
|
+
res = Terminal().run("cat /proc/version").op
|
|
120
|
+
if "microsoft" in res.lower() or "wsl" in res.lower():
|
|
121
|
+
profile += "\ncd ~" # this is to make sure that the current dir is not in the windows file system, which is terribly slow and its a bad idea to be there anyway.
|
|
122
|
+
|
|
123
|
+
profile_path_obj.write_text(profile)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
if __name__ == '__main__':
|
|
127
|
+
pass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
version = "0.5"
|
|
4
|
-
release_notes = """
|
|
5
|
-
created toml file for symlinks
|
|
6
|
-
"""
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
version = "0.5"
|
|
4
|
+
release_notes = """
|
|
5
|
+
created toml file for symlinks
|
|
6
|
+
"""
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
|
|
2
|
+
"""CC
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from crocodile.file_management import P, Struct
|
|
6
|
+
from crocodile.meta import RepeatUntilNoException
|
|
7
|
+
import getpass
|
|
8
|
+
from machineconfig.scripts.python.cloud_sync import parse_cloud_source_target, ArgsDefaults, Args
|
|
9
|
+
import argparse
|
|
10
|
+
import os
|
|
11
|
+
# from dataclasses import dataclass
|
|
12
|
+
# from pydantic import BaseModel
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@RepeatUntilNoException()
|
|
17
|
+
def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] = None):
|
|
18
|
+
folder_obj = P.cwd() if folder is None else P(folder)
|
|
19
|
+
|
|
20
|
+
if os.environ.get("DECRYPTION_PASSWORD") is not None:
|
|
21
|
+
pwd: str = str(os.environ.get("DECRYPTION_PASSWORD"))
|
|
22
|
+
else:
|
|
23
|
+
pwd = getpass.getpass(prompt="Enter decryption password: ")
|
|
24
|
+
|
|
25
|
+
if url is None:
|
|
26
|
+
if os.environ.get("SHARE_URL") is not None:
|
|
27
|
+
url = os.environ.get("SHARE_URL")
|
|
28
|
+
assert url is not None
|
|
29
|
+
else:
|
|
30
|
+
url = input("Enter share url: ")
|
|
31
|
+
|
|
32
|
+
from rich.progress import Progress
|
|
33
|
+
with Progress(transient=True) as progress:
|
|
34
|
+
_task = progress.add_task("Downloading ... ", total=None)
|
|
35
|
+
url_obj = P(url).download(folder=folder_obj)
|
|
36
|
+
with Progress(transient=True) as progress:
|
|
37
|
+
_task = progress.add_task("Decrypting ... ", total=None)
|
|
38
|
+
tmp_folder = P.tmpdir(prefix="tmp_unzip")
|
|
39
|
+
res = url_obj.decrypt(pwd=pwd, inplace=True).unzip(inplace=True, folder=tmp_folder)
|
|
40
|
+
res.search("*").apply(lambda x: x.move(folder=folder_obj, overwrite=True))
|
|
41
|
+
print(f"Decrypted to {res}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def arg_parser() -> None:
|
|
45
|
+
parser = argparse.ArgumentParser(description='Cloud CLI. It wraps rclone with sane defaults for optimum type time.')
|
|
46
|
+
|
|
47
|
+
# positional argument
|
|
48
|
+
parser.add_argument("source", help="file/folder path to be taken from here.")
|
|
49
|
+
parser.add_argument("target", help="file/folder path to be be sent to here.")
|
|
50
|
+
|
|
51
|
+
parser.add_argument("--overwrite", "-w", help="Overwrite existing file.", action="store_true", default=ArgsDefaults.overwrite)
|
|
52
|
+
parser.add_argument("--share", "-s", help="Share file / directory", action="store_true", default=ArgsDefaults.share)
|
|
53
|
+
parser.add_argument("--rel2home", "-r", help="Relative to `myhome` folder", action="store_true", default=ArgsDefaults.rel2home)
|
|
54
|
+
parser.add_argument("--root", "-R", help="Remote root. None is the default, unless rel2home is raied, making the default `myhome`.", default=ArgsDefaults.root)
|
|
55
|
+
|
|
56
|
+
parser.add_argument("--key", "-k", help="Key for encryption", type=str, default=ArgsDefaults.key)
|
|
57
|
+
parser.add_argument("--pwd", "-p", help="Password for encryption", type=str, default=ArgsDefaults.pwd)
|
|
58
|
+
parser.add_argument("--encrypt", "-e", help="Decrypt after receiving.", action="store_true", default=ArgsDefaults.encrypt)
|
|
59
|
+
parser.add_argument("--zip", "-z", help="unzip after receiving.", action="store_true", default=ArgsDefaults.zip_)
|
|
60
|
+
|
|
61
|
+
parser.add_argument("--config", "-c", help="path to cloud.json file.", default=None)
|
|
62
|
+
|
|
63
|
+
args = parser.parse_args()
|
|
64
|
+
args_dict = vars(args)
|
|
65
|
+
source: str = args_dict.pop("source")
|
|
66
|
+
target: str = args_dict.pop("target")
|
|
67
|
+
args_obj = Args(**args_dict)
|
|
68
|
+
Struct(args_obj.__dict__).print(as_config=True, title=f"CLI config")
|
|
69
|
+
|
|
70
|
+
if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")): return get_securely_shared_file(url=source, folder=target)
|
|
71
|
+
if args_obj.rel2home is True and args_obj.root is None: args_obj.root = "myhome"
|
|
72
|
+
|
|
73
|
+
cloud, source, target = parse_cloud_source_target(args=args_obj, source=source, target=target)
|
|
74
|
+
|
|
75
|
+
assert args_obj.key is None, f"Key is not supported yet."
|
|
76
|
+
if cloud in source:
|
|
77
|
+
P(target).from_cloud(cloud=cloud, remotepath=source.replace(cloud + ":", ""),
|
|
78
|
+
unzip=args_obj.zip, decrypt=args_obj.encrypt, pwd=args_obj.pwd,
|
|
79
|
+
overwrite=args_obj.overwrite,
|
|
80
|
+
rel2home=args_obj.rel2home, os_specific=args_obj.os_specific, root=args_obj.root, strict=False,
|
|
81
|
+
)
|
|
82
|
+
elif cloud in target:
|
|
83
|
+
res = P(source).to_cloud(cloud=cloud, remotepath=target.replace(cloud + ":", ""),
|
|
84
|
+
zip=args_obj.zip, encrypt=args_obj.encrypt, pwd=args_obj.pwd,
|
|
85
|
+
rel2home=args_obj.rel2home, root=args_obj.root, os_specific=args_obj.os_specific, strict=False,
|
|
86
|
+
share=args_obj.share)
|
|
87
|
+
if args_obj.share:
|
|
88
|
+
print(res.as_url_str())
|
|
89
|
+
else: raise ValueError(f"Cloud `{cloud}` not found in source or target.")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == "__main__":
|
|
93
|
+
arg_parser()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
"""Run cloud manager.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from crocodile.cluster.loader_runner import CloudManager
|
|
6
|
+
import argparse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main():
|
|
10
|
+
parser = argparse.ArgumentParser()
|
|
11
|
+
parser.add_argument("-c", "--cloud", help="Rclone Config Name", action="store", type=str, default=None)
|
|
12
|
+
parser.add_argument("-s", "--serve", help="Start job server", action="store_true", default=False)
|
|
13
|
+
parser.add_argument("-R", "--reset_local", help="Clear local cache", action="store_true", default=False)
|
|
14
|
+
parser.add_argument("-r", "--rerun_jobs", help="Re-run jobs by bringing them back from wherever to the queue.", action="store_true", default=False)
|
|
15
|
+
parser.add_argument("-L", "--release_lock", help="Release lock.", action="store_true", default=False)
|
|
16
|
+
parser.add_argument("-f", "--queue_failed_jobs", help="Bring failed jobs back to queued jobs for a re-trial.", action="store_true", default=False)
|
|
17
|
+
parser.add_argument("-m", "--monitor_cloud", help="Monitor workers instead of running a job server.", action="store_true", default=False)
|
|
18
|
+
parser.add_argument("-j", "--num_jobs", help="Number of jobs the server will run in parallel.", action="store", type=int, default=1)
|
|
19
|
+
args = parser.parse_args()
|
|
20
|
+
|
|
21
|
+
cm = CloudManager(max_jobs=args.num_jobs, cloud=args.cloud, reset_local=args.reset_local)
|
|
22
|
+
if args.release_lock:
|
|
23
|
+
cm.claim_lock()
|
|
24
|
+
cm.release_lock()
|
|
25
|
+
if args.queue_failed_jobs:
|
|
26
|
+
cm.clean_failed_jobs_mess()
|
|
27
|
+
if args.rerun_jobs:
|
|
28
|
+
cm.rerun_jobs()
|
|
29
|
+
if args.monitor_cloud:
|
|
30
|
+
cm.run_monitor()
|
|
31
|
+
if args.serve:
|
|
32
|
+
cm.serve()
|
|
33
|
+
import sys
|
|
34
|
+
sys.exit(0)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if __name__ == '__main__':
|
|
38
|
+
main()
|