deskflow/scripts/install_deps.py

214 lines
5.6 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
import os
from lib import windows, cmd_utils
import sys
import argparse
import traceback
config_file = "deps.yml"
class YamlError(Exception):
pass
class PlatformError(Exception):
pass
class PathError(Exception):
pass
try:
import yaml # type: ignore
except ImportError:
# this is fairly common in earlier versions of python3,
# which is normally what you find on mac and windows.
print("Python yaml module missing, please install: pip install pyyaml")
sys.exit(1)
def main():
"""Entry point for the script."""
parser = argparse.ArgumentParser()
parser.add_argument(
"--pause-on-exit", action="store_true", help="Useful on Windows"
)
parser.add_argument(
"--only", type=str, help="Only install the specified dependency"
)
args = parser.parse_args()
try:
deps = Dependencies(args.only)
deps.install()
except Exception:
traceback.print_exc()
if args.pause_on_exit:
input("Press enter to continue...")
def get_os():
"""Detects the operating system."""
if sys.platform == "win32":
return "windows"
elif sys.platform == "darwin":
return "mac"
elif sys.platform.startswith("linux"):
return "linux"
else:
raise PlatformError(f"Unsupported platform: {sys.platform}")
def get_linux_distro():
"""Detects the Linux distro."""
os_file = "/etc/os-release"
if os.path.isfile(os_file):
with open(os_file) as f:
for line in f:
if line.startswith("ID="):
return line.strip().split("=")[1].strip('"')
return None
class Config:
"""Reads the dependencies configuration file."""
def __init__(self):
with open(config_file, "r") as f:
data = yaml.safe_load(f)
os_name = get_os()
try:
root = data["dependencies"]
except KeyError:
raise YamlError(f"Nothing found in {config_file} for: dependencies")
try:
self.os = root[os_name]
except KeyError:
raise YamlError(f"Nothing found in {config_file} for: {os_name}")
def get_qt_config(self):
try:
return self.os["qt"]
except KeyError:
raise YamlError(f"Nothing found in {config_file} for: qt")
def get_packages_file(self):
try:
return self.os["packages"]
except KeyError:
raise YamlError(f"Nothing found in {config_file} for: packages")
def get_linux_package_command(self, distro):
try:
distro_data = self.os[distro]
except KeyError:
raise YamlError(f"Nothing found in {config_file} for: {distro}")
try:
command_base = distro_data["command"]
except KeyError:
raise YamlError(f"No package command found in {config_file} for: {distro}")
try:
package_data = distro_data["packages"]
except KeyError:
raise YamlError(f"No package list found in {config_file} for: {distro}")
packages = " ".join(package_data)
return f"{command_base} {packages}"
class Dependencies:
def __init__(self, only):
self.config = Config()
self.only = only
def install(self):
"""Installs dependencies for the current platform."""
os = get_os()
if os == "windows":
self.windows()
elif os == "mac":
self.mac()
elif os == "linux":
self.linux()
else:
raise PlatformError(f"Unsupported platform: {os}")
def windows(self):
"""Installs dependencies on Windows."""
if not windows.is_admin():
windows.relaunch_as_admin(__file__)
sys.exit()
ci_env = os.environ.get("CI")
if ci_env:
print("CI environment detected")
only_qt = self.only == "qt"
# for ci, skip qt; we install qt separately so we can cache it.
if not ci_env or only_qt:
qt = windows.WindowsQt(self.config.get_qt_config(), config_file)
qt_install_dir = qt.get_install_dir()
if qt_install_dir:
print(f"Skipping Qt, already installed at: {qt_install_dir}")
else:
qt.install()
if only_qt:
return
choco = windows.WindowsChoco()
if ci_env:
choco.config_ci_cache()
try:
ci_skip = self.config.os["ci"]["skip"]
choco_config_file = ci_skip["edit-config"]
remove_packages = ci_skip["packages"]
except KeyError:
raise YamlError(f"Bad mapping in {config_file} on Windows for: ci")
choco.remove_from_config(choco_config_file, remove_packages)
try:
command = self.config.os["command"]
except KeyError:
raise YamlError(f"Nothing found in {config_file} on Windows for: command")
choco.install(command, ci_env)
def mac(self):
"""Installs dependencies on macOS."""
try:
command = self.config.os["command"]
except KeyError:
raise YamlError(f"Nothing found in {config_file} on Mac for: command")
cmd_utils.run(command)
def linux(self):
"""Installs dependencies on Linux."""
distro = get_linux_distro()
if not distro:
raise PlatformError("Unable to detect Linux distro")
command = self.config.get_linux_package_command(distro)
cmd_utils.run(command)
if __name__ == "__main__":
main()