Initial commit: add AutoDeploy project
This commit is contained in:
98
deploy_tool/path_manager.py
Normal file
98
deploy_tool/path_manager.py
Normal file
@@ -0,0 +1,98 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import ctypes
|
||||
import os
|
||||
import sys
|
||||
import winreg
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Protocol
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class EnvironmentUpdate:
|
||||
path_entries: list[Path] = field(default_factory=list)
|
||||
env_vars: dict[str, str] = field(default_factory=dict)
|
||||
|
||||
|
||||
class RegistryLike(Protocol):
|
||||
def get_value(self, name: str) -> str: ...
|
||||
|
||||
def set_value(self, name: str, value: str) -> None: ...
|
||||
|
||||
def broadcast_change(self) -> None: ...
|
||||
|
||||
|
||||
class UserEnvironmentRegistry:
|
||||
key_path = r"Environment"
|
||||
|
||||
def get_value(self, name: str) -> str:
|
||||
try:
|
||||
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, self.key_path, 0, winreg.KEY_READ) as key:
|
||||
value, _ = winreg.QueryValueEx(key, name)
|
||||
return str(value)
|
||||
except FileNotFoundError:
|
||||
return ""
|
||||
|
||||
def set_value(self, name: str, value: str) -> None:
|
||||
with winreg.CreateKeyEx(winreg.HKEY_CURRENT_USER, self.key_path, 0, winreg.KEY_SET_VALUE) as key:
|
||||
winreg.SetValueEx(key, name, 0, winreg.REG_EXPAND_SZ, value)
|
||||
|
||||
def broadcast_change(self) -> None:
|
||||
if sys.platform != "win32":
|
||||
return
|
||||
hwnd_broadcast = 0xFFFF
|
||||
wm_settingchange = 0x001A
|
||||
smto_abortifhung = 0x0002
|
||||
result = ctypes.c_ulong()
|
||||
ctypes.windll.user32.SendMessageTimeoutW(
|
||||
hwnd_broadcast,
|
||||
wm_settingchange,
|
||||
0,
|
||||
"Environment",
|
||||
smto_abortifhung,
|
||||
5000,
|
||||
ctypes.byref(result),
|
||||
)
|
||||
|
||||
|
||||
def merge_path_entries(current_path: str, entries: list[Path]) -> str:
|
||||
parts = [part for part in current_path.split(os.pathsep) if part.strip()]
|
||||
seen = {_normalize_path(part) for part in parts}
|
||||
|
||||
for entry in entries:
|
||||
value = str(entry)
|
||||
normalized = _normalize_path(value)
|
||||
if normalized not in seen:
|
||||
parts.append(value)
|
||||
seen.add(normalized)
|
||||
|
||||
return os.pathsep.join(parts)
|
||||
|
||||
|
||||
def build_environment_update(tool_name: str, executable: Path) -> EnvironmentUpdate:
|
||||
exe = Path(executable)
|
||||
bin_dir = exe.parent
|
||||
env_vars: dict[str, str] = {}
|
||||
|
||||
if tool_name == "JDK":
|
||||
env_vars["JAVA_HOME"] = str(bin_dir.parent)
|
||||
elif tool_name == "Maven":
|
||||
env_vars["MAVEN_HOME"] = str(bin_dir.parent)
|
||||
elif tool_name == "Gradle":
|
||||
env_vars["GRADLE_HOME"] = str(bin_dir.parent)
|
||||
|
||||
return EnvironmentUpdate(path_entries=[bin_dir], env_vars=env_vars)
|
||||
|
||||
|
||||
def apply_user_environment(update: EnvironmentUpdate, registry: RegistryLike | None = None) -> None:
|
||||
env_registry = registry or UserEnvironmentRegistry()
|
||||
current_path = env_registry.get_value("Path")
|
||||
env_registry.set_value("Path", merge_path_entries(current_path, update.path_entries))
|
||||
for name, value in update.env_vars.items():
|
||||
env_registry.set_value(name, value)
|
||||
env_registry.broadcast_change()
|
||||
|
||||
|
||||
def _normalize_path(value: str) -> str:
|
||||
return os.path.normcase(os.path.normpath(os.path.expandvars(value.strip().strip('"'))))
|
||||
Reference in New Issue
Block a user