machineconfig 1.9__py3-none-any.whl → 1.92__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 +2 -4
- machineconfig/jobs/python/check_installations.py +14 -6
- machineconfig/jobs/python/checkout_version.py +27 -32
- machineconfig/jobs/python/create_bootable_media.py +1 -1
- machineconfig/jobs/python/python_cargo_build_share.py +2 -2
- machineconfig/jobs/python/tasks.py +2 -2
- machineconfig/jobs/python_custom_installers/{helix.py → hx.py} +21 -6
- machineconfig/profile/create.py +23 -21
- machineconfig/profile/create_hardlinks.py +101 -0
- machineconfig/profile/shell.py +10 -7
- machineconfig/scripts/python/cloud_copy.py +19 -16
- machineconfig/scripts/python/cloud_repo_sync.py +94 -47
- machineconfig/scripts/python/cloud_sync.py +78 -61
- machineconfig/scripts/python/croshell.py +6 -6
- machineconfig/scripts/python/devops.py +22 -22
- machineconfig/scripts/python/devops_add_ssh_key.py +1 -1
- machineconfig/scripts/python/devops_backup_retrieve.py +19 -10
- machineconfig/scripts/python/devops_devapps_install.py +80 -62
- machineconfig/scripts/python/devops_update_repos.py +5 -5
- machineconfig/scripts/python/dotfile.py +4 -4
- machineconfig/scripts/python/fire_jobs.py +115 -63
- machineconfig/scripts/python/gh_models.py +55 -0
- machineconfig/scripts/python/mount_nfs.py +1 -1
- machineconfig/scripts/python/mount_nw_drive.py +3 -3
- machineconfig/scripts/python/mount_ssh.py +2 -3
- machineconfig/scripts/python/pomodoro.py +1 -1
- machineconfig/scripts/python/repos.py +22 -23
- machineconfig/scripts/python/scheduler.py +1 -1
- machineconfig/scripts/python/start_slidev.py +12 -6
- machineconfig/scripts/python/start_terminals.py +5 -4
- machineconfig/scripts/python/wifi_conn.py +34 -42
- machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
- machineconfig/settings/__init__.py +0 -0
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +1 -1
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +3 -2
- machineconfig/utils/installer.py +86 -41
- machineconfig/utils/procs.py +2 -2
- machineconfig/utils/scheduling.py +3 -3
- machineconfig/utils/utils.py +136 -56
- machineconfig/utils/ve.py +145 -95
- {machineconfig-1.9.dist-info → machineconfig-1.92.dist-info}/METADATA +160 -155
- machineconfig-1.92.dist-info/RECORD +70 -0
- machineconfig/jobs/python_custom_installers/azuredatastudio.py +0 -36
- machineconfig/jobs/python_custom_installers/bypass_paywall.py +0 -30
- machineconfig/jobs/python_custom_installers/docker_desktop.py +0 -52
- machineconfig/jobs/python_custom_installers/goes.py +0 -35
- machineconfig/jobs/python_custom_installers/lvim.py +0 -48
- machineconfig/jobs/python_custom_installers/ngrok.py +0 -39
- machineconfig/jobs/python_custom_installers/nvim.py +0 -48
- machineconfig/jobs/python_custom_installers/vscode.py +0 -45
- machineconfig/jobs/python_custom_installers/wezterm.py +0 -41
- machineconfig-1.9.dist-info/RECORD +0 -76
- {machineconfig-1.9.dist-info → machineconfig-1.92.dist-info}/LICENSE +0 -0
- {machineconfig-1.9.dist-info → machineconfig-1.92.dist-info}/WHEEL +0 -0
- {machineconfig-1.9.dist-info → machineconfig-1.92.dist-info}/top_level.txt +0 -0
machineconfig/__init__.py
CHANGED
|
@@ -15,6 +15,7 @@ from crocodile.file_management import P
|
|
|
15
15
|
from crocodile.meta import Terminal
|
|
16
16
|
from tqdm import tqdm
|
|
17
17
|
from typing import Optional
|
|
18
|
+
from datetime import datetime
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
APP_SUMMARY_PATH = LIBRARY_ROOT.joinpath(f"profile/records/{platform.system().lower()}/apps_summary_report.csv")
|
|
@@ -42,7 +43,7 @@ def scan(path: P, pct: float = 0.0):
|
|
|
42
43
|
repeat_counter += 1
|
|
43
44
|
if repeat_counter > 2:
|
|
44
45
|
raise ValueError(f"Error in scanning {path}") from ex
|
|
45
|
-
print(
|
|
46
|
+
print("Error in scanning, trying again.")
|
|
46
47
|
time.sleep(30)
|
|
47
48
|
df = pd.DataFrame(anal.results.values())
|
|
48
49
|
malicious = []
|
|
@@ -81,7 +82,9 @@ def main() -> None:
|
|
|
81
82
|
print(f"Checking tools collected from `{INSTALL_VERSION_ROOT}`:")
|
|
82
83
|
apps_paths_raw.print()
|
|
83
84
|
positive_pct: list[Optional[float]] = []
|
|
85
|
+
scan_time: list[str] = []
|
|
84
86
|
detailed_results: list[dict[str, Optional[pd.DataFrame]]] = []
|
|
87
|
+
|
|
85
88
|
for idx, app in enumerate(apps_paths_raw):
|
|
86
89
|
try: res = scan(path=app, pct=idx / len(apps_paths_raw) * 100)
|
|
87
90
|
except ValueError as ve:
|
|
@@ -94,9 +97,13 @@ def main() -> None:
|
|
|
94
97
|
ppct, df = res
|
|
95
98
|
positive_pct.append(ppct)
|
|
96
99
|
detailed_results.append({app.stem: df})
|
|
100
|
+
scan_time.append(datetime.now().strftime("%Y-%m-%d %H:%M"))
|
|
97
101
|
|
|
98
|
-
res_df = pd.DataFrame({"app_name": apps_paths_raw.apply(lambda x: x.stem).list,
|
|
99
|
-
|
|
102
|
+
res_df = pd.DataFrame({"app_name": apps_paths_raw.apply(lambda x: x.stem).list,
|
|
103
|
+
"version": app_versions,
|
|
104
|
+
"positive_pct": positive_pct,
|
|
105
|
+
"scan_time": scan_time,
|
|
106
|
+
"app_path": apps_paths_raw.apply(lambda x: x.collapseuser(strict=False).as_posix()).list})
|
|
100
107
|
|
|
101
108
|
app_url: list[Optional[str]] = []
|
|
102
109
|
for idx, row in tqdm(res_df.iterrows(), total=res_df.shape[0]):
|
|
@@ -105,12 +112,13 @@ def main() -> None:
|
|
|
105
112
|
res_df["app_url"] = app_url
|
|
106
113
|
res_df.to_csv(APP_SUMMARY_PATH.with_suffix(".csv").create(parents_only=True), index=False)
|
|
107
114
|
APP_SUMMARY_PATH.with_suffix(".md").write_text(res_df.to_markdown())
|
|
108
|
-
print(
|
|
115
|
+
print("Safety Report:")
|
|
109
116
|
print(res_df)
|
|
110
117
|
|
|
111
118
|
|
|
112
119
|
def upload(path: P):
|
|
113
|
-
|
|
120
|
+
import call_function_with_timeout
|
|
121
|
+
set_time_out = call_function_with_timeout.SetTimeout
|
|
114
122
|
func_with_timeout = set_time_out(lambda: path.to_cloud(CLOUD, rel2home=True, share=True, os_specific=True), timeout=180)
|
|
115
123
|
is_done, _is_timeout, _erro_message, results = func_with_timeout()
|
|
116
124
|
if is_done: return results
|
|
@@ -146,7 +154,7 @@ class PrecheckedCloudInstaller:
|
|
|
146
154
|
exe.move(folder=P.home().joinpath("AppData/Local/Microsoft/WindowsApps"), overwrite=True)
|
|
147
155
|
return True
|
|
148
156
|
|
|
149
|
-
def download_safe_apps(self, name: str
|
|
157
|
+
def download_safe_apps(self, name: str="AllEssentials"):
|
|
150
158
|
# if platform.system().lower() == "windows":
|
|
151
159
|
# from machineconfig.jobs.python.python_windows_installers_all import get_cli_py_installers
|
|
152
160
|
# cli_installers = get_cli_py_installers()
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from crocodile.file_management import P, Save, randstr
|
|
6
6
|
from crocodile.meta import Terminal
|
|
7
|
-
from machineconfig.utils.ve import get_ve_profile, get_ve_specs
|
|
7
|
+
from machineconfig.utils.ve import get_ve_profile, get_ve_specs
|
|
8
8
|
from machineconfig.scripts.python.repos import record_a_repo, install_repos
|
|
9
9
|
import platform
|
|
10
10
|
|
|
@@ -12,12 +12,18 @@ import platform
|
|
|
12
12
|
# TODO: add data requirements for added isolation of file system.
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def checkout_version(version: str, repo_root: P, exclude_editable: bool
|
|
15
|
+
def checkout_version(version: str, repo_root: P, exclude_editable: bool=False):
|
|
16
16
|
"""Checkout a version of the repo and install its requirements."""
|
|
17
17
|
ve_name = get_ve_profile(init_path=repo_root)
|
|
18
18
|
ve_path = P.home().joinpath("venvs", ve_name)
|
|
19
19
|
ve_specs = get_ve_specs(ve_path)
|
|
20
|
-
|
|
20
|
+
try:
|
|
21
|
+
py_version = ve_specs['version']
|
|
22
|
+
except KeyError as err:
|
|
23
|
+
# print(f"❌ No python version found in {ve_specs}.")
|
|
24
|
+
# raise err
|
|
25
|
+
_ = err
|
|
26
|
+
py_version = ve_specs['version_info']
|
|
21
27
|
sys = platform.system().lower()
|
|
22
28
|
|
|
23
29
|
target_dir = repo_root.expanduser().absolute().joinpath(f"versions/{version}").as_posix()
|
|
@@ -33,24 +39,29 @@ def checkout_version(version: str, repo_root: P, exclude_editable: bool = False)
|
|
|
33
39
|
checkout_ve = f"{repo_root.name}-{version}-prod" if not exclude_editable else ve_name
|
|
34
40
|
checkout_ve = input(f"Name of the ve to create (default: {checkout_ve}): ") or checkout_ve
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
version_root_obj.joinpath("install_ve.ps1").write_text(ve_template)
|
|
38
|
-
ve_template = get_ve_install_script(ve_name=checkout_ve, py_version=py_version, system="Linux", delete_if_exists=False, install_crocodile_and_machineconfig=False)
|
|
39
|
-
version_root_obj.joinpath("install_ve.sh").write_text(ve_template)
|
|
42
|
+
install_env = f"""
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
uv venv $HOME/venvs/{checkout_ve} --python {py_version} --python-preference only-managed
|
|
42
45
|
. $HOME/scripts/activate_ve {ve_name}
|
|
43
|
-
|
|
44
|
-
pip install
|
|
46
|
+
|
|
47
|
+
uv pip install pip
|
|
48
|
+
|
|
45
49
|
{install_editable_packages}
|
|
50
|
+
|
|
51
|
+
cd {version_root}
|
|
52
|
+
uv pip install -r requirements_{sys}.txt
|
|
53
|
+
|
|
46
54
|
"""
|
|
47
55
|
if sys == "windows":
|
|
48
|
-
version_root_obj.joinpath("
|
|
49
|
-
if not version_root_obj.joinpath("
|
|
56
|
+
version_root_obj.joinpath("install_env.ps1").write_text(install_env)
|
|
57
|
+
if not version_root_obj.joinpath("install_env.sh").exists():
|
|
58
|
+
version_root_obj.joinpath("install_env.sh").write_text(install_env)
|
|
50
59
|
elif sys == "linux":
|
|
51
|
-
version_root_obj.joinpath("
|
|
52
|
-
if not version_root_obj.joinpath("
|
|
53
|
-
|
|
60
|
+
version_root_obj.joinpath("install_env.sh").write_text(install_env)
|
|
61
|
+
if not version_root_obj.joinpath("install_env.ps1").exists():
|
|
62
|
+
version_root_obj.joinpath("install_env.ps1").write_text(install_env)
|
|
63
|
+
else:
|
|
64
|
+
raise NotImplementedError(f"System {sys} not supported.")
|
|
54
65
|
|
|
55
66
|
pip_freeze_script = f"""
|
|
56
67
|
cd '{target_dir}'
|
|
@@ -58,23 +69,6 @@ cd '{target_dir}'
|
|
|
58
69
|
python -m pip freeze {'--exclude-editable' if exclude_editable else ''} > requirements_{sys}.txt
|
|
59
70
|
"""
|
|
60
71
|
Terminal().run_script(pip_freeze_script, verbose=True, shell="default").print()
|
|
61
|
-
|
|
62
|
-
install_all_script = r"""
|
|
63
|
-
#!/usr/bin/bash
|
|
64
|
-
|
|
65
|
-
CUR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
|
66
|
-
. $CUR_DIR/install_ve.sh
|
|
67
|
-
. $CUR_DIR/install_requirements.sh
|
|
68
|
-
"""
|
|
69
|
-
version_root_obj.joinpath("install.sh").write_text(install_all_script)
|
|
70
|
-
install_all_script = r"""
|
|
71
|
-
|
|
72
|
-
$CUR_DIR = Split-Path $MyInvocation.MyCommand.Path -Parent
|
|
73
|
-
. $CUR_DIR/install_ve.ps1
|
|
74
|
-
. $CUR_DIR/install_requirements.ps1
|
|
75
|
-
|
|
76
|
-
"""
|
|
77
|
-
version_root_obj.joinpath("install.ps1").write_text(install_all_script)
|
|
78
72
|
print(f"✅ Installed requirements for version {version}.")
|
|
79
73
|
|
|
80
74
|
|
|
@@ -97,6 +91,7 @@ def main():
|
|
|
97
91
|
|
|
98
92
|
def get_editable_packages(ve_name: str):
|
|
99
93
|
file = P.tmp().joinpath(f"tmp_files/editable_requirements_{randstr()}.txt")
|
|
94
|
+
file.parent.mkdir(parents=True, exist_ok=True)
|
|
100
95
|
editable_packages_script = f"""
|
|
101
96
|
. $HOME/scripts/activate_ve {ve_name}
|
|
102
97
|
pip list --editable > {file}
|
|
@@ -8,7 +8,7 @@ from crocodile.file_management import P
|
|
|
8
8
|
import platform
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def build_rust_executable(url: str
|
|
11
|
+
def build_rust_executable(url: str=r"https://github.com/atanunq/viu"):
|
|
12
12
|
tool_name = url.split('/')[-1]
|
|
13
13
|
|
|
14
14
|
# move command is not required since tool will go to .cargo/bin which is in PATH by default.
|
|
@@ -35,7 +35,7 @@ cargo install --path .
|
|
|
35
35
|
print(f"PermissionError, couldn't delete: {P.home().joinpath(tool_name)}")
|
|
36
36
|
|
|
37
37
|
if platform.system() == "Windows":
|
|
38
|
-
exe = exe.move(folder=P.get_env().WindowsApps)
|
|
38
|
+
exe = exe.move(folder=P.get_env().WindowsPaths().WindowsApps)
|
|
39
39
|
elif platform.system() == "Linux":
|
|
40
40
|
Terminal().run(f"sudo mv {exe} /usr/local/bin")
|
|
41
41
|
exe = P(r"/usr/local/bin").joinpath(exe.name)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
from machineconfig.scripts.python.devops_backup_retrieve import
|
|
2
|
+
from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
|
|
3
3
|
|
|
4
|
-
program =
|
|
4
|
+
program = main_backup_retrieve(direction="BACKUP", which="all")
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
Installers do not add runtime files to the machine, hence this script.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
from machineconfig.utils.installer import Installer,
|
|
6
|
+
from crocodile.file_management import P
|
|
7
|
+
from machineconfig.utils.installer import Installer, WINDOWS_INSTALL_PATH
|
|
8
8
|
from typing import Optional
|
|
9
9
|
import platform
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
config_dict = {
|
|
13
|
-
"repo_url": "
|
|
13
|
+
"repo_url": "CUSTOM",
|
|
14
14
|
"doc": "Helix is a post-modern modal text editor.",
|
|
15
15
|
"filename_template_windows_amd_64": "helix-{}-x86_64-windows.zip",
|
|
16
16
|
"filename_template_linux_amd_64": "helix-{}-x86_64-linux.tar.xz",
|
|
@@ -20,23 +20,38 @@ config_dict = {
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def main(version: Optional[str]):
|
|
23
|
-
|
|
23
|
+
config_dict_copy = config_dict.copy()
|
|
24
|
+
config_dict_copy["repo_url"] = "https://github.com/helix-editor/helix"
|
|
25
|
+
inst = Installer.from_dict(d=config_dict_copy, name="hx")
|
|
24
26
|
downloaded, _version_to_be_installed = inst.download(version=version)
|
|
25
|
-
|
|
27
|
+
if platform.system() == "Windows":
|
|
28
|
+
hx_file_search = downloaded.search("hx.exe", folders=False, files=True, r=True)
|
|
29
|
+
else:
|
|
30
|
+
hx_file_search = downloaded.search("hx", folders=False, files=True, r=True)
|
|
26
31
|
assert len(hx_file_search) == 1
|
|
27
32
|
hx_file = hx_file_search.list[0]
|
|
28
33
|
contrib = hx_file.parent / "contrib"
|
|
29
34
|
runtime = contrib.parent / "runtime"
|
|
30
35
|
assert runtime.exists()
|
|
31
36
|
assert contrib.exists()
|
|
37
|
+
P.home().joinpath(".config/helix/runtime").delete(sure=True)
|
|
38
|
+
P.home().joinpath(".config/helix/contrib").delete(sure=True)
|
|
32
39
|
if platform.system() == "Linux":
|
|
33
|
-
hx_file.move(folder=LINUX_INSTALL_PATH)
|
|
40
|
+
# hx_file.move(folder=LINUX_INSTALL_PATH) # to be added later
|
|
34
41
|
contrib.move(folder="~/.config/helix")
|
|
35
42
|
runtime.move(folder="~/.config/helix")
|
|
36
43
|
elif platform.system() == "Windows":
|
|
37
44
|
hx_file.move(folder=WINDOWS_INSTALL_PATH)
|
|
38
45
|
contrib.move(folder="~/.config/helix")
|
|
39
46
|
runtime.move(folder="~/.config/helix")
|
|
47
|
+
else:
|
|
48
|
+
print("Unsupported OS")
|
|
49
|
+
downloaded.delete(sure=True)
|
|
50
|
+
|
|
51
|
+
if platform.system() == "Linux":
|
|
52
|
+
inst.install(version=version) # because we can't normally move hx (without privliage) # hx_file.move(folder=LINUX_INSTALL_PATH)
|
|
53
|
+
|
|
54
|
+
return ""
|
|
40
55
|
|
|
41
56
|
|
|
42
57
|
if __name__ == "__main__":
|
machineconfig/profile/create.py
CHANGED
|
@@ -6,15 +6,15 @@ This script Takes away all config files from the computer, place them in one dir
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
from crocodile.environment import system
|
|
9
|
+
from crocodile.environment import system # ProgramFiles, WindowsApps # , exe
|
|
10
10
|
from crocodile.meta import Terminal
|
|
11
11
|
from crocodile.file_management import P
|
|
12
|
-
from machineconfig.utils.utils import
|
|
12
|
+
from machineconfig.utils.utils import symlink_func, symlink_copy, LIBRARY_ROOT, REPO_ROOT, display_options
|
|
13
13
|
from machineconfig.profile.shell import create_default_shell_profile
|
|
14
14
|
# import os
|
|
15
15
|
import subprocess
|
|
16
16
|
from rich.console import Console
|
|
17
|
-
from typing import Optional, Any
|
|
17
|
+
from typing import Optional, Any, TypedDict
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
ERROR_LIST: list[Any] = [] # append to this after every exception captured.
|
|
@@ -23,18 +23,16 @@ OTHER_SYSTEM = "windows" if system == "Linux" else "linux"
|
|
|
23
23
|
SYSTEM = system.lower()
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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)
|
|
26
|
+
class SymlinkMapper(TypedDict):
|
|
27
|
+
this: str
|
|
28
|
+
to_this: str
|
|
29
|
+
contents: Optional[bool]
|
|
32
30
|
|
|
33
31
|
|
|
34
32
|
def main_symlinks(choice: Optional[str] = None):
|
|
35
33
|
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)
|
|
34
|
+
# symlink_mapper['wsl_windows']['home']["to_this"] = symlink_mapper['wsl_windows']['home']["to_this"].replace("username", UserName)
|
|
35
|
+
# symlink_mapper['wsl_linux']['home']["to_this"] = symlink_mapper['wsl_linux']['home']["to_this"].replace("username", UserName)
|
|
38
36
|
|
|
39
37
|
overwrite = True
|
|
40
38
|
exclude: list[str] = [] # "wsl_linux", "wsl_windows"
|
|
@@ -43,7 +41,6 @@ def main_symlinks(choice: Optional[str] = None):
|
|
|
43
41
|
program_keys: list[str] = []
|
|
44
42
|
for program_key in program_keys_raw:
|
|
45
43
|
if program_key in exclude or OTHER_SYSTEM in program_key:
|
|
46
|
-
# print(f"Skipping {program_key} for {system}")
|
|
47
44
|
continue
|
|
48
45
|
else: program_keys.append(program_key)
|
|
49
46
|
|
|
@@ -56,13 +53,12 @@ def main_symlinks(choice: Optional[str] = None):
|
|
|
56
53
|
# overwrite = display_options(msg="Overwrite existing source file?", options=["yes", "no"], default="yes") == "yes"
|
|
57
54
|
from rich.prompt import Confirm
|
|
58
55
|
overwrite = Confirm.ask("Overwrite existing source file?", default=True)
|
|
59
|
-
|
|
60
56
|
else: choice_selected = choice
|
|
61
57
|
|
|
62
58
|
if isinstance(choice_selected, str):
|
|
63
59
|
if str(choice_selected) == "all" and system == "Windows" and not Terminal.is_user_admin():
|
|
64
60
|
print("*" * 200)
|
|
65
|
-
raise RuntimeError(
|
|
61
|
+
raise RuntimeError("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
62
|
elif choice_selected == "all":
|
|
67
63
|
print(f"{program_keys=}")
|
|
68
64
|
pass # i.e. program_keys = program_keys
|
|
@@ -74,17 +70,23 @@ def main_symlinks(choice: Optional[str] = None):
|
|
|
74
70
|
this = P(file_map['this'])
|
|
75
71
|
to_this = P(file_map['to_this'].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
|
|
76
72
|
if "contents" in file_map:
|
|
77
|
-
try:
|
|
73
|
+
try:
|
|
74
|
+
for a_target in to_this.expanduser().search("*"):
|
|
75
|
+
symlink_func(this=this.joinpath(a_target.name), to_this=a_target, prioritize_to_this=overwrite)
|
|
78
76
|
except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
|
|
77
|
+
if "copy" in file_map:
|
|
78
|
+
try:
|
|
79
|
+
symlink_copy(this=this, to_this=to_this, prioritize_to_this=overwrite)
|
|
80
|
+
except Exception as ex: print("Config error: ", program_key, file_key, ex)
|
|
79
81
|
else:
|
|
80
|
-
try:
|
|
82
|
+
try: symlink_func(this=this, to_this=to_this, prioritize_to_this=overwrite)
|
|
81
83
|
except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
|
|
82
84
|
|
|
83
85
|
if program_key == "ssh" and system == "Linux": # permissions of ~/dotfiles/.ssh should be adjusted
|
|
84
86
|
try:
|
|
85
|
-
subprocess.run(
|
|
86
|
-
subprocess.run(
|
|
87
|
-
subprocess.run(
|
|
87
|
+
subprocess.run("chmod 700 ~/.ssh/", check=True)
|
|
88
|
+
subprocess.run("chmod 700 ~/dotfiles/creds/.ssh/", check=True) # may require sudo
|
|
89
|
+
subprocess.run("chmod 600 ~/dotfiles/creds/.ssh/*", check=True)
|
|
88
90
|
except Exception as e:
|
|
89
91
|
ERROR_LIST.append(e)
|
|
90
92
|
print("Caught error", e)
|
|
@@ -98,11 +100,11 @@ def main_symlinks(choice: Optional[str] = None):
|
|
|
98
100
|
def main(choice: Optional[str] = None):
|
|
99
101
|
console = Console()
|
|
100
102
|
print("\n")
|
|
101
|
-
console.rule(
|
|
103
|
+
console.rule("CREATING SYMLINKS")
|
|
102
104
|
main_symlinks(choice=choice)
|
|
103
105
|
|
|
104
106
|
print("\n")
|
|
105
|
-
console.rule(
|
|
107
|
+
console.rule("CREATING SYMLINKS")
|
|
106
108
|
create_default_shell_profile()
|
|
107
109
|
|
|
108
110
|
|
|
@@ -0,0 +1,101 @@
|
|
|
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 # ProgramFiles, WindowsApps # , exe
|
|
10
|
+
from crocodile.meta import Terminal
|
|
11
|
+
from crocodile.file_management import P
|
|
12
|
+
from machineconfig.utils.utils import symlink_copy as symlink_func, 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
|
+
def main_symlinks(choice: Optional[str] = None):
|
|
27
|
+
symlink_mapper = LIBRARY_ROOT.joinpath("profile/mapper.toml").readit()
|
|
28
|
+
# symlink_mapper['wsl_windows']['home']["to_this"] = symlink_mapper['wsl_windows']['home']["to_this"].replace("username", UserName)
|
|
29
|
+
# symlink_mapper['wsl_linux']['home']["to_this"] = symlink_mapper['wsl_linux']['home']["to_this"].replace("username", UserName)
|
|
30
|
+
|
|
31
|
+
overwrite = True
|
|
32
|
+
exclude: list[str] = [] # "wsl_linux", "wsl_windows"
|
|
33
|
+
|
|
34
|
+
program_keys_raw: list[str] = list(symlink_mapper.keys())
|
|
35
|
+
program_keys: list[str] = []
|
|
36
|
+
for program_key in program_keys_raw:
|
|
37
|
+
if program_key in exclude or OTHER_SYSTEM in program_key:
|
|
38
|
+
# print(f"Skipping {program_key} for {system}")
|
|
39
|
+
continue
|
|
40
|
+
else: program_keys.append(program_key)
|
|
41
|
+
|
|
42
|
+
program_keys.sort()
|
|
43
|
+
if choice is None:
|
|
44
|
+
choice_selected = display_options(msg="Which symlink to create?", options=program_keys + ["all", "none(EXIT)"], default="none(EXIT)", fzf=True, multi=True)
|
|
45
|
+
assert isinstance(choice_selected, list)
|
|
46
|
+
if len(choice_selected) == 1 and choice_selected[0] == "none(EXIT)": return # terminate function.
|
|
47
|
+
elif len(choice_selected) == 1 and choice_selected[0] == "all": choice_selected = "all" # i.e. program_keys = program_keys
|
|
48
|
+
# overwrite = display_options(msg="Overwrite existing source file?", options=["yes", "no"], default="yes") == "yes"
|
|
49
|
+
from rich.prompt import Confirm
|
|
50
|
+
overwrite = Confirm.ask("Overwrite existing source file?", default=True)
|
|
51
|
+
|
|
52
|
+
else: choice_selected = choice
|
|
53
|
+
|
|
54
|
+
if isinstance(choice_selected, str):
|
|
55
|
+
if choice_selected == "all":
|
|
56
|
+
print(f"{program_keys=}")
|
|
57
|
+
pass # i.e. program_keys = program_keys
|
|
58
|
+
else: program_keys = [choice_selected]
|
|
59
|
+
else: program_keys = choice_selected
|
|
60
|
+
|
|
61
|
+
for program_key in program_keys:
|
|
62
|
+
for file_key, file_map in symlink_mapper[program_key].items():
|
|
63
|
+
this = P(file_map['this'])
|
|
64
|
+
to_this = P(file_map['to_this'].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
|
|
65
|
+
if "contents" in file_map:
|
|
66
|
+
try:
|
|
67
|
+
for a_target in to_this.expanduser().search("*"):
|
|
68
|
+
symlink_func(this=this.joinpath(a_target.name), to_this=a_target, prioritize_to_this=overwrite)
|
|
69
|
+
except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
|
|
70
|
+
else:
|
|
71
|
+
try: symlink_func(this=this, to_this=to_this, prioritize_to_this=overwrite)
|
|
72
|
+
except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
|
|
73
|
+
|
|
74
|
+
if program_key == "ssh" and system == "Linux": # permissions of ~/dotfiles/.ssh should be adjusted
|
|
75
|
+
try:
|
|
76
|
+
subprocess.run("chmod 700 ~/.ssh/", check=True)
|
|
77
|
+
subprocess.run("chmod 700 ~/dotfiles/creds/.ssh/", check=True) # may require sudo
|
|
78
|
+
subprocess.run("chmod 600 ~/dotfiles/creds/.ssh/*", check=True)
|
|
79
|
+
except Exception as e:
|
|
80
|
+
ERROR_LIST.append(e)
|
|
81
|
+
print("Caught error", e)
|
|
82
|
+
|
|
83
|
+
if system == "Linux": Terminal().run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R')
|
|
84
|
+
print("\n\n", "*" * 200)
|
|
85
|
+
if len(ERROR_LIST) > 0:
|
|
86
|
+
print("Errors caught: ", ERROR_LIST)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def main(choice: Optional[str] = None):
|
|
90
|
+
console = Console()
|
|
91
|
+
print("\n")
|
|
92
|
+
console.rule("CREATING SYMLINKS")
|
|
93
|
+
main_symlinks(choice=choice)
|
|
94
|
+
|
|
95
|
+
print("\n")
|
|
96
|
+
console.rule("CREATING SYMLINKS")
|
|
97
|
+
create_default_shell_profile()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == '__main__':
|
|
101
|
+
pass
|
machineconfig/profile/shell.py
CHANGED
|
@@ -22,10 +22,10 @@ system = platform.system()
|
|
|
22
22
|
def create_default_shell_profile():
|
|
23
23
|
profile_path = get_shell_profile_path()
|
|
24
24
|
profile = profile_path.read_text()
|
|
25
|
-
if system == "Windows": source = f". {LIBRARY_ROOT.joinpath('settings/shells/pwsh/init.ps1').collapseuser().
|
|
26
|
-
else: source = f"source {LIBRARY_ROOT.joinpath('settings/shells/bash/init.sh').collapseuser().
|
|
25
|
+
if system == "Windows": source = f". {LIBRARY_ROOT.joinpath('settings/shells/pwsh/init.ps1').collapseuser().to_str().replace('~', '$HOME')}"
|
|
26
|
+
else: source = f"source {LIBRARY_ROOT.joinpath('settings/shells/bash/init.sh').collapseuser().to_str().replace('~', '$HOME')}"
|
|
27
27
|
|
|
28
|
-
if source in profile: print(
|
|
28
|
+
if source in profile: print("Skipping sourcing init script; already in profile")
|
|
29
29
|
else:
|
|
30
30
|
profile += "\n" + source + "\n"
|
|
31
31
|
if system == "Linux":
|
|
@@ -37,9 +37,12 @@ def create_default_shell_profile():
|
|
|
37
37
|
|
|
38
38
|
def get_shell_profile_path():
|
|
39
39
|
if system == "Windows":
|
|
40
|
-
|
|
40
|
+
obj = Terminal().run("$PROFILE", shell="pwsh")
|
|
41
|
+
res = obj.op2path()
|
|
41
42
|
if isinstance(res, P): profile_path = res
|
|
42
|
-
else:
|
|
43
|
+
else:
|
|
44
|
+
obj.print(capture=False)
|
|
45
|
+
raise ValueError(f"Could not get profile path for Windows. Got {res}")
|
|
43
46
|
elif system == "Linux": profile_path = P("~/.bashrc").expanduser()
|
|
44
47
|
else: raise ValueError(f"Not implemented for this system {system}")
|
|
45
48
|
print(f"Working on shell profile `{profile_path}`")
|
|
@@ -50,7 +53,7 @@ def main_env_path(choice: Optional[str] = None, profile_path: Optional[str] = No
|
|
|
50
53
|
env_path = LIBRARY_ROOT.joinpath("profile/env_path.toml").readit()
|
|
51
54
|
dirs = env_path[f'path_{system.lower()}']['extension']
|
|
52
55
|
|
|
53
|
-
print(
|
|
56
|
+
print("Current PATH: ", "\n============")
|
|
54
57
|
P.get_env().PATH.print()
|
|
55
58
|
|
|
56
59
|
if choice is None:
|
|
@@ -62,7 +65,7 @@ def main_env_path(choice: Optional[str] = None, profile_path: Optional[str] = No
|
|
|
62
65
|
|
|
63
66
|
addition = PathVar.append_temporarily(dirs=dirs)
|
|
64
67
|
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 +
|
|
68
|
+
profile_path_obj.copy(name=profile_path_obj.name + ".orig_" + randstr())
|
|
66
69
|
profile_path_obj.modify_text(addition, addition, replace_line=False, notfound_append=True)
|
|
67
70
|
|
|
68
71
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
"""
|
|
2
|
+
"""
|
|
3
|
+
CC
|
|
3
4
|
"""
|
|
4
5
|
|
|
5
|
-
from crocodile.file_management import P
|
|
6
|
+
from crocodile.file_management import P
|
|
7
|
+
from crocodile.core import Struct
|
|
6
8
|
from crocodile.meta import RepeatUntilNoException
|
|
7
9
|
import getpass
|
|
8
10
|
from machineconfig.scripts.python.cloud_sync import parse_cloud_source_target, ArgsDefaults, Args
|
|
@@ -13,22 +15,20 @@ import os
|
|
|
13
15
|
from typing import Optional
|
|
14
16
|
|
|
15
17
|
|
|
16
|
-
@RepeatUntilNoException()
|
|
18
|
+
@RepeatUntilNoException(retry=3, sleep=1)
|
|
17
19
|
def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] = None) -> None:
|
|
18
20
|
folder_obj = P.cwd() if folder is None else P(folder)
|
|
19
21
|
|
|
20
22
|
if os.environ.get("DECRYPTION_PASSWORD") is not None:
|
|
21
|
-
pwd: str
|
|
23
|
+
pwd: str=str(os.environ.get("DECRYPTION_PASSWORD"))
|
|
22
24
|
else:
|
|
23
25
|
pwd = getpass.getpass(prompt="Enter decryption password: ")
|
|
24
|
-
|
|
25
26
|
if url is None:
|
|
26
27
|
if os.environ.get("SHARE_URL") is not None:
|
|
27
28
|
url = os.environ.get("SHARE_URL")
|
|
28
29
|
assert url is not None
|
|
29
30
|
else:
|
|
30
31
|
url = input("Enter share url: ")
|
|
31
|
-
|
|
32
32
|
from rich.progress import Progress
|
|
33
33
|
with Progress(transient=True) as progress:
|
|
34
34
|
_task = progress.add_task("Downloading ... ", total=None)
|
|
@@ -63,23 +63,26 @@ def arg_parser() -> None:
|
|
|
63
63
|
|
|
64
64
|
args = parser.parse_args()
|
|
65
65
|
args_dict = vars(args)
|
|
66
|
-
source: str
|
|
67
|
-
target: str
|
|
66
|
+
source: str=args_dict.pop("source")
|
|
67
|
+
target: str=args_dict.pop("target")
|
|
68
68
|
args_obj = Args(**args_dict)
|
|
69
|
-
Struct(args_obj.__dict__).print(as_config=True, title=
|
|
69
|
+
Struct(args_obj.__dict__).print(as_config=True, title="CLI config")
|
|
70
70
|
|
|
71
|
-
if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")):
|
|
72
|
-
|
|
71
|
+
if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")):
|
|
72
|
+
return get_securely_shared_file(url=source, folder=target)
|
|
73
|
+
if args_obj.rel2home is True and args_obj.root is None:
|
|
74
|
+
args_obj.root = "myhome"
|
|
73
75
|
|
|
76
|
+
# print(f"source: {source}")
|
|
74
77
|
cloud, source, target = parse_cloud_source_target(args=args_obj, source=source, target=target)
|
|
75
78
|
|
|
76
|
-
assert args_obj.key is None,
|
|
79
|
+
assert args_obj.key is None, "Key is not supported yet."
|
|
77
80
|
if cloud in source:
|
|
78
81
|
P(target).from_cloud(cloud=cloud, remotepath=source.replace(cloud + ":", ""),
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
unzip=args_obj.zip, decrypt=args_obj.encrypt, pwd=args_obj.pwd,
|
|
83
|
+
overwrite=args_obj.overwrite,
|
|
84
|
+
rel2home=args_obj.rel2home, os_specific=args_obj.os_specific, root=args_obj.root, strict=False,
|
|
85
|
+
)
|
|
83
86
|
elif cloud in target:
|
|
84
87
|
res = P(source).to_cloud(cloud=cloud, remotepath=target.replace(cloud + ":", ""),
|
|
85
88
|
zip=args_obj.zip, encrypt=args_obj.encrypt, pwd=args_obj.pwd,
|