machineconfig 4.8__py3-none-any.whl → 4.91__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/jobs/installer/custom_dev/winget.py +1 -0
- machineconfig/jobs/installer/installer_data.json +2403 -0
- machineconfig/jobs/installer/package_groups.py +157 -0
- machineconfig/scripts/linux/agents +2 -0
- machineconfig/scripts/linux/sessions +2 -0
- machineconfig/scripts/python/{fire_agents.py → agents.py} +7 -0
- machineconfig/scripts/python/croshell.py +13 -27
- machineconfig/scripts/python/devops.py +0 -13
- machineconfig/scripts/python/devops_devapps_install.py +148 -107
- machineconfig/scripts/python/interactive.py +30 -76
- machineconfig/scripts/python/{fire_jobs_layout_helper.py → sessions.py} +7 -0
- machineconfig/utils/installer.py +40 -16
- machineconfig/utils/installer_utils/github_release_bulk.py +2 -12
- machineconfig/utils/installer_utils/installer_abc.py +56 -60
- machineconfig/utils/schemas/installer/installer_types.py +0 -1
- {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/METADATA +1 -1
- {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/RECORD +20 -21
- {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/entry_points.txt +2 -0
- machineconfig/jobs/installer/packages_custom_dev.json +0 -380
- machineconfig/jobs/installer/packages_custom_essential.json +0 -39
- machineconfig/jobs/installer/packages_github_dev.json +0 -1127
- machineconfig/jobs/installer/packages_github_essential.json +0 -787
- machineconfig/setup_linux/web_shortcuts/ascii_art.sh +0 -93
- {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/WHEEL +0 -0
- {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from typing import Literal, TypeAlias, Union
|
|
2
|
+
|
|
3
|
+
PACKAGES_NAMES_DEV = Literal[
|
|
4
|
+
"ngrok",
|
|
5
|
+
"Visual Studio Code",
|
|
6
|
+
"aider",
|
|
7
|
+
"github-copilot-cli",
|
|
8
|
+
"gemini",
|
|
9
|
+
"crush",
|
|
10
|
+
"opencode-ai",
|
|
11
|
+
"warp",
|
|
12
|
+
"q",
|
|
13
|
+
"cursor-cli",
|
|
14
|
+
"droid",
|
|
15
|
+
"Alacritty",
|
|
16
|
+
"Brave",
|
|
17
|
+
"bypass-paywalls-chrome",
|
|
18
|
+
"Cursor",
|
|
19
|
+
"espanso",
|
|
20
|
+
"Gorilla",
|
|
21
|
+
"lvim",
|
|
22
|
+
"nerdfont",
|
|
23
|
+
"Redis",
|
|
24
|
+
"Wezterm",
|
|
25
|
+
"winget",
|
|
26
|
+
"ytui-music",
|
|
27
|
+
"youtube-tui",
|
|
28
|
+
"termusic",
|
|
29
|
+
"kronos",
|
|
30
|
+
"transmission",
|
|
31
|
+
"nnn",
|
|
32
|
+
"exa",
|
|
33
|
+
"bytehound",
|
|
34
|
+
"atuin",
|
|
35
|
+
"browsh",
|
|
36
|
+
"carbonyl",
|
|
37
|
+
"patat",
|
|
38
|
+
"SqliteBrowser",
|
|
39
|
+
"DBeaver",
|
|
40
|
+
"rainfrog",
|
|
41
|
+
"duckdb",
|
|
42
|
+
"cpz",
|
|
43
|
+
"rmz",
|
|
44
|
+
"mermaid-cli",
|
|
45
|
+
"html2markdown",
|
|
46
|
+
"xcrawl3r",
|
|
47
|
+
"obsidian",
|
|
48
|
+
"marp",
|
|
49
|
+
"presenterm",
|
|
50
|
+
"pandoc",
|
|
51
|
+
"devcontainer",
|
|
52
|
+
"bitwarden",
|
|
53
|
+
"OBS Background removal",
|
|
54
|
+
"rustdesk",
|
|
55
|
+
"evcxr",
|
|
56
|
+
"forward-cli",
|
|
57
|
+
"bandwhich",
|
|
58
|
+
"ipinfo",
|
|
59
|
+
"dust",
|
|
60
|
+
"ots",
|
|
61
|
+
"ffsend",
|
|
62
|
+
"portal",
|
|
63
|
+
"qrcp",
|
|
64
|
+
"qrscan",
|
|
65
|
+
"termscp",
|
|
66
|
+
"qr",
|
|
67
|
+
"filebrowser",
|
|
68
|
+
"cloudreve",
|
|
69
|
+
"restic",
|
|
70
|
+
"syncthing",
|
|
71
|
+
"istio",
|
|
72
|
+
"openpomodoro-cli",
|
|
73
|
+
"rust-analyzer",
|
|
74
|
+
"kondo",
|
|
75
|
+
"tokei",
|
|
76
|
+
"lazygit",
|
|
77
|
+
"lazydocker",
|
|
78
|
+
"onefetch",
|
|
79
|
+
"gitcs",
|
|
80
|
+
"just",
|
|
81
|
+
"navi",
|
|
82
|
+
"tealdeer",
|
|
83
|
+
"sniffnet",
|
|
84
|
+
"hyperfine",
|
|
85
|
+
"ollama",
|
|
86
|
+
"cointop",
|
|
87
|
+
"vtm",
|
|
88
|
+
"edex-ui",
|
|
89
|
+
"extraterm",
|
|
90
|
+
"nushell",
|
|
91
|
+
"geckodriver",
|
|
92
|
+
"lolcatjs",
|
|
93
|
+
"figlet-cli",
|
|
94
|
+
"sharewifi",
|
|
95
|
+
"share-wifi",
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
PACKAGES_NAMES_ESSENTIAL = Literal[
|
|
99
|
+
"gh",
|
|
100
|
+
"hx",
|
|
101
|
+
"speedtest",
|
|
102
|
+
"pistol",
|
|
103
|
+
"diskonaut",
|
|
104
|
+
"xplr",
|
|
105
|
+
"btop",
|
|
106
|
+
"gotty",
|
|
107
|
+
"joshuto",
|
|
108
|
+
"zellij",
|
|
109
|
+
"boxes",
|
|
110
|
+
"ugrep",
|
|
111
|
+
"zoomit",
|
|
112
|
+
"ntop",
|
|
113
|
+
"devtunnel",
|
|
114
|
+
"bat",
|
|
115
|
+
"broot",
|
|
116
|
+
"btm",
|
|
117
|
+
"chatgpt",
|
|
118
|
+
"cloudflared",
|
|
119
|
+
"cpufetch",
|
|
120
|
+
"delta",
|
|
121
|
+
"dua",
|
|
122
|
+
"fastfetch",
|
|
123
|
+
"fd",
|
|
124
|
+
"fzf",
|
|
125
|
+
"gitui",
|
|
126
|
+
"glow",
|
|
127
|
+
"gum",
|
|
128
|
+
"lf",
|
|
129
|
+
"lsd",
|
|
130
|
+
"m365",
|
|
131
|
+
"mcfly",
|
|
132
|
+
"mods",
|
|
133
|
+
"mprocs",
|
|
134
|
+
"ouch",
|
|
135
|
+
"procs",
|
|
136
|
+
"rclone",
|
|
137
|
+
"rg",
|
|
138
|
+
"rga",
|
|
139
|
+
"starship",
|
|
140
|
+
"tere",
|
|
141
|
+
"topgrade",
|
|
142
|
+
"ttyd",
|
|
143
|
+
"viu",
|
|
144
|
+
"watchexec",
|
|
145
|
+
"yazi",
|
|
146
|
+
"zoxide",
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
PACKAGE_GROUPS: TypeAlias = Literal["ESSENTIAL", "DEV", "ESSENTIAL_SYSTEM", "DEV_SYSTEM"]
|
|
150
|
+
PACKAGE_GROUP2NAMES: dict[PACKAGE_GROUPS, list[str]] = {
|
|
151
|
+
"ESSENTIAL": list(PACKAGES_NAMES_ESSENTIAL.__args__),
|
|
152
|
+
"DEV": list(PACKAGES_NAMES_DEV.__args__),
|
|
153
|
+
"ESSENTIAL_SYSTEM": [],
|
|
154
|
+
"DEV_SYSTEM": [],
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
_ = Union
|
|
@@ -193,5 +193,12 @@ fire_agents collect $AGENTS_DIR "$REPO_ROOT/.ai/agents/$JOB_NAME/collected.txt"
|
|
|
193
193
|
typer.echo(f"Template bash script written to {save_path}")
|
|
194
194
|
|
|
195
195
|
|
|
196
|
+
def main_from_parser():
|
|
197
|
+
agents_app = typer.Typer(help="🤖 AI Agents management subcommands")
|
|
198
|
+
agents_app.command("create")(create)
|
|
199
|
+
agents_app.command("collect")(collect)
|
|
200
|
+
agents_app.command("template")(template)
|
|
201
|
+
return agents_app()
|
|
202
|
+
|
|
196
203
|
if __name__ == "__main__": # pragma: no cover
|
|
197
204
|
pass
|
|
@@ -10,10 +10,10 @@ from machineconfig.utils.path_extended import PathExtended as PathExtended
|
|
|
10
10
|
from machineconfig.utils.accessories import randstr
|
|
11
11
|
|
|
12
12
|
from machineconfig.utils.options import choose_from_options
|
|
13
|
-
from machineconfig.utils.ve import get_ve_activate_line
|
|
13
|
+
# from machineconfig.utils.ve import get_ve_activate_line
|
|
14
14
|
from rich.console import Console
|
|
15
15
|
from rich.panel import Panel
|
|
16
|
-
from rich.text import Text
|
|
16
|
+
# from rich.text import Text
|
|
17
17
|
|
|
18
18
|
console = Console()
|
|
19
19
|
|
|
@@ -173,41 +173,27 @@ print(f"🐊 Crocodile Shell | Running @ {Path.cwd()}")
|
|
|
173
173
|
title = "Running Python File"
|
|
174
174
|
else:
|
|
175
175
|
title = "Executed code"
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
pyfile.write_text(total_program, encoding="utf-8")
|
|
179
|
-
|
|
176
|
+
python_program = preprogram + add_print_header_pycode(str(pyfile), title=title) + program
|
|
177
|
+
pyfile.write_text(python_program, encoding="utf-8")
|
|
180
178
|
# ve_root_from_file, ipython_profile = get_ve_path_and_ipython_profile(PathExtended(file))
|
|
181
179
|
ipython_profile = ipython_profile if ipython_profile is not None else "default"
|
|
182
180
|
# ve_activateion_line = get_ve_activate_line(ve_name=args.ve or ve_profile_suggested, a_path=str(PathExtended.cwd()))
|
|
183
|
-
|
|
184
|
-
final_program = f"""
|
|
181
|
+
shell_program = """
|
|
185
182
|
#!/bin/bash
|
|
186
183
|
|
|
187
|
-
{activate_ve_line}
|
|
188
|
-
|
|
189
184
|
"""
|
|
190
185
|
if jupyter:
|
|
191
186
|
fire_line = f"code --new-window {str(pyfile)}"
|
|
192
187
|
else:
|
|
193
|
-
fire_line = interpreter
|
|
194
|
-
if interpreter == "ipython":
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
title = "🚀 LAUNCHING SCRIPT"
|
|
201
|
-
text1 = f"📄 Script: {pyfile}"
|
|
202
|
-
text2 = f"🔥 Command: {fire_line}"
|
|
203
|
-
launch_message = f"{title} \n{text1}\n{text2}"
|
|
204
|
-
console.print(Panel(Text(launch_message, justify="left"), expand=False, border_style="blue"))
|
|
205
|
-
|
|
206
|
-
# PROGRAM_PATH.write_text(data=final_program, encoding="utf-8")
|
|
207
|
-
# (PROGRAM_PATH + ".py").write_text(str(pyfile), encoding='utf-8')
|
|
188
|
+
fire_line = f"uv run --project $HOME/code/machineconfig/.venv {interpreter} {interactivity} "
|
|
189
|
+
if interpreter == "ipython": fire_line += f" --profile {ipython_profile} --no-banner"
|
|
190
|
+
fire_line += " " + str(pyfile)
|
|
191
|
+
shell_program += fire_line
|
|
192
|
+
from rich.syntax import Syntax
|
|
193
|
+
console.print(Syntax(shell_program, lexer="bash"))
|
|
194
|
+
print()
|
|
208
195
|
import subprocess
|
|
209
|
-
|
|
210
|
-
subprocess.run(final_program, shell=True, check=True)
|
|
196
|
+
subprocess.run(shell_program, shell=True, check=True)
|
|
211
197
|
|
|
212
198
|
|
|
213
199
|
def arg_parser() -> None:
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""devops with emojis"""
|
|
2
2
|
|
|
3
|
-
import machineconfig.scripts.python.fire_agents as fire_agents
|
|
4
|
-
import machineconfig.scripts.python.fire_jobs_layout_helper as fire_jobs_layout_helper
|
|
5
3
|
import machineconfig.scripts.python.devops_devapps_install as installer_entry_point
|
|
6
4
|
import machineconfig.scripts.python.share_terminal as share_terminal
|
|
7
5
|
import machineconfig.scripts.python.repos as repos
|
|
@@ -10,17 +8,6 @@ import typer
|
|
|
10
8
|
|
|
11
9
|
app = typer.Typer(help="🛠️ DevOps operations with emojis", no_args_is_help=True)
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
agents_app = typer.Typer(help="🤖 AI Agents management subcommands")
|
|
15
|
-
agents_app.command("create")(fire_agents.create)
|
|
16
|
-
agents_app.command("collect")(fire_agents.collect)
|
|
17
|
-
app.add_typer(agents_app, name="agents")
|
|
18
|
-
|
|
19
|
-
layouts_app = typer.Typer(help="Layouts management subcommands")
|
|
20
|
-
layouts_app.command("launch")(fire_jobs_layout_helper.launch)
|
|
21
|
-
layouts_app.command("load-balance")(fire_jobs_layout_helper.load_balance)
|
|
22
|
-
app.add_typer(layouts_app, name="session")
|
|
23
|
-
|
|
24
11
|
app.command(name="install", help="📦 Install essential packages")(installer_entry_point.main)
|
|
25
12
|
app.command(name="share-terminal", help="📡 Share terminal via web browser")(share_terminal.main)
|
|
26
13
|
app.command(name="repos", help="📁 Manage git repositories")(repos.main)
|
|
@@ -1,85 +1,79 @@
|
|
|
1
1
|
"""Devops Devapps Install"""
|
|
2
2
|
|
|
3
|
+
from machineconfig.utils.installer import get_installers_system_groups
|
|
3
4
|
import typer
|
|
4
5
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
from rich.panel import Panel
|
|
8
|
+
from rich.table import Table
|
|
5
9
|
from platform import system
|
|
6
|
-
from typing import Optional,
|
|
10
|
+
from typing import Optional, cast, get_args
|
|
11
|
+
from machineconfig.jobs.installer.package_groups import PACKAGE_GROUPS
|
|
7
12
|
|
|
8
|
-
|
|
13
|
+
console = Console()
|
|
9
14
|
|
|
10
15
|
|
|
11
16
|
def _handle_installer_not_found(search_term: str, all_installers: list["InstallerData"]) -> None: # type: ignore
|
|
12
17
|
"""Handle installer not found with friendly suggestions using fuzzy matching."""
|
|
13
18
|
from difflib import get_close_matches
|
|
14
|
-
|
|
15
|
-
# Get all possible names (both exe names and app names)
|
|
19
|
+
|
|
16
20
|
all_names = []
|
|
17
21
|
for inst in all_installers:
|
|
18
22
|
exe_name = inst["appName"]
|
|
19
23
|
all_names.append(exe_name)
|
|
20
|
-
|
|
21
|
-
# Find close matches using fuzzy matching
|
|
22
24
|
close_matches = get_close_matches(search_term, all_names, n=5, cutoff=0.4)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
console.print(f"\n❌ '[red]{search_term}[/red]' was not found.", style="bold")
|
|
26
|
+
|
|
26
27
|
if close_matches:
|
|
27
|
-
print("🤔 Did you mean one of these?")
|
|
28
|
+
console.print("🤔 Did you mean one of these?", style="yellow")
|
|
29
|
+
table = Table(show_header=False, box=None, pad_edge=False)
|
|
28
30
|
for i, match in enumerate(close_matches, 1):
|
|
29
|
-
|
|
31
|
+
table.add_row(f"[cyan]{i}.[/cyan]", f"[green]{match}[/green]")
|
|
32
|
+
console.print(table)
|
|
30
33
|
else:
|
|
31
|
-
print("📋 Here are some available options:")
|
|
34
|
+
console.print("📋 Here are some available options:", style="blue")
|
|
32
35
|
# Show first 10 installers as examples
|
|
33
36
|
sample_names = []
|
|
34
37
|
for inst in all_installers[:10]:
|
|
35
38
|
exe_name = inst["appName"]
|
|
36
|
-
sample_names.append(exe_name)
|
|
39
|
+
sample_names.append(exe_name)
|
|
40
|
+
|
|
41
|
+
table = Table(show_header=False, box=None, pad_edge=False)
|
|
37
42
|
for i, name in enumerate(sample_names, 1):
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
table.add_row(f"[cyan]{i}.[/cyan]", f"[green]{name}[/green]")
|
|
44
|
+
console.print(table)
|
|
45
|
+
|
|
40
46
|
if len(all_installers) > 10:
|
|
41
|
-
print(f" ... and {len(all_installers) - 10} more")
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
console.print(f" [dim]... and {len(all_installers) - 10} more[/dim]")
|
|
48
|
+
|
|
49
|
+
panel = Panel(
|
|
50
|
+
f"[bold blue]💡 Use 'ia' to interactively browse all available installers.[/bold blue]\n[bold blue]💡 Use one of the categories: {list(get_args(PACKAGE_GROUPS))}[/bold blue]", title="[yellow]Helpful Tips[/yellow]", border_style="yellow"
|
|
51
|
+
)
|
|
52
|
+
console.print(panel)
|
|
45
53
|
|
|
46
54
|
|
|
47
55
|
def main_with_parser():
|
|
48
56
|
import typer
|
|
57
|
+
|
|
49
58
|
app = typer.Typer()
|
|
50
59
|
app.command()(main)
|
|
51
60
|
app()
|
|
52
61
|
|
|
53
62
|
|
|
54
|
-
def main(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
exe_name = installer["appName"]
|
|
69
|
-
app_name = installer["appName"]
|
|
70
|
-
if exe_name == a_which or app_name == a_which:
|
|
71
|
-
selected_installer = installer
|
|
72
|
-
break
|
|
73
|
-
|
|
74
|
-
if selected_installer is None:
|
|
75
|
-
_handle_installer_not_found(a_which, all_installers)
|
|
76
|
-
return None
|
|
77
|
-
message = Installer(selected_installer).install_robust(version=None) # finish the task
|
|
78
|
-
total_messages.append(message)
|
|
79
|
-
for a_message in total_messages:
|
|
80
|
-
print(a_message)
|
|
81
|
-
return None
|
|
82
|
-
|
|
63
|
+
def main(
|
|
64
|
+
which: Optional[str] = typer.Option(None, "--which", "-w", help="Comma-separated list of program names to install."),
|
|
65
|
+
group: Optional[PACKAGE_GROUPS] = typer.Option(None, "--group", "-g", help=f"Group name (one of {list(get_args(PACKAGE_GROUPS))})"),
|
|
66
|
+
interactive: bool = typer.Option(False, "--interactive", "-ia", help="Interactive selection of programs to install."),
|
|
67
|
+
) -> None:
|
|
68
|
+
if which is not None:
|
|
69
|
+
return install_clis(clis_names=[x.strip() for x in which.split(",") if x.strip() != ""])
|
|
70
|
+
if group is not None:
|
|
71
|
+
return get_programs_by_category(package_group=group)
|
|
72
|
+
if interactive:
|
|
73
|
+
return install_interactively()
|
|
74
|
+
typer.echo("❌ You must provide either --which, --group, or --interactive/-ia option.")
|
|
75
|
+
# typer.help(main)
|
|
76
|
+
raise typer.Exit(1)
|
|
83
77
|
|
|
84
78
|
|
|
85
79
|
def install_interactively():
|
|
@@ -87,84 +81,131 @@ def install_interactively():
|
|
|
87
81
|
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
88
82
|
from machineconfig.utils.installer import get_installers
|
|
89
83
|
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
90
|
-
installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
installer_options
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
progress.update(task, advance=1)
|
|
97
|
-
category_options = [f"📦 {cat}" for cat in get_args(WHICH_CAT)]
|
|
98
|
-
options = category_options + ["─" * 50] + installer_options
|
|
84
|
+
installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL", "DEV"])
|
|
85
|
+
installer_options = []
|
|
86
|
+
for x in installers:
|
|
87
|
+
installer_options.append(Installer(installer_data=x).get_description())
|
|
88
|
+
category_options = [f"📦 {cat}" for cat in get_args(PACKAGE_GROUPS)]
|
|
89
|
+
options = category_options + ["─" * 50] + installer_options
|
|
99
90
|
program_names = choose_from_options(multi=True, msg="Categories are prefixed with 📦", options=options, header="🚀 CHOOSE DEV APP OR CATEGORY", default="📦 essentials", fzf=True)
|
|
100
91
|
installation_messages: list[str] = []
|
|
101
92
|
for _an_idx, a_program_name in enumerate(program_names):
|
|
102
|
-
if a_program_name.startswith("─"):
|
|
93
|
+
if a_program_name.startswith("─"): # 50 dashes separator
|
|
103
94
|
continue
|
|
104
95
|
if a_program_name.startswith("📦 "):
|
|
105
96
|
category_name = a_program_name[2:] # Remove "📦 " prefix
|
|
106
|
-
if category_name in get_args(
|
|
107
|
-
get_programs_by_category(
|
|
97
|
+
if category_name in get_args(PACKAGE_GROUPS):
|
|
98
|
+
get_programs_by_category(package_group=cast(PACKAGE_GROUPS, category_name))
|
|
108
99
|
else:
|
|
109
100
|
installer_idx = installer_options.index(a_program_name)
|
|
110
101
|
an_installer_data = installers[installer_idx]
|
|
111
102
|
status_message = Installer(an_installer_data).install_robust(version=None) # finish the task - this returns a status message, not a command
|
|
112
103
|
installation_messages.append(status_message)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
print(
|
|
121
|
-
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
122
|
-
┃ 📦 Installing Category: {program_name}
|
|
123
|
-
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
|
|
124
|
-
from machineconfig.utils.source_of_truth import LIBRARY_ROOT
|
|
104
|
+
if installation_messages:
|
|
105
|
+
panel = Panel("\n".join([f"[blue]• {message}[/blue]" for message in installation_messages]), title="[bold green]📊 Installation Summary[/bold green]", border_style="green", padding=(1, 2))
|
|
106
|
+
console.print(panel)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def get_programs_by_category(package_group: PACKAGE_GROUPS):
|
|
110
|
+
panel = Panel(f"[bold yellow]Installing programs from category: [green]{package_group}[/green][/bold yellow]", title="[bold blue]📦 Category Installation[/bold blue]", border_style="blue", padding=(1, 2))
|
|
111
|
+
console.print(panel)
|
|
125
112
|
from machineconfig.utils.installer import get_installers, install_all
|
|
126
|
-
from machineconfig.utils.installer_utils.installer_abc import parse_apps_installer_linux, parse_apps_installer_windows
|
|
127
113
|
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
|
|
114
|
+
match package_group:
|
|
115
|
+
case "ESSENTIAL":
|
|
116
|
+
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL"])
|
|
132
117
|
install_all(installers_data=installers_)
|
|
133
|
-
case "
|
|
134
|
-
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["
|
|
118
|
+
case "DEV":
|
|
119
|
+
installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["DEV", "ESSENTIAL"])
|
|
135
120
|
install_all(installers_data=installers_)
|
|
136
|
-
case "
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
121
|
+
case "DEV_SYSTEM" | "ESSENTIAL_SYSTEM":
|
|
122
|
+
options_system = get_installers_system_groups()
|
|
123
|
+
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
124
|
+
for an_item in options_system:
|
|
125
|
+
if an_item["appName"] == package_group:
|
|
126
|
+
program = an_item["fileNamePattern"][get_normalized_arch()][get_os_name()]
|
|
127
|
+
if program is not None:
|
|
128
|
+
install_terminal_packages(program)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def choose_from_system_package_groups(options_system: dict[str, tuple[str, str]]) -> str:
|
|
132
|
+
from machineconfig.utils.options import choose_from_options
|
|
133
|
+
display_options = []
|
|
134
|
+
for group_name, (description, _) in options_system.items():
|
|
135
|
+
if description:
|
|
136
|
+
display_options.append(f"{group_name:<20} - {description}")
|
|
137
|
+
else:
|
|
138
|
+
display_options.append(group_name)
|
|
139
|
+
program_names = choose_from_options(multi=True, msg="", options=sorted(display_options), header="🚀 CHOOSE DEV APP", fzf=True)
|
|
140
|
+
program = ""
|
|
141
|
+
for display_name in program_names:
|
|
142
|
+
# Extract the actual group name (everything before " - " if present)
|
|
143
|
+
group_name = display_name.split(" - ")[0].strip() if " - " in display_name else display_name.strip()
|
|
144
|
+
console.print(f"\n[bold cyan]⚙️ Installing: [yellow]{group_name}[/yellow][/bold cyan]", style="bold")
|
|
145
|
+
_, sub_program = options_system[group_name] # Extract content from tuple
|
|
146
|
+
if sub_program.startswith("#winget"):
|
|
147
|
+
sub_program = sub_program[1:]
|
|
148
|
+
program += "\n" + sub_program
|
|
149
|
+
return program
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def install_terminal_packages(program: str):
|
|
153
|
+
from pathlib import Path
|
|
154
|
+
|
|
155
|
+
if system() == "Windows":
|
|
156
|
+
temp_script_path = Path("C:/Windows/Temp/temp_install_script.ps1")
|
|
157
|
+
lexer = "powershell"
|
|
158
|
+
else:
|
|
159
|
+
temp_script_path = Path("/tmp/temp_install_script.sh")
|
|
160
|
+
lexer = "bash"
|
|
161
|
+
temp_script_path.write_text(program, encoding="utf-8")
|
|
162
|
+
console.print(f"📝 [blue]Temporary script written to:[/blue] [green]{temp_script_path}[/green]")
|
|
163
|
+
from rich.syntax import Syntax
|
|
164
|
+
|
|
165
|
+
console.print(Panel(Syntax(code=program, lexer=lexer), title="📄 Installation Program", subtitle="shell code"), style="bold red")
|
|
166
|
+
console.print("🚀 [bold yellow]Starting installation...[/bold yellow]")
|
|
167
|
+
if system() == "Windows":
|
|
168
|
+
import subprocess
|
|
169
|
+
|
|
170
|
+
subprocess.run(["powershell", "-ExecutionPolicy", "Bypass", "-File", str(temp_script_path)], check=True)
|
|
171
|
+
elif system() == "Linux":
|
|
172
|
+
import subprocess
|
|
173
|
+
|
|
174
|
+
subprocess.run(["bash", str(temp_script_path)], check=True)
|
|
175
|
+
console.print("✅ [bold green]Installation completed.[/bold green]")
|
|
176
|
+
temp_script_path.unlink(missing_ok=True)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def install_clis(clis_names: list[str]):
|
|
180
|
+
from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
|
|
181
|
+
from machineconfig.utils.installer import get_installers
|
|
182
|
+
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
183
|
+
|
|
184
|
+
total_messages: list[str] = []
|
|
185
|
+
for a_which in clis_names:
|
|
186
|
+
all_installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL", "DEV"])
|
|
187
|
+
selected_installer = None
|
|
188
|
+
for installer in all_installers:
|
|
189
|
+
exe_name = installer["appName"]
|
|
190
|
+
app_name = installer["appName"]
|
|
191
|
+
if exe_name == a_which or app_name == a_which:
|
|
192
|
+
selected_installer = installer
|
|
193
|
+
break
|
|
194
|
+
if selected_installer is None:
|
|
195
|
+
_handle_installer_not_found(a_which, all_installers)
|
|
196
|
+
return None
|
|
197
|
+
message = Installer(selected_installer).install_robust(version=None) # finish the task
|
|
198
|
+
total_messages.append(message)
|
|
199
|
+
if total_messages:
|
|
200
|
+
console.print("\n[bold green]📊 Installation Results:[/bold green]")
|
|
201
|
+
for a_message in total_messages:
|
|
202
|
+
console.print(f"[blue]• {a_message}[/blue]")
|
|
203
|
+
return None
|
|
164
204
|
|
|
165
205
|
|
|
166
206
|
if __name__ == "__main__":
|
|
167
207
|
from machineconfig.utils.schemas.installer.installer_types import InstallerData
|
|
168
208
|
from machineconfig.utils.installer_utils.installer_class import Installer
|
|
209
|
+
|
|
169
210
|
_ = InstallerData, Installer
|
|
170
211
|
pass
|