machineconfig 3.97__py3-none-any.whl → 3.98__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/scripts/python/devops.py +12 -63
- machineconfig/scripts/python/devops_devapps_install.py +21 -82
- machineconfig/scripts/python/interactive.py +56 -136
- machineconfig/scripts/python/share_terminal.py +30 -11
- machineconfig/setup_linux/__init__.py +0 -0
- machineconfig/setup_linux/web_shortcuts/interactive.sh +2 -51
- machineconfig/utils/installer.py +5 -6
- machineconfig/utils/installer_utils/installer_abc.py +107 -2
- machineconfig/utils/installer_utils/installer_class.py +1 -41
- machineconfig/utils/options.py +3 -16
- {machineconfig-3.97.dist-info → machineconfig-3.98.dist-info}/METADATA +1 -1
- {machineconfig-3.97.dist-info → machineconfig-3.98.dist-info}/RECORD +15 -14
- {machineconfig-3.97.dist-info → machineconfig-3.98.dist-info}/entry_points.txt +1 -4
- {machineconfig-3.97.dist-info → machineconfig-3.98.dist-info}/WHEEL +0 -0
- {machineconfig-3.97.dist-info → machineconfig-3.98.dist-info}/top_level.txt +0 -0
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
"""devops with emojis"""
|
|
2
2
|
|
|
3
|
-
from machineconfig.
|
|
3
|
+
from machineconfig.scripts.python.share_terminal import main as share_terminal_main
|
|
4
|
+
import machineconfig.scripts.python.devops_devapps_install as installer_entry_point
|
|
4
5
|
|
|
5
6
|
from platform import system
|
|
6
|
-
from typing import Optional, Literal, TypeAlias
|
|
7
7
|
from rich.console import Console
|
|
8
8
|
from rich.panel import Panel
|
|
9
9
|
import typer
|
|
10
10
|
|
|
11
11
|
console = Console()
|
|
12
|
-
app = typer.Typer(help="🛠️ DevOps operations with emojis",
|
|
12
|
+
app = typer.Typer(help="🛠️ DevOps operations with emojis", no_args_is_help=True)
|
|
13
13
|
|
|
14
|
-
BOX_WIDTH = 150 # width for box drawing
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
COMMANDS: TypeAlias = Literal["🔄 UPDATE essential repos", "⚙️ DEVAPPS install", "🔗 SYMLINKS, SHELL PROFILE, FONT, TERMINAL SETTINGS.", "🆕 SYMLINKS new", "🔑 SSH add pub key to this machine", "🗝️ SSH add identity (private key) to this machine", "🔐 SSH use key pair to connect two machines", "📡 SSH setup", "🐧 SSH setup wsl", "💾 BACKUP", "📥 RETRIEVE", "⏰ SCHEDULER"]
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
BOX_WIDTH = 150 # width for box drawing
|
|
20
16
|
|
|
21
17
|
|
|
22
18
|
@app.command()
|
|
@@ -27,12 +23,9 @@ def update():
|
|
|
27
23
|
helper.main()
|
|
28
24
|
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
console.print(Panel("⚙️ Installing development applications...", width=BOX_WIDTH, border_style="blue"))
|
|
34
|
-
import machineconfig.scripts.python.devops_devapps_install as helper
|
|
35
|
-
helper.main(which=None)
|
|
26
|
+
app.command(name="install")(installer_entry_point.main)
|
|
27
|
+
app.command(name="share-terminal", help="📡 Share terminal via web browser")(share_terminal_main)
|
|
28
|
+
|
|
36
29
|
|
|
37
30
|
|
|
38
31
|
@app.command()
|
|
@@ -123,55 +116,11 @@ def scheduler():
|
|
|
123
116
|
# from machineconfig.scripts.python.scheduler import main as helper
|
|
124
117
|
# helper()
|
|
125
118
|
|
|
126
|
-
|
|
127
|
-
def
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
@app.command()
|
|
132
|
-
def interactive(which: Optional[COMMANDS] = None):
|
|
133
|
-
"""🛠️ Interactive menu mode (legacy)"""
|
|
134
|
-
console.print(Panel("🚀 Initializing DevOps operation...", width=BOX_WIDTH, border_style="blue"))
|
|
135
|
-
options = options_list
|
|
136
|
-
if which is None:
|
|
137
|
-
try:
|
|
138
|
-
choice_key = choose_from_options(msg="", options=options, header="🛠️ DEVOPS", default=options[0], multi=False, fzf=False)
|
|
139
|
-
except KeyboardInterrupt:
|
|
140
|
-
console.print(Panel("❌ Operation cancelled by user", title_align="left", border_style="red", width=BOX_WIDTH))
|
|
141
|
-
return
|
|
142
|
-
else:
|
|
143
|
-
choice_key = which
|
|
144
|
-
|
|
145
|
-
console.print(Panel(f"🔧 SELECTED OPERATION\n{choice_key}", title_align="left", border_style="green", width=BOX_WIDTH))
|
|
146
|
-
|
|
147
|
-
if choice_key == "🔄 UPDATE essential repos":
|
|
148
|
-
update()
|
|
149
|
-
elif choice_key == "⚙️ DEVAPPS install":
|
|
150
|
-
install()
|
|
151
|
-
elif choice_key == "🆕 SYMLINKS new":
|
|
152
|
-
symlinks_new()
|
|
153
|
-
elif choice_key == "🔗 SYMLINKS, SHELL PROFILE, FONT, TERMINAL SETTINGS.":
|
|
154
|
-
symlinks()
|
|
155
|
-
elif choice_key == "🔑 SSH add pub key to this machine":
|
|
156
|
-
ssh_add_key()
|
|
157
|
-
elif choice_key == "🔐 SSH use key pair to connect two machines":
|
|
158
|
-
ssh_connect()
|
|
159
|
-
elif choice_key == "🗝️ SSH add identity (private key) to this machine":
|
|
160
|
-
ssh_add_identity()
|
|
161
|
-
elif choice_key == "📡 SSH setup":
|
|
162
|
-
ssh_setup()
|
|
163
|
-
elif choice_key == "🐧 SSH setup wsl":
|
|
164
|
-
ssh_setup_wsl()
|
|
165
|
-
elif choice_key == "💾 BACKUP":
|
|
166
|
-
backup()
|
|
167
|
-
elif choice_key == "📥 RETRIEVE":
|
|
168
|
-
retrieve()
|
|
169
|
-
elif choice_key == "⏰ SCHEDULER":
|
|
170
|
-
scheduler()
|
|
171
|
-
else:
|
|
172
|
-
console.print(Panel("❌ ERROR: Invalid choice", title_align="left", border_style="red", width=BOX_WIDTH))
|
|
173
|
-
raise ValueError(f"Unimplemented choice: {choice_key}")
|
|
119
|
+
@app.command("ia")
|
|
120
|
+
def interactive():
|
|
121
|
+
from machineconfig.scripts.python.interactive import main
|
|
122
|
+
main()
|
|
174
123
|
|
|
175
124
|
|
|
176
125
|
if __name__ == "__main__":
|
|
177
|
-
|
|
126
|
+
pass
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
"""Devops Devapps Install"""
|
|
2
2
|
|
|
3
|
-
# import subprocess
|
|
4
3
|
import typer
|
|
5
4
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
6
|
-
from machineconfig.utils.source_of_truth import LIBRARY_ROOT
|
|
7
|
-
from machineconfig.utils.options import choose_from_options
|
|
8
|
-
from machineconfig.utils.installer import get_installers, install_all
|
|
9
|
-
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
10
5
|
from platform import system
|
|
11
|
-
from typing import
|
|
6
|
+
from typing import Optional, Literal, TypeAlias, cast, get_args, Annotated
|
|
12
7
|
|
|
13
|
-
WHICH_CAT: TypeAlias = Literal["essentials", "essentialsDev", "systymPackages", "precheckedPackages"]
|
|
8
|
+
WHICH_CAT: TypeAlias = Literal["essentials", "essentialsDev", "systymPackages", "precheckedPackages", "ia"]
|
|
14
9
|
|
|
15
10
|
|
|
16
11
|
def main_with_parser():
|
|
@@ -20,11 +15,12 @@ def main_with_parser():
|
|
|
20
15
|
app()
|
|
21
16
|
|
|
22
17
|
|
|
23
|
-
def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category or program to install, {list(get_args(WHICH_CAT))} or <program_name>")]) -> None:
|
|
24
|
-
if which
|
|
18
|
+
def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category or program to install, {list(get_args(WHICH_CAT))} or <program_name> or list of programs names separated by comma.")]) -> None:
|
|
19
|
+
if which in get_args(WHICH_CAT): # install by category
|
|
25
20
|
return get_programs_by_category(program_name=which) # type: ignore
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
22
|
+
from machineconfig.utils.installer import get_installers
|
|
23
|
+
if which != "ia" and which is not None: # install by name
|
|
28
24
|
total_messages: list[str] = []
|
|
29
25
|
for a_which in which.split(",") if type(which) == str else which:
|
|
30
26
|
all_installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL", "GITHUB_DEV", "CUSTOM_DEV"])
|
|
@@ -53,6 +49,12 @@ def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category
|
|
|
53
49
|
print(a_message)
|
|
54
50
|
return None
|
|
55
51
|
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def install_interactively():
|
|
55
|
+
from machineconfig.utils.options import choose_from_options
|
|
56
|
+
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
57
|
+
from machineconfig.utils.installer import get_installers
|
|
56
58
|
installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL", "GITHUB_DEV", "CUSTOM_DEV"])
|
|
57
59
|
# Check installed programs with progress indicator
|
|
58
60
|
with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
|
|
@@ -84,8 +86,7 @@ def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category
|
|
|
84
86
|
if a_program_name.startswith("📦 "):
|
|
85
87
|
category_name = a_program_name[2:] # Remove "📦 " prefix
|
|
86
88
|
if category_name in get_args(WHICH_CAT):
|
|
87
|
-
|
|
88
|
-
total_commands += "\n" + shell_commands
|
|
89
|
+
get_programs_by_category(program_name=cast(WHICH_CAT, category_name))
|
|
89
90
|
else:
|
|
90
91
|
# Handle individual installer options
|
|
91
92
|
installer_idx = installer_options.index(a_program_name)
|
|
@@ -112,15 +113,18 @@ def get_programs_by_category(program_name: WHICH_CAT):
|
|
|
112
113
|
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
113
114
|
┃ 📦 Installing Category: {program_name}
|
|
114
115
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
|
|
116
|
+
from machineconfig.utils.source_of_truth import LIBRARY_ROOT
|
|
117
|
+
from machineconfig.utils.installer import get_installers, install_all
|
|
118
|
+
from machineconfig.utils.installer_utils.installer_abc import parse_apps_installer_linux, parse_apps_installer_windows
|
|
119
|
+
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
120
|
+
from machineconfig.utils.options import choose_from_options
|
|
115
121
|
match program_name:
|
|
116
122
|
case "essentials":
|
|
117
123
|
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
|
|
118
124
|
install_all(installers=installers_)
|
|
119
|
-
program = ""
|
|
120
125
|
case "essentialsDev":
|
|
121
126
|
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_DEV", "CUSTOM_DEV", "GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
|
|
122
127
|
install_all(installers=installers_)
|
|
123
|
-
program = ""
|
|
124
128
|
case "systymPackages":
|
|
125
129
|
if system() == "Windows":
|
|
126
130
|
options_system = parse_apps_installer_windows(LIBRARY_ROOT.joinpath("setup_windows/apps.ps1").read_text(encoding="utf-8"))
|
|
@@ -141,79 +145,14 @@ def get_programs_by_category(program_name: WHICH_CAT):
|
|
|
141
145
|
if sub_program.startswith("#winget"):
|
|
142
146
|
sub_program = sub_program[1:]
|
|
143
147
|
program += "\n" + sub_program
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
# installers = get_installers(dev=True, system=system())
|
|
147
|
-
# options__: list[str] = [x.get_description() for x in tqdm(installers, desc="Checking installed programs")]
|
|
148
|
-
# program_names = choose_from_options(multi=True, msg="", options=sorted(options__) + ["all"], header="CHOOSE DEV APP")
|
|
149
|
-
# if "all" in program_names: program_names = options__
|
|
150
|
-
# program = ""
|
|
151
|
-
# print("Installing:")
|
|
152
|
-
# L(program_names).print()
|
|
153
|
-
# for name in program_names:
|
|
154
|
-
# try:
|
|
155
|
-
# idx = options__.index(name)
|
|
156
|
-
# except ValueError as ve:
|
|
157
|
-
# print(f"{name=}")
|
|
158
|
-
# print(f"{options__=}")
|
|
159
|
-
# raise ve
|
|
160
|
-
# print(f"Installing {name}")
|
|
161
|
-
# sub_program = installers[idx].install_robust(version=None) # finish the task
|
|
162
|
-
|
|
148
|
+
case "ia":
|
|
149
|
+
install_interactively()
|
|
163
150
|
case "precheckedPackages":
|
|
164
151
|
# from machineconfig.jobs.python.check_installations import precheckedPackages
|
|
165
152
|
# ci = precheckedPackages()
|
|
166
153
|
# ci.download_safe_apps(name="essentials")
|
|
167
154
|
# program = ""
|
|
168
155
|
raise NotImplementedError("precheckedPackages is not implemented yet.")
|
|
169
|
-
return program
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
def parse_apps_installer_linux(txt: str) -> dict[str, Any]:
|
|
173
|
-
txts = txt.split("""yes '' | sed 3q; echo "----------------------------- installing """)
|
|
174
|
-
res = {}
|
|
175
|
-
for chunk in txts[1:]:
|
|
176
|
-
try:
|
|
177
|
-
k = chunk.split("----")[0].rstrip().lstrip()
|
|
178
|
-
v = "\n".join(chunk.split("\n")[1:])
|
|
179
|
-
res[k] = v
|
|
180
|
-
except IndexError as e:
|
|
181
|
-
print(f"""
|
|
182
|
-
❌ Error parsing chunk:
|
|
183
|
-
{"-" * 50}
|
|
184
|
-
{chunk}
|
|
185
|
-
{"-" * 50}""")
|
|
186
|
-
raise e
|
|
187
|
-
return res
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
def parse_apps_installer_windows(txt: str) -> dict[str, Any]:
|
|
191
|
-
chunks: list[str] = []
|
|
192
|
-
for idx, item in enumerate(txt.split(sep="winget install")):
|
|
193
|
-
if idx == 0:
|
|
194
|
-
continue
|
|
195
|
-
if idx == 1:
|
|
196
|
-
chunks.append(item)
|
|
197
|
-
else:
|
|
198
|
-
chunks.append("winget install" + item)
|
|
199
|
-
# progs = L(txt.splitlines()).filter(lambda x: x.startswith("winget ") or x.startswith("#winget"))
|
|
200
|
-
res: dict[str, str] = {}
|
|
201
|
-
for a_chunk in chunks:
|
|
202
|
-
try:
|
|
203
|
-
name = a_chunk.split("--name ")[1]
|
|
204
|
-
if "--Id" not in name:
|
|
205
|
-
print(f"⚠️ Warning: {name} does not have an Id, skipping")
|
|
206
|
-
continue
|
|
207
|
-
name = name.split(" --Id ", maxsplit=1)[0].strip('"').strip('"')
|
|
208
|
-
res[name] = a_chunk
|
|
209
|
-
except IndexError as e:
|
|
210
|
-
print(f"""
|
|
211
|
-
❌ Error parsing chunk:
|
|
212
|
-
{"-" * 50}
|
|
213
|
-
{a_chunk}
|
|
214
|
-
{"-" * 50}""")
|
|
215
|
-
raise e
|
|
216
|
-
return res
|
|
217
156
|
|
|
218
157
|
|
|
219
158
|
if __name__ == "__main__":
|
|
@@ -39,36 +39,23 @@ def run_command(command: str, description: str) -> bool:
|
|
|
39
39
|
except subprocess.CalledProcessError as e:
|
|
40
40
|
console.print(f"❌ Error executing command: {e}", style="bold red")
|
|
41
41
|
return False
|
|
42
|
-
|
|
43
|
-
|
|
44
42
|
def display_header() -> None:
|
|
45
43
|
"""Display the script header."""
|
|
46
44
|
header_text = Text("MACHINE CONFIGURATION", style="bold magenta")
|
|
47
45
|
subtitle_text = Text("Interactive Installation Script", style="italic cyan")
|
|
48
|
-
console.print(Panel(
|
|
49
|
-
f"📦 {header_text}\n{subtitle_text}",
|
|
50
|
-
border_style="blue",
|
|
51
|
-
padding=(1, 2)
|
|
52
|
-
))
|
|
53
|
-
|
|
54
|
-
|
|
46
|
+
console.print(Panel(f"📦 {header_text}\n{subtitle_text}", border_style="blue", padding=(1, 2)))
|
|
55
47
|
def display_completion_message() -> None:
|
|
56
48
|
"""Display completion message."""
|
|
57
49
|
completion_text = Text("INSTALLATION COMPLETE", style="bold green")
|
|
58
50
|
subtitle_text = Text("System setup finished successfully", style="italic green")
|
|
59
|
-
console.print(Panel(
|
|
60
|
-
f"✨ {completion_text}\n{subtitle_text}\n\n🎉 Your system has been configured successfully!\n🔄 You may need to reboot to apply all changes.",
|
|
61
|
-
border_style="green",
|
|
62
|
-
padding=(1, 2)
|
|
63
|
-
))
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
console.print(Panel(f"✨ {completion_text}\n{subtitle_text}\n\n🎉 Your system has been configured successfully!\n🔄 You may need to reboot to apply all changes.", border_style="green", padding=(1, 2)))
|
|
66
52
|
def display_dotfiles_instructions() -> None:
|
|
67
53
|
"""Display instructions for dotfiles migration."""
|
|
68
54
|
header_text = Text("DOTFILES MIGRATION", style="bold yellow")
|
|
69
55
|
subtitle_text = Text("Configuration transfer options", style="italic yellow")
|
|
70
|
-
|
|
71
|
-
instructions = """
|
|
56
|
+
|
|
57
|
+
instructions = """
|
|
58
|
+
🖱️ [bold blue]Method 1: USING MOUSE WITHOUT KB OR BROWSER SHARE[/bold blue]
|
|
72
59
|
On original machine, run:
|
|
73
60
|
[dim]cd ~/dotfiles/creds/msc
|
|
74
61
|
easy-sharing . --password rew --username al[/dim]
|
|
@@ -84,172 +71,105 @@ def display_dotfiles_instructions() -> None:
|
|
|
84
71
|
[dim]cd ~
|
|
85
72
|
cloud_copy SHARE_URL . --config ss[/dim]
|
|
86
73
|
(requires symlinks to be created first)"""
|
|
87
|
-
|
|
88
|
-
console.print(Panel(
|
|
89
|
-
f"📂 {header_text}\n{subtitle_text}\n\n{instructions}",
|
|
90
|
-
border_style="yellow",
|
|
91
|
-
padding=(1, 2)
|
|
92
|
-
))
|
|
74
|
+
|
|
75
|
+
console.print(Panel(f"📂 {header_text}\n{subtitle_text}\n\n{instructions}", border_style="yellow", padding=(1, 2)))
|
|
93
76
|
|
|
94
77
|
|
|
95
78
|
def get_installation_choices() -> list[str]:
|
|
96
79
|
"""Get user choices for installation options."""
|
|
97
80
|
choices = [
|
|
98
|
-
Choice(value="install_apps",
|
|
99
|
-
Choice(value="upgrade_system",
|
|
100
|
-
Choice(value="install_uv_repos",
|
|
101
|
-
Choice(value="install_ssh_server",
|
|
102
|
-
Choice(value="create_symlinks",
|
|
103
|
-
Choice(value="install_cli_apps",
|
|
104
|
-
Choice(value="install_dev_tools",
|
|
81
|
+
Choice(value="install_apps", title="📥 Install Apps - Install base system applications", checked=False),
|
|
82
|
+
Choice(value="upgrade_system", title="🔄 Upgrade System Packages - Update all system packages", checked=False),
|
|
83
|
+
Choice(value="install_uv_repos", title="🐍 Install Repos - Set up Python environment and repositories permanently.", checked=False),
|
|
84
|
+
Choice(value="install_ssh_server", title="🔒 Install SSH Server - Set up remote access", checked=False),
|
|
85
|
+
Choice(value="create_symlinks", title="🔗 Create Symlinks - Set up configuration symlinks (finish dotfiles transfer first)", checked=False),
|
|
86
|
+
Choice(value="install_cli_apps", title="⚡ Install CLI Apps - Command-line tools installation", checked=False),
|
|
87
|
+
Choice(value="install_dev_tools", title="🛠️ Install Development Tools - rust, libssl-dev, ffmpeg, wezterm, brave, code", checked=False),
|
|
105
88
|
Choice(value="retrieve_repositories", title="📚 Retrieve Repositories - Clone repositories to ~/code", checked=False),
|
|
106
|
-
Choice(value="retrieve_data",
|
|
107
|
-
Choice(value="install_ascii_art",
|
|
89
|
+
Choice(value="retrieve_data", title="💾 Retrieve Data - Backup restoration", checked=False),
|
|
90
|
+
Choice(value="install_ascii_art", title="🎨 Install ASCII Art Libraries - Terminal visualization tools", checked=False),
|
|
108
91
|
]
|
|
109
|
-
|
|
110
|
-
selected = questionary.checkbox(
|
|
111
|
-
"Select the installation options you want to execute:",
|
|
112
|
-
choices=choices,
|
|
113
|
-
show_description=True,
|
|
114
|
-
).ask()
|
|
115
|
-
|
|
92
|
+
selected = questionary.checkbox("Select the installation options you want to execute:", choices=choices, show_description=True).ask()
|
|
116
93
|
return selected or []
|
|
117
94
|
|
|
118
95
|
|
|
119
96
|
def execute_installations(selected_options: list[str]) -> None:
|
|
120
97
|
"""Execute the selected installation options."""
|
|
121
98
|
# Always start with VE setup
|
|
122
|
-
console.print(Panel(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
))
|
|
126
|
-
run_command(
|
|
127
|
-
"curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/ve.sh | bash",
|
|
128
|
-
"Setting up base virtual environment"
|
|
129
|
-
)
|
|
130
|
-
|
|
99
|
+
console.print(Panel("🐍 [bold green]PYTHON ENVIRONMENT[/bold green]\n[italic]Setting up base virtual environment[/italic]", border_style="green"))
|
|
100
|
+
run_command("curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/ve.sh | bash", "Setting up base virtual environment")
|
|
101
|
+
|
|
131
102
|
if "install_apps" in selected_options:
|
|
132
|
-
console.print(Panel(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
)
|
|
136
|
-
run_command(
|
|
137
|
-
|
|
138
|
-
"Installing base system applications"
|
|
139
|
-
)
|
|
140
|
-
|
|
103
|
+
console.print(Panel("📦 [bold blue]APPLICATIONS[/bold blue]\n[italic]Installing base system applications[/italic]", border_style="blue"))
|
|
104
|
+
from machineconfig import setup_linux as module
|
|
105
|
+
from pathlib import Path
|
|
106
|
+
script = Path(module.__file__).parent / "apps.sh"
|
|
107
|
+
run_command(f"bash {script}", "Installing base system applications")
|
|
108
|
+
|
|
141
109
|
if "upgrade_system" in selected_options:
|
|
142
|
-
console.print(Panel(
|
|
143
|
-
"🔄 [bold magenta]SYSTEM UPDATE[/bold magenta]\n[italic]Package management[/italic]",
|
|
144
|
-
border_style="magenta"
|
|
145
|
-
))
|
|
110
|
+
console.print(Panel("🔄 [bold magenta]SYSTEM UPDATE[/bold magenta]\n[italic]Package management[/italic]", border_style="magenta"))
|
|
146
111
|
run_command("sudo nala upgrade -y", "Upgrading system packages")
|
|
147
|
-
|
|
112
|
+
|
|
148
113
|
if "install_uv_repos" in selected_options:
|
|
149
|
-
console.print(Panel(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
)
|
|
153
|
-
run_command(
|
|
154
|
-
|
|
155
|
-
"Setting up Python environment and repositories"
|
|
156
|
-
)
|
|
157
|
-
|
|
114
|
+
console.print(Panel("🐍 [bold green]PYTHON ENVIRONMENT[/bold green]\n[italic]Virtual environment setup[/italic]", border_style="green"))
|
|
115
|
+
from machineconfig import setup_linux as module
|
|
116
|
+
from pathlib import Path
|
|
117
|
+
script = Path(module.__file__).parent / "repos.sh"
|
|
118
|
+
run_command(f"bash {script}", "Setting up Python environment and repositories")
|
|
119
|
+
|
|
158
120
|
if "install_ssh_server" in selected_options:
|
|
159
|
-
console.print(Panel(
|
|
160
|
-
"🔒 [bold red]SSH SERVER[/bold red]\n[italic]Remote access setup[/italic]",
|
|
161
|
-
border_style="red"
|
|
162
|
-
))
|
|
121
|
+
console.print(Panel("🔒 [bold red]SSH SERVER[/bold red]\n[italic]Remote access setup[/italic]", border_style="red"))
|
|
163
122
|
run_command("sudo nala install openssh-server -y", "Installing SSH server")
|
|
164
|
-
|
|
165
|
-
# Always display dotfiles instructions if symlinks are selected
|
|
123
|
+
|
|
166
124
|
if "create_symlinks" in selected_options:
|
|
167
125
|
display_dotfiles_instructions()
|
|
168
|
-
|
|
169
|
-
dotfiles_ready = questionary.confirm(
|
|
170
|
-
"📂 Have you finished copying dotfiles?",
|
|
171
|
-
default=True
|
|
172
|
-
).ask()
|
|
173
|
-
|
|
126
|
+
dotfiles_ready = questionary.confirm("📂 Have you finished copying dotfiles?", default=True).ask()
|
|
174
127
|
if dotfiles_ready:
|
|
175
|
-
console.print(Panel(
|
|
176
|
-
|
|
177
|
-
border_style="cyan"
|
|
178
|
-
))
|
|
179
|
-
run_command(
|
|
180
|
-
"uv run --python 3.13 --with machineconfig python -m fire machineconfig.profile.create main_symlinks --choice=all",
|
|
181
|
-
"Creating symlinks"
|
|
182
|
-
)
|
|
128
|
+
console.print(Panel("🔗 [bold cyan]SYMLINK CREATION[/bold cyan]\n[italic]Configuration setup[/italic]", border_style="cyan"))
|
|
129
|
+
run_command("uv run --python 3.13 --with machineconfig python -m fire machineconfig.profile.create main_symlinks --choice=all", "Creating symlinks")
|
|
183
130
|
run_command("sudo chmod 600 $HOME/.ssh/*", "Setting SSH key permissions")
|
|
184
131
|
run_command("sudo chmod 700 $HOME/.ssh", "Setting SSH directory permissions")
|
|
185
132
|
else:
|
|
186
133
|
console.print("⏭️ Skipping symlink creation - finish dotfiles transfer first", style="yellow")
|
|
187
|
-
|
|
134
|
+
|
|
188
135
|
if "install_cli_apps" in selected_options:
|
|
189
|
-
console.print(Panel(
|
|
190
|
-
|
|
191
|
-
border_style="bright_yellow"
|
|
192
|
-
))
|
|
193
|
-
run_command(
|
|
194
|
-
"uv run --python 3.13 --with machineconfig python -m fire machineconfig.scripts.python.devops_devapps_install main --which=essentials",
|
|
195
|
-
"Installing CLI applications"
|
|
196
|
-
)
|
|
136
|
+
console.print(Panel("⚡ [bold bright_yellow]CLI APPLICATIONS[/bold bright_yellow]\n[italic]Command-line tools installation[/italic]", border_style="bright_yellow"))
|
|
137
|
+
run_command("uv run --python 3.13 --with machineconfig python -m fire machineconfig.scripts.python.devops_devapps_install main --which=essentials", "Installing CLI applications")
|
|
197
138
|
run_command(". $HOME/.bashrc", "Reloading bash configuration")
|
|
198
|
-
|
|
139
|
+
|
|
199
140
|
if "install_dev_tools" in selected_options:
|
|
200
|
-
console.print(Panel(
|
|
201
|
-
|
|
202
|
-
border_style="bright_blue"
|
|
203
|
-
))
|
|
204
|
-
run_command(
|
|
205
|
-
"(curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh) || true",
|
|
206
|
-
"Installing Rust toolchain"
|
|
207
|
-
)
|
|
141
|
+
console.print(Panel("🛠️ [bold bright_blue]DEVELOPMENT TOOLS[/bold bright_blue]\n[italic]Software development packages[/italic]", border_style="bright_blue"))
|
|
142
|
+
run_command("(curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh) || true", "Installing Rust toolchain")
|
|
208
143
|
run_command("sudo nala install libssl-dev -y", "Installing libssl-dev")
|
|
209
144
|
run_command("sudo nala install ffmpeg -y", "Installing ffmpeg")
|
|
210
|
-
run_command(
|
|
211
|
-
|
|
212
|
-
"Installing development applications"
|
|
213
|
-
)
|
|
214
|
-
|
|
145
|
+
run_command("uv run --python 3.13 --with machineconfig python -m fire machineconfig.scripts.python.devops_devapps_install main --which=wezterm,brave,code", "Installing development applications")
|
|
146
|
+
|
|
215
147
|
if "retrieve_repositories" in selected_options:
|
|
216
|
-
console.print(Panel(
|
|
217
|
-
"📚 [bold bright_magenta]REPOSITORIES[/bold bright_magenta]\n[italic]Project code retrieval[/italic]",
|
|
218
|
-
border_style="bright_magenta"
|
|
219
|
-
))
|
|
148
|
+
console.print(Panel("📚 [bold bright_magenta]REPOSITORIES[/bold bright_magenta]\n[italic]Project code retrieval[/italic]", border_style="bright_magenta"))
|
|
220
149
|
run_command("repos ~/code --clone --cloud odg1", "Cloning repositories")
|
|
221
|
-
|
|
150
|
+
|
|
222
151
|
if "retrieve_data" in selected_options:
|
|
223
|
-
console.print(Panel(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
))
|
|
227
|
-
run_command(
|
|
228
|
-
"uv run --python 3.13 --with machineconfig python -m fire machineconfig.scripts.python.devops_backup_retrieve main --direction=RETRIEVE",
|
|
229
|
-
"Retrieving backup data"
|
|
230
|
-
)
|
|
231
|
-
|
|
152
|
+
console.print(Panel("💾 [bold bright_cyan]DATA RETRIEVAL[/bold bright_cyan]\n[italic]Backup restoration[/italic]", border_style="bright_cyan"))
|
|
153
|
+
run_command("uv run --python 3.13 --with machineconfig python -m fire machineconfig.scripts.python.devops_backup_retrieve main --direction=RETRIEVE", "Retrieving backup data")
|
|
154
|
+
|
|
232
155
|
if "install_ascii_art" in selected_options:
|
|
233
|
-
console.print(Panel(
|
|
234
|
-
"🎨 [bold bright_green]ASCII ART[/bold bright_green]\n[italic]Terminal visualization tools[/italic]",
|
|
235
|
-
border_style="bright_green"
|
|
236
|
-
))
|
|
156
|
+
console.print(Panel("🎨 [bold bright_green]ASCII ART[/bold bright_green]\n[italic]Terminal visualization tools[/italic]", border_style="bright_green"))
|
|
237
157
|
run_command("curl bit.ly/cfgasciiartlinux -L | sudo bash", "Installing ASCII art libraries")
|
|
238
158
|
|
|
239
159
|
|
|
240
160
|
def main() -> None:
|
|
241
161
|
"""Main function to run the interactive installation."""
|
|
242
162
|
display_header()
|
|
243
|
-
selected_options = get_installation_choices()
|
|
163
|
+
selected_options = get_installation_choices()
|
|
244
164
|
if not selected_options:
|
|
245
165
|
console.print("❌ No options selected. Exiting...", style="bold red")
|
|
246
166
|
sys.exit(0)
|
|
247
167
|
console.print(f"\n✅ Selected options: {', '.join(selected_options)}", style="bold green")
|
|
248
|
-
proceed = questionary.confirm("🚀 Proceed with installation?", default=True).ask()
|
|
168
|
+
proceed = questionary.confirm("🚀 Proceed with installation?", default=True).ask()
|
|
249
169
|
if not proceed:
|
|
250
170
|
console.print("❌ Installation cancelled.", style="bold red")
|
|
251
171
|
sys.exit(0)
|
|
252
|
-
execute_installations(selected_options)
|
|
172
|
+
execute_installations(selected_options)
|
|
253
173
|
display_completion_message()
|
|
254
174
|
|
|
255
175
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Optional
|
|
4
|
+
from typing import Optional, Annotated
|
|
5
5
|
import typer
|
|
6
6
|
from rich.console import Console
|
|
7
7
|
from rich.panel import Panel
|
|
@@ -43,12 +43,33 @@ def display_terminal_url(local_ip_v4: str, port: int) -> None:
|
|
|
43
43
|
)
|
|
44
44
|
|
|
45
45
|
# Print with extra spacing and attention-grabbing elements
|
|
46
|
-
console.print("\n" + "🔥" * 60 + "\n", style="bright_red bold")
|
|
46
|
+
# console.print("\n" + "🔥" * 60 + "\n", style="bright_red bold")
|
|
47
47
|
console.print(panel)
|
|
48
|
-
console.print("🔥" * 60 + "\n", style="bright_red bold")
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def
|
|
48
|
+
# console.print("🔥" * 60 + "\n", style="bright_red bold")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def install_ttyd():
|
|
52
|
+
# uv run --python 3.13 --with machineconfig devops install ttyd
|
|
53
|
+
from machineconfig.utils.installer_utils.installer_abc import check_tool_exists
|
|
54
|
+
exists = check_tool_exists("ttyd")
|
|
55
|
+
if exists:
|
|
56
|
+
print("✅ ttyd is already installed.")
|
|
57
|
+
return
|
|
58
|
+
print("⏳ ttyd not found. Installing...")
|
|
59
|
+
from machineconfig.scripts.python.devops_devapps_install import main
|
|
60
|
+
main(which="ttyd")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def main(
|
|
65
|
+
port: Annotated[Optional[int], typer.Option("--port", "-p", help="Port to run the terminal server on (default: 7681)")] = None,
|
|
66
|
+
username: Annotated[Optional[str], typer.Option("--username", "-u", help="Username for terminal access (default: current user)")] = None,
|
|
67
|
+
password: Annotated[Optional[str], typer.Option("--password", "-w", help="Password for terminal access (default: from ~/dotfiles/creds/passwords/quick_password)")] = None
|
|
68
|
+
) -> None:
|
|
69
|
+
install_ttyd()
|
|
70
|
+
if username is None:
|
|
71
|
+
import getpass
|
|
72
|
+
username = getpass.getuser()
|
|
52
73
|
if password is None:
|
|
53
74
|
pwd_path = Path.home().joinpath("dotfiles/creds/passwords/quick_password")
|
|
54
75
|
if pwd_path.exists():
|
|
@@ -67,11 +88,9 @@ def main(port: Optional[int]=None, password: Optional[str]=None) -> None:
|
|
|
67
88
|
|
|
68
89
|
# Display the flashy terminal announcement
|
|
69
90
|
display_terminal_url(local_ip_v4, port)
|
|
70
|
-
|
|
71
|
-
code = f"""
|
|
72
|
-
|
|
73
|
-
uv run --python 3.13 --with machineconfig install -ttyd
|
|
74
|
-
ttyd --writable -t enableSixel=true --port {port} --credential "$USER:{password}" -t 'theme={"background": "black"}' bash
|
|
91
|
+
|
|
92
|
+
code = f"""#!/bin/bash
|
|
93
|
+
ttyd --writable -t enableSixel=true --port {port} --credential "{username}:{password}" -t 'theme={{"background": "black"}}' bash
|
|
75
94
|
"""
|
|
76
95
|
import subprocess
|
|
77
96
|
subprocess.run(code, shell=True, check=True)
|
|
File without changes
|
|
@@ -2,57 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
echo """
|
|
4
4
|
=======================================================================
|
|
5
|
-
📦 MACHINE CONFIGURATION | Interactive Installation Script
|
|
5
|
+
📦 MACHINE CONFIGURATION | Interactive Installation Script. Installing uv then getting started.
|
|
6
6
|
======================================================================="""
|
|
7
7
|
|
|
8
8
|
curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/ve.sh | bash
|
|
9
|
-
$HOME/.local/bin/uv run --python 3.13 --with machineconfig ia
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
echo """#=======================================================================
|
|
15
|
-
📂 DOTFILES MIGRATION | Configuration transfer options
|
|
16
|
-
#=======================================================================
|
|
17
|
-
|
|
18
|
-
🖱️ Method 1: USING MOUSE WITHOUT KB OR BROWSER SHARE
|
|
19
|
-
On original machine, run:
|
|
20
|
-
cd ~/dotfiles/creds/msc
|
|
21
|
-
easy-sharing . --password rew --username al
|
|
22
|
-
Then open brave on new machine to get MouseWithoutBorders password
|
|
23
|
-
|
|
24
|
-
🔐 Method 2: USING SSH
|
|
25
|
-
FROM REMOTE, RUN:
|
|
26
|
-
fptx ~/dotfiles $USER@$(hostname):^ -z
|
|
27
|
-
# OR, using IP address if router has not yet found the hostname:
|
|
28
|
-
fptx ~/dotfiles $USER@$(hostname -I | awk '{print $1}'):^ -z
|
|
29
|
-
|
|
30
|
-
☁️ Method 3: USING INTERNET SECURE SHARE
|
|
31
|
-
cd ~
|
|
32
|
-
cloud_copy SHARE_URL . --config ss
|
|
33
|
-
(requires symlinks to be created first)
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
echo """#=======================================================================
|
|
37
|
-
📂 DOTFILES STATUS | Configuration files check
|
|
38
|
-
#=======================================================================
|
|
39
|
-
"""
|
|
40
|
-
read -p "📂 Have you finished copying dotfiles? [y]/n? " choice
|
|
41
|
-
|
|
42
|
-
echo """#=======================================================================
|
|
43
|
-
🔗 SYMLINK CREATION | Configuration setup
|
|
44
|
-
#=======================================================================
|
|
45
|
-
"""
|
|
46
|
-
read -p "🔗 Create Symlinks (finish dotfiles transfer first) [y]/n? " choice
|
|
47
|
-
choice=${choice:-y}
|
|
48
|
-
if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
|
|
49
|
-
echo """ 🔧 Creating symlinks and setting permissions...
|
|
50
|
-
"""
|
|
51
|
-
uv run --python 3.13 --with machineconfig python -m fire machineconfig.profile.create main_symlinks --choice=all
|
|
52
|
-
sudo chmod 600 $HOME/.ssh/*
|
|
53
|
-
sudo chmod 700 $HOME/.ssh
|
|
54
|
-
else
|
|
55
|
-
echo """ ⏭️ Skipping symlink creation
|
|
56
|
-
"""
|
|
57
|
-
fi
|
|
58
|
-
|
|
9
|
+
$HOME/.local/bin/uv run --python 3.13 --with machineconfig devops ia
|
machineconfig/utils/installer.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""package manager"""
|
|
2
2
|
|
|
3
|
-
from machineconfig.utils.installer_utils.installer_abc import
|
|
3
|
+
from machineconfig.utils.installer_utils.installer_abc import check_if_installed_already
|
|
4
4
|
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
5
5
|
from machineconfig.utils.schemas.installer.installer_types import APP_INSTALLER_CATEGORY, InstallerData, InstallerDataFiles, get_normalized_arch, get_os_name, OPERATING_SYSTEMS, CPU_ARCHITECTURES
|
|
6
6
|
from rich.console import Console
|
|
7
|
-
from rich.panel import Panel
|
|
7
|
+
from rich.panel import Panel
|
|
8
8
|
|
|
9
9
|
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
10
|
-
from machineconfig.utils.source_of_truth import INSTALL_VERSION_ROOT
|
|
10
|
+
from machineconfig.utils.source_of_truth import INSTALL_VERSION_ROOT, LINUX_INSTALL_PATH
|
|
11
11
|
from machineconfig.utils.io import read_json
|
|
12
12
|
|
|
13
13
|
from typing import Any
|
|
@@ -38,7 +38,7 @@ def check_latest():
|
|
|
38
38
|
repo_url = inst.installer_data.get("repoURL", "")
|
|
39
39
|
print(f"🔎 Checking {exe_name}...")
|
|
40
40
|
_release_url, version_to_be_installed = inst.get_github_release(repo_url=repo_url, version=None)
|
|
41
|
-
verdict, current_ver, new_ver =
|
|
41
|
+
verdict, current_ver, new_ver = check_if_installed_already(exe_name=exe_name, version=version_to_be_installed, use_cache=False)
|
|
42
42
|
return exe_name, verdict, current_ver, new_ver
|
|
43
43
|
|
|
44
44
|
print("\n⏳ Processing installers...\n")
|
|
@@ -188,5 +188,4 @@ def install_all(installers: list[Installer], safe: bool = False, jobs: int = 10,
|
|
|
188
188
|
print("\n" * 2)
|
|
189
189
|
|
|
190
190
|
|
|
191
|
-
|
|
192
|
-
pass
|
|
191
|
+
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
|
|
1
2
|
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
2
|
-
from machineconfig.utils.source_of_truth import WINDOWS_INSTALL_PATH, LINUX_INSTALL_PATH
|
|
3
|
-
|
|
3
|
+
from machineconfig.utils.source_of_truth import WINDOWS_INSTALL_PATH, LINUX_INSTALL_PATH, INSTALL_VERSION_ROOT
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Optional
|
|
4
7
|
import subprocess
|
|
8
|
+
import platform
|
|
5
9
|
|
|
6
10
|
|
|
7
11
|
def find_move_delete_windows(downloaded_file_path: PathExtended, exe_name: Optional[str] = None, delete: bool = True, rename_to: Optional[str] = None):
|
|
@@ -106,3 +110,104 @@ def find_move_delete_linux(downloaded: PathExtended, tool_name: str, delete: Opt
|
|
|
106
110
|
exe_new_location = PathExtended(LINUX_INSTALL_PATH).joinpath(exe.name)
|
|
107
111
|
print(f"✅ Executable installed at: {exe_new_location}\n{'=' * 80}")
|
|
108
112
|
return exe_new_location
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def check_tool_exists(tool_name: str) -> bool:
|
|
116
|
+
if platform.system() == "Windows":
|
|
117
|
+
tool_name = tool_name.replace(".exe", "") + ".exe"
|
|
118
|
+
res1 = any([Path(WINDOWS_INSTALL_PATH).joinpath(tool_name).is_file(), Path.home().joinpath("AppData/Roaming/npm").joinpath(tool_name).is_file()])
|
|
119
|
+
tool_name = tool_name.replace(".exe", "") + ".exe"
|
|
120
|
+
res2 = any([Path(WINDOWS_INSTALL_PATH).joinpath(tool_name).is_file(), Path.home().joinpath("AppData/Roaming/npm").joinpath(tool_name).is_file()])
|
|
121
|
+
return res1 or res2
|
|
122
|
+
elif platform.system() in ["Linux", "Darwin"]:
|
|
123
|
+
root_path = Path(LINUX_INSTALL_PATH)
|
|
124
|
+
return any([Path("/usr/local/bin").joinpath(tool_name).is_file(), Path("/usr/bin").joinpath(tool_name).is_file(), root_path.joinpath(tool_name).is_file()])
|
|
125
|
+
else:
|
|
126
|
+
raise NotImplementedError(f"platform {platform.system()} not implemented")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def check_if_installed_already(exe_name: str, version: Optional[str], use_cache: bool) -> tuple[str, str, str]:
|
|
130
|
+
print(f"\n{'=' * 80}\n🔍 CHECKING INSTALLATION STATUS: {exe_name} 🔍\n{'=' * 80}")
|
|
131
|
+
INSTALL_VERSION_ROOT.joinpath(exe_name).parent.mkdir(parents=True, exist_ok=True)
|
|
132
|
+
tmp_path = INSTALL_VERSION_ROOT.joinpath(exe_name)
|
|
133
|
+
|
|
134
|
+
if use_cache:
|
|
135
|
+
print("🗂️ Using cached version information...")
|
|
136
|
+
if tmp_path.exists():
|
|
137
|
+
existing_version = tmp_path.read_text(encoding="utf-8").rstrip()
|
|
138
|
+
print(f"📄 Found cached version: {existing_version}")
|
|
139
|
+
else:
|
|
140
|
+
existing_version = None
|
|
141
|
+
print("ℹ️ No cached version information found")
|
|
142
|
+
else:
|
|
143
|
+
print("🔍 Checking installed version directly...")
|
|
144
|
+
result = subprocess.run([exe_name, "--version"], check=False, capture_output=True, text=True)
|
|
145
|
+
if result.stdout.strip() == "":
|
|
146
|
+
existing_version = None
|
|
147
|
+
print("ℹ️ Could not detect installed version")
|
|
148
|
+
else:
|
|
149
|
+
existing_version = result.stdout.strip()
|
|
150
|
+
print(f"📄 Detected installed version: {existing_version}")
|
|
151
|
+
|
|
152
|
+
if existing_version is not None and version is not None:
|
|
153
|
+
if existing_version == version:
|
|
154
|
+
print(f"✅ {exe_name} is up to date (version {version})")
|
|
155
|
+
print(f"📂 Version information stored at: {INSTALL_VERSION_ROOT}")
|
|
156
|
+
return ("✅ Up to date", version.strip(), version.strip())
|
|
157
|
+
else:
|
|
158
|
+
print(f"🔄 {exe_name} needs update: {existing_version.rstrip()} → {version}")
|
|
159
|
+
tmp_path.write_text(version, encoding="utf-8")
|
|
160
|
+
return ("❌ Outdated", existing_version.strip(), version.strip())
|
|
161
|
+
else:
|
|
162
|
+
print(f"📦 {exe_name} is not installed. Will install version: {version}")
|
|
163
|
+
# tmp_path.write_text(version, encoding="utf-8")
|
|
164
|
+
|
|
165
|
+
print(f"{'=' * 80}")
|
|
166
|
+
return ("⚠️ NotInstalled", "None", version or "unknown")
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def parse_apps_installer_linux(txt: str) -> dict[str, Any]:
|
|
170
|
+
txts = txt.split("""yes '' | sed 3q; echo "----------------------------- installing """)
|
|
171
|
+
res = {}
|
|
172
|
+
for chunk in txts[1:]:
|
|
173
|
+
try:
|
|
174
|
+
k = chunk.split("----")[0].rstrip().lstrip()
|
|
175
|
+
v = "\n".join(chunk.split("\n")[1:])
|
|
176
|
+
res[k] = v
|
|
177
|
+
except IndexError as e:
|
|
178
|
+
print(f"""
|
|
179
|
+
❌ Error parsing chunk:
|
|
180
|
+
{"-" * 50}
|
|
181
|
+
{chunk}
|
|
182
|
+
{"-" * 50}""")
|
|
183
|
+
raise e
|
|
184
|
+
return res
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def parse_apps_installer_windows(txt: str) -> dict[str, Any]:
|
|
188
|
+
chunks: list[str] = []
|
|
189
|
+
for idx, item in enumerate(txt.split(sep="winget install")):
|
|
190
|
+
if idx == 0:
|
|
191
|
+
continue
|
|
192
|
+
if idx == 1:
|
|
193
|
+
chunks.append(item)
|
|
194
|
+
else:
|
|
195
|
+
chunks.append("winget install" + item)
|
|
196
|
+
# progs = L(txt.splitlines()).filter(lambda x: x.startswith("winget ") or x.startswith("#winget"))
|
|
197
|
+
res: dict[str, str] = {}
|
|
198
|
+
for a_chunk in chunks:
|
|
199
|
+
try:
|
|
200
|
+
name = a_chunk.split("--name ")[1]
|
|
201
|
+
if "--Id" not in name:
|
|
202
|
+
print(f"⚠️ Warning: {name} does not have an Id, skipping")
|
|
203
|
+
continue
|
|
204
|
+
name = name.split(" --Id ", maxsplit=1)[0].strip('"').strip('"')
|
|
205
|
+
res[name] = a_chunk
|
|
206
|
+
except IndexError as e:
|
|
207
|
+
print(f"""
|
|
208
|
+
❌ Error parsing chunk:
|
|
209
|
+
{"-" * 50}
|
|
210
|
+
{a_chunk}
|
|
211
|
+
{"-" * 50}""")
|
|
212
|
+
raise e
|
|
213
|
+
return res
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
2
2
|
from machineconfig.utils.installer_utils.installer_abc import find_move_delete_linux, find_move_delete_windows
|
|
3
3
|
from machineconfig.utils.source_of_truth import INSTALL_TMP_DIR, INSTALL_VERSION_ROOT, LIBRARY_ROOT
|
|
4
|
-
from machineconfig.utils.
|
|
4
|
+
from machineconfig.utils.installer_utils.installer_abc import check_tool_exists
|
|
5
5
|
from machineconfig.utils.io import read_json
|
|
6
6
|
from machineconfig.utils.schemas.installer.installer_types import InstallerData, InstallerDataFiles, get_os_name, get_normalized_arch
|
|
7
7
|
|
|
@@ -356,43 +356,3 @@ class Installer:
|
|
|
356
356
|
return None, None
|
|
357
357
|
browser_download_url = f"{repo_url}/releases/download/{actual_version}/{filename}"
|
|
358
358
|
return browser_download_url, actual_version
|
|
359
|
-
|
|
360
|
-
@staticmethod
|
|
361
|
-
def check_if_installed_already(exe_name: str, version: Optional[str], use_cache: bool) -> tuple[str, str, str]:
|
|
362
|
-
print(f"\n{'=' * 80}\n🔍 CHECKING INSTALLATION STATUS: {exe_name} 🔍\n{'=' * 80}")
|
|
363
|
-
INSTALL_VERSION_ROOT.joinpath(exe_name).parent.mkdir(parents=True, exist_ok=True)
|
|
364
|
-
tmp_path = INSTALL_VERSION_ROOT.joinpath(exe_name)
|
|
365
|
-
|
|
366
|
-
if use_cache:
|
|
367
|
-
print("🗂️ Using cached version information...")
|
|
368
|
-
if tmp_path.exists():
|
|
369
|
-
existing_version = tmp_path.read_text(encoding="utf-8").rstrip()
|
|
370
|
-
print(f"📄 Found cached version: {existing_version}")
|
|
371
|
-
else:
|
|
372
|
-
existing_version = None
|
|
373
|
-
print("ℹ️ No cached version information found")
|
|
374
|
-
else:
|
|
375
|
-
print("🔍 Checking installed version directly...")
|
|
376
|
-
result = subprocess.run([exe_name, "--version"], check=False, capture_output=True, text=True)
|
|
377
|
-
if result.stdout.strip() == "":
|
|
378
|
-
existing_version = None
|
|
379
|
-
print("ℹ️ Could not detect installed version")
|
|
380
|
-
else:
|
|
381
|
-
existing_version = result.stdout.strip()
|
|
382
|
-
print(f"📄 Detected installed version: {existing_version}")
|
|
383
|
-
|
|
384
|
-
if existing_version is not None and version is not None:
|
|
385
|
-
if existing_version == version:
|
|
386
|
-
print(f"✅ {exe_name} is up to date (version {version})")
|
|
387
|
-
print(f"📂 Version information stored at: {INSTALL_VERSION_ROOT}")
|
|
388
|
-
return ("✅ Up to date", version.strip(), version.strip())
|
|
389
|
-
else:
|
|
390
|
-
print(f"🔄 {exe_name} needs update: {existing_version.rstrip()} → {version}")
|
|
391
|
-
tmp_path.write_text(version, encoding="utf-8")
|
|
392
|
-
return ("❌ Outdated", existing_version.strip(), version.strip())
|
|
393
|
-
else:
|
|
394
|
-
print(f"📦 {exe_name} is not installed. Will install version: {version}")
|
|
395
|
-
# tmp_path.write_text(version, encoding="utf-8")
|
|
396
|
-
|
|
397
|
-
print(f"{'=' * 80}")
|
|
398
|
-
return ("⚠️ NotInstalled", "None", version or "unknown")
|
machineconfig/utils/options.py
CHANGED
|
@@ -1,25 +1,12 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
+
from machineconfig.utils.installer_utils.installer_abc import check_tool_exists
|
|
2
3
|
from rich.text import Text
|
|
3
4
|
from rich.panel import Panel
|
|
4
5
|
from rich.console import Console
|
|
5
|
-
import platform
|
|
6
6
|
import subprocess
|
|
7
7
|
from typing import Optional, Union, Iterable, overload, Literal
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def check_tool_exists(tool_name: str) -> bool:
|
|
12
|
-
if platform.system() == "Windows":
|
|
13
|
-
tool_name = tool_name.replace(".exe", "") + ".exe"
|
|
14
|
-
res1 = any([Path(WINDOWS_INSTALL_PATH).joinpath(tool_name).is_file(), Path.home().joinpath("AppData/Roaming/npm").joinpath(tool_name).is_file()])
|
|
15
|
-
tool_name = tool_name.replace(".exe", "") + ".exe"
|
|
16
|
-
res2 = any([Path(WINDOWS_INSTALL_PATH).joinpath(tool_name).is_file(), Path.home().joinpath("AppData/Roaming/npm").joinpath(tool_name).is_file()])
|
|
17
|
-
return res1 or res2
|
|
18
|
-
elif platform.system() in ["Linux", "Darwin"]:
|
|
19
|
-
root_path = Path(LINUX_INSTALL_PATH)
|
|
20
|
-
return any([Path("/usr/local/bin").joinpath(tool_name).is_file(), Path("/usr/bin").joinpath(tool_name).is_file(), root_path.joinpath(tool_name).is_file()])
|
|
21
|
-
else:
|
|
22
|
-
raise NotImplementedError(f"platform {platform.system()} not implemented")
|
|
8
|
+
|
|
9
|
+
|
|
23
10
|
# _ = cmd
|
|
24
11
|
# cmd = "where.exe"
|
|
25
12
|
# cmd = "which"
|
|
@@ -144,11 +144,11 @@ machineconfig/scripts/python/cloud_mount.py,sha256=RFMzRUep2D5HtVXANIi-pab3EkI-W
|
|
|
144
144
|
machineconfig/scripts/python/cloud_repo_sync.py,sha256=GBhdUu9BJwhLYmhxxtvqJGLy7xKdQcnH9kkL4jcbzEE,9502
|
|
145
145
|
machineconfig/scripts/python/cloud_sync.py,sha256=RWGpAfJ9fnN18yNBSgN44dzA38Hmd4879JL5r2pcyrM,3514
|
|
146
146
|
machineconfig/scripts/python/croshell.py,sha256=shv0FmFfD2Br0EVE-zvpt4i5Tl8kliLlIvxkx0umGiA,8954
|
|
147
|
-
machineconfig/scripts/python/devops.py,sha256=
|
|
147
|
+
machineconfig/scripts/python/devops.py,sha256=qjBXv6x-7mfJRPyLfGNzcadGBpoHoxWaZFTJCqx0DS4,4554
|
|
148
148
|
machineconfig/scripts/python/devops_add_identity.py,sha256=JfN3ZrYMCgmt4ks_VCfnV9BIIHAsOYO3E0W0wZ15FR8,3791
|
|
149
149
|
machineconfig/scripts/python/devops_add_ssh_key.py,sha256=KaoX83KltBsmutfKhSfZjd7nP_R1hJ2OLAWRhbswO7o,6889
|
|
150
150
|
machineconfig/scripts/python/devops_backup_retrieve.py,sha256=jZe5Vki7E2GCMG8hvqUZeOONFC4cNzISoGzq_dMG4GA,5601
|
|
151
|
-
machineconfig/scripts/python/devops_devapps_install.py,sha256=
|
|
151
|
+
machineconfig/scripts/python/devops_devapps_install.py,sha256=Oe8u6_EurEltEtJagcuapz-G3DyZdRyWqQ8kSEp-zHQ,8911
|
|
152
152
|
machineconfig/scripts/python/devops_update_repos.py,sha256=c5qBc9cuTGDEqDHufkjDT4d_vvJsswv3tlqk9MAulYk,8063
|
|
153
153
|
machineconfig/scripts/python/dotfile.py,sha256=SRcX-9Ak1jRvF-killBTTm2IWcsNxfiLucH6ZsytAFA,2202
|
|
154
154
|
machineconfig/scripts/python/fire_agents.py,sha256=IpglbN30zJ1jIBzHNCR2LmPULoIdFaj2M0JBsEfZEZg,9216
|
|
@@ -162,7 +162,7 @@ machineconfig/scripts/python/fire_jobs_streamlit_helper.py,sha256=47DEQpj8HBSa-_
|
|
|
162
162
|
machineconfig/scripts/python/ftpx.py,sha256=l_gdJS0QB2wVZErubtZvm4HJD9HZAJxSP68sbY73xwo,10278
|
|
163
163
|
machineconfig/scripts/python/get_zellij_cmd.py,sha256=e35-18hoXM9N3PFbvbizfkNY_-63iMicieWE3TbGcCQ,576
|
|
164
164
|
machineconfig/scripts/python/gh_models.py,sha256=3BLfW25mBRiPO5VKtVm-nMlKLv-PaZDw7mObajq6F6M,5538
|
|
165
|
-
machineconfig/scripts/python/interactive.py,sha256=
|
|
165
|
+
machineconfig/scripts/python/interactive.py,sha256=qGcvn8XXCkck1xidcEFqPGBawgiEJXctwQqd_-dhRIQ,10162
|
|
166
166
|
machineconfig/scripts/python/mount_nfs.py,sha256=c8pWXimDWdgCkSskcnPgT-8ESPosil6Cvy2hGSaIBJE,3359
|
|
167
167
|
machineconfig/scripts/python/mount_nw_drive.py,sha256=iru6AtnTyvyuk6WxlK5R4lDkuliVpPV5_uBTVVhXtjQ,1550
|
|
168
168
|
machineconfig/scripts/python/mount_ssh.py,sha256=rGY2pgtlnWMi0Rrge1aCdjtfbULrj2cyaStDoX-y2w4,2236
|
|
@@ -174,7 +174,7 @@ machineconfig/scripts/python/repos_helper_clone.py,sha256=xW5YZEoNt3k7h9NIULhUhO
|
|
|
174
174
|
machineconfig/scripts/python/repos_helper_record.py,sha256=YEEQORfEiLddOIIgePo5eEkyQUFruFg3kc8npMvRL-o,10927
|
|
175
175
|
machineconfig/scripts/python/repos_helper_update.py,sha256=AYyKIB7eQ48yoYmFjydIhRI1lV39TBv_S4_LCa-oKuQ,11042
|
|
176
176
|
machineconfig/scripts/python/scheduler.py,sha256=rKhssuxkD697EY6qaV6CSdNhxpAQLDWO4fE8GMCQ9FA,3061
|
|
177
|
-
machineconfig/scripts/python/share_terminal.py,sha256=
|
|
177
|
+
machineconfig/scripts/python/share_terminal.py,sha256=3d0tOjAiXbonuJprHitoUmyU4zVLnexQGdTNs1-5qq0,3455
|
|
178
178
|
machineconfig/scripts/python/snapshot.py,sha256=aDvKeoniZaeTSNv9zWBUajaj2yagAxVdfuvO1_tgq5Y,1026
|
|
179
179
|
machineconfig/scripts/python/start_slidev.py,sha256=U5ujAL7R5Gd5CzFReTsnF2SThjY91aFBg0Qz_MMl6U4,4573
|
|
180
180
|
machineconfig/scripts/python/start_terminals.py,sha256=DRWbMZumhPmL0DvvsCsbRNFL5AVQn1SgaziafTio3YQ,6149
|
|
@@ -353,13 +353,14 @@ machineconfig/settings/zellij/layouts/panes.kdl,sha256=KlhKtelBy4Z2ENV_pix4xE7NH
|
|
|
353
353
|
machineconfig/settings/zellij/layouts/st.kdl,sha256=QXLRK7Wx05aKbKRHVmm4RspLYzPmEa44JMK1TwXQk58,523
|
|
354
354
|
machineconfig/settings/zellij/layouts/st2.kdl,sha256=1FKTH3qQWYMWp_wPMreP7fKOTlVd4cfBy3J8fv4zCBc,1489
|
|
355
355
|
machineconfig/settings/zellij/layouts/stacked_panes.kdl,sha256=usY8kKKwX1KUMXnWDivPg0i0drpM1Biw-tOnNZVjiZU,163
|
|
356
|
+
machineconfig/setup_linux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
356
357
|
machineconfig/setup_linux/nix/cli_installation.sh,sha256=AQ_wRmldeD1tPqCmU7qgz9ZrZFly4OYwBJDGRpb9IJ0,5470
|
|
357
358
|
machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh,sha256=F5dbg0n9RHsKGPn8fIdZMn3p0RrHEkb8rWBGsdVGbus,1207
|
|
358
359
|
machineconfig/setup_linux/others/openssh-server_add_pub_key.sh,sha256=UiJcD1o4UekKKtp5YJKRq135PpqdTLXy7M6HvQ-Qum4,1993
|
|
359
360
|
machineconfig/setup_linux/web_shortcuts/android.sh,sha256=gzep6bBhK7FCBvGcXK0fdJCtkSfBOftt0aFyDZq_eMs,68
|
|
360
361
|
machineconfig/setup_linux/web_shortcuts/ascii_art.sh,sha256=RWcxH_Db7WHH37PclYmc92o6zAS557wGZxcYTuyTUZ0,3550
|
|
361
362
|
machineconfig/setup_linux/web_shortcuts/croshell.sh,sha256=X9-B1cVptbaFWaWTA-2ELNQx_2ktxu7ZVe48RvpCmkU,316
|
|
362
|
-
machineconfig/setup_linux/web_shortcuts/interactive.sh,sha256=
|
|
363
|
+
machineconfig/setup_linux/web_shortcuts/interactive.sh,sha256=o_rw_1lVKU7dazJ4ST58ZbaDwZ6FGLRyTD-yI2dBShk,454
|
|
363
364
|
machineconfig/setup_linux/web_shortcuts/ssh.sh,sha256=k6BAY-zAWsi1beOMiZODxw4VOjZCTABZu__gxSET1eU,1924
|
|
364
365
|
machineconfig/setup_windows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
365
366
|
machineconfig/setup_windows/others/docker.ps1,sha256=M8NfsSxH8YlmY92J4rSe1xWOwTW8IFrdgb8cI8Riu2E,311
|
|
@@ -374,11 +375,11 @@ machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py,sha256=rZZJamy3YxAeJh
|
|
|
374
375
|
machineconfig/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
375
376
|
machineconfig/utils/accessories.py,sha256=W_9dLzjwNTW5JQk_pe3B2ijQ1nA2-8Kdg2r7VBtzgQs,4340
|
|
376
377
|
machineconfig/utils/code.py,sha256=pKPHInKgXJWeACVbxuE7sMdYeZCbNttaYCsfonGhFfc,4464
|
|
377
|
-
machineconfig/utils/installer.py,sha256=
|
|
378
|
+
machineconfig/utils/installer.py,sha256=Cfu0arQ-QE2TfDThP5Bb5HHpDA7kHlsWpAqGFrTA8c0,8954
|
|
378
379
|
machineconfig/utils/io.py,sha256=ZXB3aataS1IZ_0WMcCRSmoN1nbkvEO-bWYcs-TpngqU,2872
|
|
379
380
|
machineconfig/utils/links.py,sha256=riNUrG8aGElRszdOPOic4M2AyOcpdcth_-y8JEiZpJ4,10253
|
|
380
381
|
machineconfig/utils/notifications.py,sha256=vvdsY5IX6XEiILTnt5lNyHxhCi0ljdGX2T_67VRfrG4,9009
|
|
381
|
-
machineconfig/utils/options.py,sha256=
|
|
382
|
+
machineconfig/utils/options.py,sha256=8pG-apcc28xxJ5BQiACsGNTKwWtkQyH3hCtzBEhokK8,8366
|
|
382
383
|
machineconfig/utils/path_extended.py,sha256=nTETtTxzNaxdrapIH3WzkR__b-1k6Lx7SpRAXqmIJN4,51793
|
|
383
384
|
machineconfig/utils/path_helper.py,sha256=jqOf3TAlw5cqSp4HBAlOqjAR_bzC8_fvjA-_-CooI6Y,8030
|
|
384
385
|
machineconfig/utils/procs.py,sha256=KjEbrwfbdoi5IBM518scxMDVi7NxTZLHuYiKmwdGlzg,11393
|
|
@@ -395,14 +396,14 @@ machineconfig/utils/cloud/onedrive/setup_oauth.py,sha256=ZTVkqgrwbV_EoPvyT8dyOTU
|
|
|
395
396
|
machineconfig/utils/cloud/onedrive/transaction.py,sha256=m-aNcnWj_gfZVvJOSpkdIqjZxU_3nXx2CA-qKbQgP3I,26232
|
|
396
397
|
machineconfig/utils/installer_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
397
398
|
machineconfig/utils/installer_utils/github_release_bulk.py,sha256=vK5WJ-a566egAIEHdKsn3iOAh5LBqeY4zPDHPgqHVcE,6887
|
|
398
|
-
machineconfig/utils/installer_utils/installer_abc.py,sha256=
|
|
399
|
-
machineconfig/utils/installer_utils/installer_class.py,sha256=
|
|
399
|
+
machineconfig/utils/installer_utils/installer_abc.py,sha256=6lN_luAmyiPnncD9o-TjRQBYZHCwdrLU8V9eFp9eZBc,9549
|
|
400
|
+
machineconfig/utils/installer_utils/installer_class.py,sha256=6IQswaC9mxIdeaMG-rOt-vqyKGYibBRMvC0UglZ_3mI,20268
|
|
400
401
|
machineconfig/utils/schemas/fire_agents/fire_agents_input.py,sha256=CCs5ebomW1acKWZRpv9dyDzM-W6pwvVplikcutE2D8I,2339
|
|
401
402
|
machineconfig/utils/schemas/installer/installer_types.py,sha256=DLagmIe0G5-xg7HZ9VrlFCDk1gIbwvX7O4gZjwq0wh0,1326
|
|
402
403
|
machineconfig/utils/schemas/layouts/layout_types.py,sha256=M1ZFCz_kjRZPhxM19rIYUDR5lDDpwa09odR_ihtIFq0,1932
|
|
403
404
|
machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
|
|
404
|
-
machineconfig-3.
|
|
405
|
-
machineconfig-3.
|
|
406
|
-
machineconfig-3.
|
|
407
|
-
machineconfig-3.
|
|
408
|
-
machineconfig-3.
|
|
405
|
+
machineconfig-3.98.dist-info/METADATA,sha256=Lp-8scw6tGrHgQ7ENdFL1_uwZYhb2pT3V6P87zYmWtc,7032
|
|
406
|
+
machineconfig-3.98.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
407
|
+
machineconfig-3.98.dist-info/entry_points.txt,sha256=c6ea0waVseT1rbfz1bw3k-eph2yVaB67x9hx64Mpvfs,1066
|
|
408
|
+
machineconfig-3.98.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
|
|
409
|
+
machineconfig-3.98.dist-info/RECORD,,
|
|
@@ -5,17 +5,14 @@ cloud_mount = machineconfig.scripts.python.cloud_mount:arg_parser
|
|
|
5
5
|
cloud_repo_sync = machineconfig.scripts.python.cloud_repo_sync:args_parser
|
|
6
6
|
cloud_sync = machineconfig.scripts.python.cloud_sync:arg_parser
|
|
7
7
|
croshell = machineconfig.scripts.python.croshell:arg_parser
|
|
8
|
-
devops = machineconfig.scripts.python.devops:
|
|
8
|
+
devops = machineconfig.scripts.python.devops:app
|
|
9
9
|
fire = machineconfig.scripts.python.fire_jobs:main_from_parser
|
|
10
10
|
fire_agents = machineconfig.scripts.python.fire_agents:main
|
|
11
11
|
ftpx = machineconfig.scripts.python.ftpx:main_from_parser
|
|
12
|
-
ia = machineconfig.scripts.python.interactive:main
|
|
13
12
|
initai = machineconfig.scripts.python.ai.initai:main
|
|
14
|
-
install = machineconfig.scripts.python.devops_devapps_install:main_with_parser
|
|
15
13
|
kill_process = machineconfig.utils.procs:main
|
|
16
14
|
mount_nfs = machineconfig.scripts.python.mount_nfs:main
|
|
17
15
|
mount_nw_drive = machineconfig.scripts.python.mount_nw_drive:main
|
|
18
16
|
repos = machineconfig.scripts.python.repos:main_from_parser
|
|
19
|
-
share_terminal = machineconfig.scripts.python.share_terminal:main_with_parser
|
|
20
17
|
start_slidev = machineconfig.scripts.python.start_slidev:arg_parser
|
|
21
18
|
wifi_conn = machineconfig.scripts.python.wifi_conn:arg_parser
|
|
File without changes
|
|
File without changes
|