machineconfig 1.7__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 +2 -2
- machineconfig/jobs/python/check_installations.py +37 -31
- machineconfig/jobs/python/create_bootable_media.py +4 -4
- machineconfig/jobs/python/create_zellij_template.py +3 -2
- machineconfig/jobs/python/python_cargo_build_share.py +14 -9
- machineconfig/jobs/python/python_ve_symlink.py +6 -6
- machineconfig/jobs/{python_linux_installers/dev → script_installer}/azure_data_studio.py +6 -5
- machineconfig/jobs/{python_windows_installers/dev → script_installer}/bypass_paywall.py +5 -4
- machineconfig/jobs/script_installer/code.py +34 -0
- machineconfig/jobs/{python_linux_installers/dev → script_installer}/docker_desktop.py +2 -2
- machineconfig/jobs/script_installer/ngrok.py +29 -0
- machineconfig/jobs/script_installer/skim.py +21 -0
- machineconfig/jobs/script_installer/wezterm.py +34 -0
- machineconfig/profile/create.py +8 -6
- machineconfig/profile/shell.py +15 -13
- machineconfig/scripts/python/cloud_copy.py +14 -13
- machineconfig/scripts/python/cloud_mount.py +27 -11
- machineconfig/scripts/python/cloud_repo_sync.py +32 -14
- machineconfig/scripts/python/cloud_sync.py +9 -9
- machineconfig/scripts/python/croshell.py +3 -3
- machineconfig/scripts/python/devops.py +22 -6
- machineconfig/scripts/python/devops_add_identity.py +7 -6
- machineconfig/scripts/python/devops_add_ssh_key.py +10 -9
- machineconfig/scripts/python/devops_backup_retrieve.py +5 -5
- machineconfig/scripts/python/devops_devapps_install.py +13 -14
- machineconfig/scripts/python/devops_update_repos.py +5 -4
- machineconfig/scripts/python/dotfile.py +8 -4
- machineconfig/scripts/python/fire_jobs.py +95 -24
- machineconfig/scripts/python/ftpx.py +1 -1
- machineconfig/scripts/python/mount_nfs.py +13 -10
- machineconfig/scripts/python/mount_nw_drive.py +4 -3
- machineconfig/scripts/python/mount_ssh.py +8 -5
- machineconfig/scripts/python/repos.py +21 -20
- machineconfig/scripts/python/snapshot.py +2 -2
- machineconfig/scripts/python/start_slidev.py +104 -0
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +20 -34
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +11 -12
- machineconfig/utils/installer.py +96 -204
- machineconfig/utils/scheduling.py +1 -1
- machineconfig/utils/utils.py +102 -51
- machineconfig/utils/ve.py +96 -13
- {machineconfig-1.7.dist-info → machineconfig-1.8.dist-info}/METADATA +8 -8
- machineconfig-1.8.dist-info/RECORD +70 -0
- machineconfig/jobs/python_generic_installers/archive/gopass.py +0 -18
- machineconfig/jobs/python_generic_installers/archive/nvim.py +0 -20
- machineconfig/jobs/python_generic_installers/archive/opencommit.py +0 -25
- machineconfig/jobs/python_generic_installers/archive/strongbox.py +0 -33
- machineconfig/jobs/python_generic_installers/dev/__init__.py +0 -0
- machineconfig/jobs/python_linux_installers/archive/__init__.py +0 -0
- machineconfig/jobs/python_linux_installers/archive/bandwhich.py +0 -14
- machineconfig/jobs/python_linux_installers/archive/ranger.py +0 -19
- machineconfig/jobs/python_linux_installers/dev/bytehound.py +0 -20
- machineconfig/jobs/python_linux_installers/dev/nnn.py +0 -22
- machineconfig/jobs/python_windows_installers/archive/ntop.py +0 -21
- machineconfig/jobs/python_windows_installers/dev/obs_background_removal_plugin.py +0 -22
- machineconfig/scripts/python/choose_ohmybash_theme.py +0 -31
- machineconfig/scripts/python/choose_ohmyposh_theme.py +0 -57
- machineconfig/utils/pandas_type.py +0 -37
- machineconfig/utils/to_exe.py +0 -7
- machineconfig-1.7.dist-info/RECORD +0 -81
- /machineconfig/jobs/{python_generic_installers/archive → script_installer}/__init__.py +0 -0
- {machineconfig-1.7.dist-info → machineconfig-1.8.dist-info}/WHEEL +0 -0
- {machineconfig-1.7.dist-info → machineconfig-1.8.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
"""Set Windows Terminal Settings
|
|
3
3
|
"""
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
from crocodile.core import randstr, List as L
|
|
6
|
+
from crocodile.file_management import P, Read, Save
|
|
5
7
|
import crocodile.environment as env
|
|
8
|
+
from machineconfig.utils.utils import LIBRARY_ROOT
|
|
6
9
|
from uuid import uuid4
|
|
7
10
|
import os
|
|
8
11
|
from typing import Any
|
|
@@ -27,14 +30,14 @@ class TerminalSettings(object):
|
|
|
27
30
|
tmp = os.getenv("LOCALAPPDATA")
|
|
28
31
|
if not isinstance(tmp, str):
|
|
29
32
|
raise ValueError("Could not find LOCALAPPDATA environment variable.")
|
|
30
|
-
self.path =
|
|
31
|
-
self.path.copy(append=".orig_" +
|
|
32
|
-
self.dat = self.path
|
|
33
|
-
self.profs =
|
|
33
|
+
self.path = P(tmp).joinpath(r"Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json")
|
|
34
|
+
self.path.copy(append=".orig_" + randstr())
|
|
35
|
+
self.dat: dict[str, Any] = Read.json(self.path)
|
|
36
|
+
self.profs = L(self.dat["profiles"]["list"])
|
|
34
37
|
|
|
35
38
|
def save_terminal_settings(self):
|
|
36
39
|
self.dat["profiles"]["list"] = list(self.profs)
|
|
37
|
-
self.dat
|
|
40
|
+
Save.json(obj=self.dat, path=self.path, indent=5)
|
|
38
41
|
|
|
39
42
|
# ========================= Terminal Settings =========================================
|
|
40
43
|
def update_default_settings(self):
|
|
@@ -73,14 +76,10 @@ class TerminalSettings(object):
|
|
|
73
76
|
else: print("Powershell profile was not found in the list of profile and therefore was not made the deafult.")
|
|
74
77
|
|
|
75
78
|
def add_croshell(self):
|
|
76
|
-
# Adding croshell if it is not there.
|
|
77
|
-
# py_pr = tb.copy.deepcopy(pr) # use it as a template for the new profile.
|
|
78
|
-
import machineconfig
|
|
79
|
-
lib_root = tb.P(machineconfig.__file__).parent.collapseuser().as_posix()
|
|
80
79
|
croshell = dict(name="croshell",
|
|
81
80
|
guid="{" + str(uuid4()) + "}",
|
|
82
81
|
# commandline=f"powershell.exe -Command \"{activate} ipython -i -c 'from crocodile.toolbox import *'\"",
|
|
83
|
-
commandline=f'powershell.exe -Command "{
|
|
82
|
+
commandline=f'powershell.exe -Command "{LIBRARY_ROOT.as_posix()}/scripts/windows/croshell.ps1"',
|
|
84
83
|
startingDirectory="%USERPROFILE%", # "%USERPROFILE%", # None: inherent from parent process.
|
|
85
84
|
)
|
|
86
85
|
# startingDirectory = None means: inheret from parent process, which will is the default, which point to /System32
|
|
@@ -114,7 +113,7 @@ class TerminalSettings(object):
|
|
|
114
113
|
elif name == "Command Prompt": cmd = profile
|
|
115
114
|
elif name == "Azure Cloud Shell": azure = profile
|
|
116
115
|
else: others.append(profile)
|
|
117
|
-
self.profs =
|
|
116
|
+
self.profs = L([item for item in [pwsh, croshell, ubuntu, wpwsh, cmd, azure] + others if item is not None])
|
|
118
117
|
|
|
119
118
|
|
|
120
119
|
def main():
|
machineconfig/utils/installer.py
CHANGED
|
@@ -5,11 +5,12 @@ from rich.console import Console
|
|
|
5
5
|
|
|
6
6
|
from crocodile.file_management import P, List as L, Read, Struct
|
|
7
7
|
from crocodile.meta import Terminal
|
|
8
|
-
from machineconfig.utils.utils import INSTALL_VERSION_ROOT, INSTALL_TMP_DIR, LIBRARY_ROOT
|
|
8
|
+
from machineconfig.utils.utils import INSTALL_VERSION_ROOT, INSTALL_TMP_DIR, LIBRARY_ROOT, check_tool_exists
|
|
9
9
|
|
|
10
|
-
from dataclasses import dataclass
|
|
10
|
+
# from dataclasses import dataclass
|
|
11
11
|
from typing import Optional, Any
|
|
12
12
|
import platform
|
|
13
|
+
# import os
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def find_move_delete_windows(downloaded_file_path: P, exe_name: Optional[str] = None, delete: bool = True, rename_to: Optional[str] = None):
|
|
@@ -24,9 +25,9 @@ def find_move_delete_windows(downloaded_file_path: P, exe_name: Optional[str] =
|
|
|
24
25
|
else: exe = downloaded_file_path.search("*.exe", r=True).list[0]
|
|
25
26
|
if rename_to and exe.name != rename_to:
|
|
26
27
|
exe = exe.with_name(name=rename_to, inplace=True)
|
|
27
|
-
exe.move(folder=P.get_env().WindowsApps, overwrite=True) # latest version overwrites older installation.
|
|
28
|
+
exe_new_location = exe.move(folder=P.get_env().WindowsApps, overwrite=True) # latest version overwrites older installation.
|
|
28
29
|
if delete: downloaded_file_path.delete(sure=True)
|
|
29
|
-
return
|
|
30
|
+
return exe_new_location
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
def find_move_delete_linux(downloaded: P, tool_name: str, delete: Optional[bool] = True, rename_to: Optional[str] = None):
|
|
@@ -35,7 +36,13 @@ def find_move_delete_linux(downloaded: P, tool_name: str, delete: Optional[bool]
|
|
|
35
36
|
else:
|
|
36
37
|
res = downloaded.search(f"*{tool_name}*", folders=False, r=True)
|
|
37
38
|
if len(res) == 1: exe = res.list[0]
|
|
38
|
-
else:
|
|
39
|
+
else:
|
|
40
|
+
exe_search_res = downloaded.search(tool_name, folders=False, r=True)
|
|
41
|
+
if len(exe_search_res) == 0:
|
|
42
|
+
print(f"No search results for `{tool_name}` in `{downloaded}`")
|
|
43
|
+
raise IndexError(f"No executable found in {downloaded}")
|
|
44
|
+
else:
|
|
45
|
+
exe = exe_search_res.list[0]
|
|
39
46
|
if rename_to and exe.name != rename_to:
|
|
40
47
|
exe = exe.with_name(name=rename_to, inplace=True)
|
|
41
48
|
print(f"MOVING file `{repr(exe)}` to '/usr/local/bin'")
|
|
@@ -43,79 +50,128 @@ def find_move_delete_linux(downloaded: P, tool_name: str, delete: Optional[bool]
|
|
|
43
50
|
# exe.move(folder=r"/usr/local/bin", overwrite=False)
|
|
44
51
|
Terminal().run(f"sudo mv {exe} /usr/local/bin/").print_if_unsuccessful(desc="MOVING executable to /usr/local/bin", strict_err=True, strict_returncode=True)
|
|
45
52
|
if delete: downloaded.delete(sure=True)
|
|
46
|
-
|
|
53
|
+
exe_new_location = P(r"/usr/local/bin").joinpath(exe.name)
|
|
54
|
+
return exe_new_location
|
|
47
55
|
|
|
48
56
|
|
|
49
57
|
class Installer:
|
|
50
|
-
def __init__(self, repo_url: str, doc: str, filename_template_windows_amd_64: str, filename_template_linux_amd_64: str, strip_v: bool, exe_name: str):
|
|
58
|
+
def __init__(self, repo_url: str, name: str, doc: str, filename_template_windows_amd_64: str, filename_template_linux_amd_64: str, strip_v: bool, exe_name: str):
|
|
51
59
|
self.repo_url = repo_url
|
|
60
|
+
self.name = name
|
|
52
61
|
self.doc = doc
|
|
53
62
|
self.filename_template_windows_amd_64 = filename_template_windows_amd_64
|
|
54
63
|
self.filename_template_linux_amd_64 = filename_template_linux_amd_64
|
|
55
64
|
self.strip_v = strip_v
|
|
56
65
|
self.exe_name = exe_name
|
|
57
66
|
def __repr__(self) -> str: return f"Installer of {self.repo_url}"
|
|
58
|
-
def get_description(self):
|
|
67
|
+
def get_description(self):
|
|
68
|
+
# old_version_cli = Terminal().run(f"{self.exe_name} --version").op.replace("\n", "")
|
|
69
|
+
# old_version_cli = os.system(f"{self.exe_name} --version").replace("\n", "")
|
|
70
|
+
old_version_cli = check_tool_exists(self.exe_name)
|
|
71
|
+
old_version_cli_str = "✅" if old_version_cli else "❌"
|
|
72
|
+
# name_version = f"{self.exe_name} {old_version_cli_str}"
|
|
73
|
+
return f"{self.exe_name:<12} {old_version_cli_str} {self.doc}"
|
|
59
74
|
def to_dict(self): return self.__dict__
|
|
60
75
|
@staticmethod
|
|
61
|
-
def from_dict(d: dict[str, Any]):
|
|
62
|
-
try: return Installer(**d)
|
|
76
|
+
def from_dict(d: dict[str, Any], name: str):
|
|
77
|
+
try: return Installer(name=name, **d)
|
|
63
78
|
except Exception as ex:
|
|
64
79
|
Struct(d).print(as_config=True)
|
|
65
80
|
raise ex
|
|
66
81
|
@staticmethod
|
|
67
|
-
def
|
|
82
|
+
def choose_app_and_install():
|
|
68
83
|
from machineconfig.utils.utils import choose_one_option
|
|
69
84
|
path = choose_one_option(options=LIBRARY_ROOT.joinpath("jobs").search("config.json", r=True).list)
|
|
70
85
|
config: dict[str, Any] = Read.json(path) # /python_generic_installers/config.json"))
|
|
71
86
|
# binary = choose_one_option(options=list(config.keys()), fzf=True)
|
|
72
|
-
for
|
|
73
|
-
installer = Installer.from_dict(
|
|
87
|
+
for keys, dict_ in config.items():
|
|
88
|
+
installer = Installer.from_dict(d=dict_, name=keys)
|
|
74
89
|
installer.install(version=None)
|
|
75
90
|
|
|
76
91
|
def install_robust(self, version: Optional[str]):
|
|
77
92
|
try:
|
|
78
|
-
|
|
93
|
+
old_version_cli = Terminal().run(f"{self.exe_name} --version").op.replace("\n", "")
|
|
79
94
|
self.install(version=version)
|
|
80
|
-
|
|
81
|
-
if
|
|
82
|
-
else: return f"🤩 {self.exe_name} updated from {
|
|
95
|
+
new_version_cli = Terminal().run(f"{self.exe_name} --version").op.replace("\n", "")
|
|
96
|
+
if old_version_cli == new_version_cli: return f"📦️ 😑 {self.exe_name}, same version: {old_version_cli}"
|
|
97
|
+
else: return f"📦️ 🤩 {self.exe_name} updated from {old_version_cli} === to ===> {new_version_cli}"
|
|
83
98
|
except Exception as ex:
|
|
84
99
|
print(ex)
|
|
85
|
-
return f"Failed at {self.exe_name} with {ex}"
|
|
86
|
-
|
|
100
|
+
return f"📦️ Failed at {self.exe_name} with {ex}"
|
|
87
101
|
|
|
88
102
|
def install(self, version: Optional[str]):
|
|
103
|
+
if self.repo_url == "CUSTOM":
|
|
104
|
+
import machineconfig.jobs.script_installer as custom_installer
|
|
105
|
+
installer_path = P(custom_installer.__file__).parent.joinpath(self.exe_name + ".py")
|
|
106
|
+
import runpy
|
|
107
|
+
program = runpy.run_path(str(installer_path), run_name="__main__")['main'](version=version)
|
|
108
|
+
Terminal().run(program, shell="default")
|
|
109
|
+
version_to_be_installed = str(version)
|
|
110
|
+
elif "npm " in self.repo_url:
|
|
111
|
+
Terminal().run(self.repo_url, shell="default").print_if_unsuccessful(desc="npm install", strict_err=True, strict_returncode=True)
|
|
112
|
+
version_to_be_installed = "npmLatest"
|
|
113
|
+
elif "pip " in self.repo_url:
|
|
114
|
+
Terminal().run(self.repo_url, shell="default").print_if_unsuccessful(desc="pip install", strict_err=True, strict_returncode=True)
|
|
115
|
+
version_to_be_installed = "pipLatest"
|
|
116
|
+
else:
|
|
117
|
+
downloaded, version_to_be_installed = self.download(version=version)
|
|
118
|
+
if downloaded.str.endswith(".deb"):
|
|
119
|
+
assert platform.system() == "Linux"
|
|
120
|
+
Terminal().run(f"sudo apt install -y {downloaded}").print_if_unsuccessful(desc="Installing .deb", strict_err=True, strict_returncode=True)
|
|
121
|
+
downloaded.delete(sure=True)
|
|
122
|
+
else:
|
|
123
|
+
if platform.system() == "Windows":
|
|
124
|
+
exe = find_move_delete_windows(downloaded_file_path=downloaded, exe_name=self.exe_name, delete=True, rename_to=self.exe_name + ".exe")
|
|
125
|
+
elif platform.system() == "Linux":
|
|
126
|
+
exe = find_move_delete_linux(downloaded=downloaded, tool_name=self.exe_name, delete=True, rename_to=self.exe_name)
|
|
127
|
+
else: raise NotImplementedError(f"System {platform.system()} not implemented")
|
|
128
|
+
_ = exe
|
|
129
|
+
if exe.name.replace(".exe", "") != self.exe_name.replace(".exe", ""):
|
|
130
|
+
from rich import print as pprint
|
|
131
|
+
from rich.panel import Panel
|
|
132
|
+
pprint(Panel(f"Expected exe name: [red]{self.exe_name}[/red] \nAttained name: [red]{exe.name.replace('.exe', '')}[/red]", title="exe name mismatch", subtitle=self.repo_url))
|
|
133
|
+
new_exe_name = self.exe_name + ".exe" if platform.system() == "Windows" else self.exe_name
|
|
134
|
+
exe.with_name(name=new_exe_name, inplace=True, overwrite=True)
|
|
135
|
+
INSTALL_VERSION_ROOT.joinpath(self.exe_name).create(parents_only=True).write_text(version_to_be_installed)
|
|
136
|
+
|
|
137
|
+
def download(self, version: Optional[str]):
|
|
89
138
|
if "github" not in self.repo_url or ".zip" in self.repo_url or ".tar.gz" in self.repo_url:
|
|
90
139
|
download_link = P(self.repo_url)
|
|
140
|
+
version_to_be_installed = "predefined_url"
|
|
141
|
+
print(f"📦️ Version to be installed: {version_to_be_installed}")
|
|
142
|
+
elif "http" in self.filename_template_linux_amd_64 or "http" in self.filename_template_windows_amd_64:
|
|
143
|
+
if platform.system() == "Windows":
|
|
144
|
+
download_link = P(self.filename_template_windows_amd_64)
|
|
145
|
+
elif platform.system() == "Linux":
|
|
146
|
+
download_link = P(self.filename_template_linux_amd_64)
|
|
147
|
+
else: raise NotImplementedError(f"📦️ System {platform.system()} not implemented")
|
|
148
|
+
version_to_be_installed = "predefined_url"
|
|
91
149
|
else:
|
|
92
150
|
release_url, version_to_be_installed = self.get_github_release(repo_url=self.repo_url, version=version)
|
|
151
|
+
print(f"📦️ Version to be installed: {version_to_be_installed}")
|
|
152
|
+
print(f"📦️ Release URL: {release_url}")
|
|
93
153
|
version_to_be_installed_stripped = version_to_be_installed.replace("v", "") if self.strip_v else version_to_be_installed
|
|
94
154
|
if platform.system() == "Windows":
|
|
95
155
|
file_name = self.filename_template_windows_amd_64.format(version_to_be_installed_stripped)
|
|
96
156
|
elif platform.system() == "Linux":
|
|
97
157
|
file_name = self.filename_template_linux_amd_64.format(version_to_be_installed_stripped)
|
|
98
|
-
else: raise NotImplementedError(f"System {platform.system()} not implemented")
|
|
158
|
+
else: raise NotImplementedError(f"📦️ System {platform.system()} not implemented")
|
|
159
|
+
print(f"📦️ File name", file_name)
|
|
99
160
|
download_link = release_url.joinpath(file_name)
|
|
100
|
-
print("Downloading", download_link.as_url_str())
|
|
161
|
+
print("📦️ Downloading: ", download_link.as_url_str())
|
|
101
162
|
downloaded = download_link.download(folder=INSTALL_TMP_DIR).decompress()
|
|
102
|
-
|
|
103
|
-
elif platform.system() == "Linux": exe = find_move_delete_linux(downloaded=downloaded, tool_name=self.exe_name, delete=True, rename_to=self.exe_name)
|
|
104
|
-
else: raise NotImplementedError(f"System {platform.system()} not implemented")
|
|
105
|
-
if exe.name.replace(".exe", "") != self.exe_name:
|
|
106
|
-
from rich import print as pprint
|
|
107
|
-
from rich.panel import Panel
|
|
108
|
-
pprint(Panel(f"Expected exe name, [red]{self.exe_name}! Attained name: {exe.name}", title="exe mismatch", subtitle=self.repo_url))
|
|
163
|
+
return downloaded, version_to_be_installed
|
|
109
164
|
|
|
110
165
|
@staticmethod
|
|
111
166
|
def get_github_release(repo_url: str, version: Optional[str] = None):
|
|
112
167
|
print("\n\n\n")
|
|
113
|
-
print(f"Inspecting latest release @ {repo_url} ...")
|
|
168
|
+
print(f"📦️ Inspecting latest release @ {repo_url} ...")
|
|
114
169
|
# with console.status("Installing..."): # makes troubles on linux when prompt asks for password to move file to /usr/bin
|
|
115
170
|
if version is None:
|
|
116
171
|
import requests # https://docs.github.com/en/repositories/releasing-projects-on-github/linking-to-releases
|
|
117
172
|
_latest_version = requests.get(str(repo_url) + "/releases/latest", timeout=10).url.split("/")[-1] # this is to resolve the redirection that occures: https://stackoverflow.com/questions/36070821/how-to-get-redirect-url-using-python-requests
|
|
118
173
|
version_to_be_installed = _latest_version
|
|
174
|
+
# print(version_to_be_installed)
|
|
119
175
|
else:
|
|
120
176
|
version_to_be_installed = version
|
|
121
177
|
release_url = P(repo_url + "/releases/download/" + version_to_be_installed)
|
|
@@ -124,188 +180,24 @@ class Installer:
|
|
|
124
180
|
@staticmethod
|
|
125
181
|
def check_if_installed_already(exe_name: str, version: str):
|
|
126
182
|
version_to_be_installed = version
|
|
127
|
-
# existing_version_cli = Terminal().run(f"{exe_name or tool_name} --version", shell="powershell").op_if_successfull_or_default(strict_err=True, strict_returcode=True)
|
|
128
183
|
tmp_path = INSTALL_VERSION_ROOT.joinpath(exe_name).create(parents_only=True)
|
|
129
184
|
if tmp_path.exists(): existing_version = tmp_path.read_text().rstrip()
|
|
130
185
|
else: existing_version = None
|
|
131
186
|
|
|
132
187
|
if existing_version is not None:
|
|
133
188
|
if existing_version == version_to_be_installed:
|
|
134
|
-
print(f"⚠️ {exe_name} already installed at version {version_to_be_installed}. See {INSTALL_VERSION_ROOT}")
|
|
189
|
+
print(f"📦️ ⚠️ {exe_name} already installed at version {version_to_be_installed}. See {INSTALL_VERSION_ROOT}")
|
|
135
190
|
return True
|
|
136
191
|
else:
|
|
137
192
|
# print(f"Latest version is {version}, logged at {tmp_path}")
|
|
138
|
-
print(f"⬆️ {exe_name} installed at version {existing_version.rstrip()} --> Installing version {version_to_be_installed} ")
|
|
193
|
+
print(f"📦️ ⬆️ {exe_name} installed at version {existing_version.rstrip()} --> Installing version {version_to_be_installed} ")
|
|
139
194
|
tmp_path.write_text(version_to_be_installed)
|
|
140
195
|
else:
|
|
141
|
-
print(f"{exe_name} has no known version. Installing version `{version_to_be_installed}` ")
|
|
196
|
+
print(f"📦️ {exe_name} has no known version. Installing version `{version_to_be_installed}` ")
|
|
142
197
|
tmp_path.write_text(version_to_be_installed)
|
|
143
198
|
return False
|
|
144
199
|
|
|
145
200
|
|
|
146
|
-
# ------------------------ ARCHIVE ------------------------
|
|
147
|
-
@dataclass
|
|
148
|
-
class ReleaseFileNameStructure:
|
|
149
|
-
repo_url: str
|
|
150
|
-
fixed_file_name_windows_amd_64: Optional[str] # the release has a fixed file name, so no need to compose it
|
|
151
|
-
fixed_file_name_linux_amd_64: Optional[str] # the release has a fixed file name, so no need to compose it
|
|
152
|
-
tool_name: str # as it appears in the release file name
|
|
153
|
-
exe_name: str # as it is called from the terminal, i.e. the name of the executable file
|
|
154
|
-
suffix_window_amd_64: Optional[str]
|
|
155
|
-
suffix_linux_amd_64: Optional[str]
|
|
156
|
-
compression_windows: Optional[str]
|
|
157
|
-
compression_linux: Optional[str]
|
|
158
|
-
sep: str = "-"
|
|
159
|
-
strip_v: bool = False
|
|
160
|
-
doc: str = ""
|
|
161
|
-
|
|
162
|
-
def to_dict(self):
|
|
163
|
-
return self.__dict__
|
|
164
|
-
|
|
165
|
-
@staticmethod
|
|
166
|
-
def from_dict(d: dict[str, Any]):
|
|
167
|
-
return ReleaseFileNameStructure(**d)
|
|
168
|
-
|
|
169
|
-
def compose_filename(self, version: Optional[str]) -> str:
|
|
170
|
-
if platform.system() == "Windows": fixed_file_name = self.fixed_file_name_windows_amd_64
|
|
171
|
-
elif platform.system() == "Linux": fixed_file_name = self.fixed_file_name_linux_amd_64
|
|
172
|
-
else: raise NotImplementedError(f"System {platform.system()} not implemented")
|
|
173
|
-
if fixed_file_name is not None: return fixed_file_name
|
|
174
|
-
assert version is not None, f"Version must be passed if fixed_file_name is None"
|
|
175
|
-
version_in_filename = version.replace("v", "") if self.strip_v else version
|
|
176
|
-
if platform.system() == "Windows":
|
|
177
|
-
compression = self.compression_windows
|
|
178
|
-
suffix = self.suffix_window_amd_64
|
|
179
|
-
assert suffix is not None, f"No binaries for windows found for {self.tool_name}"
|
|
180
|
-
elif platform.system() == "Linux":
|
|
181
|
-
compression = self.compression_linux
|
|
182
|
-
suffix = self.suffix_linux_amd_64
|
|
183
|
-
assert suffix is not None, f"No binaries for linux found for {self.tool_name}"
|
|
184
|
-
else: raise NotImplementedError(f"System {platform.system()} not implemented")
|
|
185
|
-
file_name = f'{self.tool_name}{self.sep}{version_in_filename}{self.sep}{suffix}'
|
|
186
|
-
if compression is not None: file_name += f".{compression}"
|
|
187
|
-
return file_name
|
|
188
|
-
|
|
189
|
-
def compose_download_link(self, version: Optional[str]):
|
|
190
|
-
release_url, version_to_be_installed = Installer.get_github_release(repo_url=self.repo_url, version=version)
|
|
191
|
-
file_name = self.compose_filename(version=version_to_be_installed)
|
|
192
|
-
download_link = release_url.joinpath(file_name)
|
|
193
|
-
return download_link
|
|
194
|
-
|
|
195
|
-
def install(self, version: Optional[str] = None):
|
|
196
|
-
gh_release = self
|
|
197
|
-
release_url, version_to_be_installed = Installer.get_github_release(repo_url=gh_release.repo_url, version=version)
|
|
198
|
-
installed_already = Installer.check_if_installed_already(exe_name=gh_release.exe_name, version=version_to_be_installed)
|
|
199
|
-
|
|
200
|
-
if installed_already: return None
|
|
201
|
-
# if not download_n_extract: return release_url
|
|
202
|
-
console = Console()
|
|
203
|
-
console.rule(f"Installing {gh_release.exe_name} version {version_to_be_installed}")
|
|
204
|
-
file_name = gh_release.compose_filename(version=version_to_be_installed)
|
|
205
|
-
download_link = release_url.joinpath(file_name)
|
|
206
|
-
|
|
207
|
-
print("Downloading", download_link.as_url_str())
|
|
208
|
-
downloaded = download_link.download(folder=INSTALL_TMP_DIR).decompress()
|
|
209
|
-
if not platform.system() == "Linux": return find_move_delete_windows(downloaded_file_path=downloaded, exe_name=gh_release.exe_name, delete=True)
|
|
210
|
-
return find_move_delete_linux(downloaded=downloaded, tool_name=gh_release.exe_name, delete=True)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
def get_latest_release(repo_url: str, exe_name: str,
|
|
214
|
-
download_n_extract: bool = False,
|
|
215
|
-
suffix: Optional[str] = "x86_64-pc-windows-msvc",
|
|
216
|
-
file_name: Optional[str] = None, # e.g. windows_x86_64.zip
|
|
217
|
-
tool_name: Optional[str] = None,
|
|
218
|
-
delete: bool = True, strip_v: bool = False,
|
|
219
|
-
compression: Optional[str] = None,
|
|
220
|
-
sep: str = "-", version: Optional[str] = None):
|
|
221
|
-
"""Arguments help form last part of URL `filename = f'{tool_name}{sep}{version}{sep}{suffix}.{compression}'`
|
|
222
|
-
Unless `file_name` is passed directly, in which case it is used as is and parameters above are ignored.
|
|
223
|
-
"""
|
|
224
|
-
|
|
225
|
-
console = Console()
|
|
226
|
-
if platform.system() == "Windows":
|
|
227
|
-
gh_release = ReleaseFileNameStructure(repo_url=repo_url, fixed_file_name_linux_amd_64=None, fixed_file_name_windows_amd_64=file_name,
|
|
228
|
-
tool_name=tool_name or exe_name, exe_name=exe_name,
|
|
229
|
-
suffix_window_amd_64=suffix, suffix_linux_amd_64=suffix, compression_windows=compression, compression_linux=compression, sep=sep, strip_v=strip_v)
|
|
230
|
-
elif platform.system() == "Linux":
|
|
231
|
-
gh_release = ReleaseFileNameStructure(repo_url=repo_url, fixed_file_name_windows_amd_64=None, fixed_file_name_linux_amd_64=file_name, tool_name=tool_name or exe_name, exe_name=exe_name, suffix_window_amd_64=suffix, suffix_linux_amd_64=suffix, compression_windows=compression, compression_linux=compression, sep=sep, strip_v=strip_v)
|
|
232
|
-
else: raise NotImplementedError(f"System {platform.system()} not implemented")
|
|
233
|
-
|
|
234
|
-
release_url, version_to_be_installed = Installer.get_github_release(repo_url=gh_release.repo_url, version=version)
|
|
235
|
-
installed_already = Installer.check_if_installed_already(exe_name=exe_name, version=version_to_be_installed)
|
|
236
|
-
|
|
237
|
-
if installed_already: return None
|
|
238
|
-
if not download_n_extract: return release_url
|
|
239
|
-
|
|
240
|
-
console.rule(f"Installing {exe_name} version {version_to_be_installed}")
|
|
241
|
-
file_name = gh_release.compose_filename(version=version_to_be_installed)
|
|
242
|
-
download_link = release_url.joinpath(file_name)
|
|
243
|
-
|
|
244
|
-
print("Downloading", download_link.as_url_str())
|
|
245
|
-
downloaded = download_link.download(folder=INSTALL_TMP_DIR).decompress()
|
|
246
|
-
if not platform.system() == "Linux": return find_move_delete_windows(downloaded_file_path=downloaded, exe_name=exe_name, delete=delete)
|
|
247
|
-
return find_move_delete_linux(downloaded=downloaded, tool_name=exe_name, delete=delete)
|
|
248
|
-
# console.rule(f"Completed Installation")
|
|
249
|
-
# return res
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
def run_python_installer(py_file: P, version: Optional[str] = None):
|
|
253
|
-
try:
|
|
254
|
-
old_version = Terminal().run(f"{py_file.stem} --version", shell="powershell").op.replace("\n", "")
|
|
255
|
-
Read.py(py_file)["main"](version=version)
|
|
256
|
-
new_version = Terminal().run(f"{py_file.stem} --version", shell="powershell").op.replace("\n", "")
|
|
257
|
-
if old_version == new_version: return f"😑 {py_file.stem}, same version: {old_version}"
|
|
258
|
-
else: return f"🤩 {py_file.stem} updated from {old_version} === to ===> {new_version}"
|
|
259
|
-
except Exception as ex:
|
|
260
|
-
print(ex)
|
|
261
|
-
return f"Failed at {py_file.stem} with {ex}"
|
|
262
|
-
|
|
263
|
-
def get_cli_py_installers(system: str, dev: bool, use_config: bool = False):
|
|
264
|
-
if system == "Windows": import machineconfig.jobs.python_windows_installers as inst
|
|
265
|
-
else: import machineconfig.jobs.python_linux_installers as inst
|
|
266
|
-
import machineconfig.jobs.python_generic_installers as gens
|
|
267
|
-
path = P(inst.__file__).parent
|
|
268
|
-
gens_path = P(gens.__file__).parent
|
|
269
|
-
if dev:
|
|
270
|
-
path = path.joinpath("dev")
|
|
271
|
-
gens_path = gens_path.joinpath("dev")
|
|
272
|
-
if use_config: return L([path.joinpath("config.json"), gens_path.joinpath("config.json")])
|
|
273
|
-
return path.search("*.py", filters=[lambda x: "__init__" not in str(x)]) + gens_path.search("*.py", filters=[lambda x: "__init__" not in str(x)])
|
|
274
|
-
|
|
275
|
-
def install_all(installers: L[P], safe: bool = False, jobs: int = 10, fresh: bool = False):
|
|
276
|
-
if fresh: INSTALL_VERSION_ROOT.delete(sure=True)
|
|
277
|
-
if safe:
|
|
278
|
-
from machineconfig.jobs.python.check_installations import APP_SUMMARY_PATH
|
|
279
|
-
apps_dir = APP_SUMMARY_PATH.readit()
|
|
280
|
-
if platform.system().lower() == "windows":
|
|
281
|
-
apps_dir.search("*").apply(lambda app: app.move(folder=P.get_env().WindowsApps))
|
|
282
|
-
elif platform.system().lower() == "linux":
|
|
283
|
-
Terminal().run(f"sudo mv {apps_dir.as_posix()}/* /usr/local/bin/").print_if_unsuccessful(desc="MOVING executable to /usr/local/bin", strict_err=True, strict_returncode=True)
|
|
284
|
-
else: raise NotImplementedError(f"I don't know this system {platform.system()}")
|
|
285
|
-
apps_dir.delete(sure=True)
|
|
286
|
-
return None
|
|
287
|
-
|
|
288
|
-
run_python_installer(installers.list[0]) # try out the first installer alone cause it will ask for password, so the rest will inherit the sudo session.
|
|
289
|
-
# summarize results
|
|
290
|
-
res: L[str] = installers.slice(start=1).apply(run_python_installer, jobs=jobs)
|
|
291
|
-
console = Console()
|
|
292
|
-
print("\n")
|
|
293
|
-
console.rule("Same version apps")
|
|
294
|
-
print(f"{res.filter(lambda x: 'same version' in x).print()}")
|
|
295
|
-
print("\n")
|
|
296
|
-
console.rule("Updated apps")
|
|
297
|
-
print(f"{res.filter(lambda x: 'updated from' in x).print()}")
|
|
298
|
-
print("\n")
|
|
299
|
-
console.rule("Failed apps")
|
|
300
|
-
print(f"{res.filter(lambda x: 'Failed at' in x).print()}")
|
|
301
|
-
|
|
302
|
-
print("\n")
|
|
303
|
-
print("Completed Installation".center(100, "-"))
|
|
304
|
-
print("\n" * 2)
|
|
305
|
-
|
|
306
|
-
# ------------------------ ARCHIVE ------------------------
|
|
307
|
-
|
|
308
|
-
|
|
309
201
|
def get_installed_cli_apps():
|
|
310
202
|
if platform.system() == "Windows": apps = P.home().joinpath("AppData/Local/Microsoft/WindowsApps").search("*.exe", not_in=["notepad"])
|
|
311
203
|
elif platform.system() == "Linux": apps = P(r"/usr/local/bin").search("*")
|
|
@@ -314,22 +206,22 @@ def get_installed_cli_apps():
|
|
|
314
206
|
return apps
|
|
315
207
|
|
|
316
208
|
|
|
317
|
-
def
|
|
318
|
-
if system == "Windows": import machineconfig.jobs.python_windows_installers as
|
|
319
|
-
else: import machineconfig.jobs.python_linux_installers as
|
|
320
|
-
import machineconfig.jobs.python_generic_installers as
|
|
321
|
-
path = P(
|
|
322
|
-
gens_path = P(
|
|
209
|
+
def get_installers(system: str, dev: bool) -> list[Installer]:
|
|
210
|
+
if system == "Windows": import machineconfig.jobs.python_windows_installers as os_specific_installer
|
|
211
|
+
else: import machineconfig.jobs.python_linux_installers as os_specific_installer
|
|
212
|
+
import machineconfig.jobs.python_generic_installers as generic_installer
|
|
213
|
+
path = P(os_specific_installer.__file__).parent
|
|
214
|
+
gens_path = P(generic_installer.__file__).parent
|
|
323
215
|
if dev:
|
|
324
216
|
path = path.joinpath("dev")
|
|
325
217
|
gens_path = gens_path.joinpath("dev")
|
|
326
218
|
res1: dict[str, Any] = Read.json(path=path.joinpath("config.json"))
|
|
327
219
|
res2: dict[str, Any] = Read.json(path=gens_path.joinpath("config.json"))
|
|
328
220
|
res2.update(res1)
|
|
329
|
-
return [Installer.from_dict(d) for
|
|
221
|
+
return [Installer.from_dict(d=vd, name=k) for k, vd in res2.items()]
|
|
330
222
|
|
|
331
223
|
|
|
332
|
-
def
|
|
224
|
+
def install_all(installers: L[Installer], safe: bool = False, jobs: int = 10, fresh: bool = False):
|
|
333
225
|
if fresh: INSTALL_VERSION_ROOT.delete(sure=True)
|
|
334
226
|
if safe:
|
|
335
227
|
from machineconfig.jobs.python.check_installations import APP_SUMMARY_PATH
|