Files
Digpkg/src/install.py

116 lines
4.5 KiB
Python
Raw Normal View History

2026-01-18 19:59:58 +11:00
import requests
import os
import sys
import tempfile
import tarfile
2026-01-19 21:06:25 +11:00
import configparser
import shutil
2026-01-18 19:59:58 +11:00
from rich.console import Console
from rich.progress import SpinnerColumn
2026-01-19 07:03:51 +11:00
from util import check_ground_libs_path, check_sudo
2026-01-18 19:59:58 +11:00
console = Console()
2026-01-19 21:06:25 +11:00
def install_package(package_name, version, args, is_dependency: bool = False):
2026-01-18 19:59:58 +11:00
retries_left = args.max_retries
with console.status("Downloading tarball...", spinner="bouncingBall", spinner_style="blue") as status:
2026-01-19 21:06:25 +11:00
console.print(f"Installing {package_name} [d]({version})[/]")
2026-01-18 19:59:58 +11:00
while retries_left > 0:
# grab the tar ball
response = requests.get(f"https://chookspace.com/api/packages/ground/generic/{package_name}/{version}/mineral.tar")
2026-01-18 19:59:58 +11:00
# check response code for errors
if response.status_code == 404: # package doesn't exist
console.print(f"[b red]digpkg: mineral \"{package_name}\" was not found. Check to make sure the name and version number are correct.[/]")
sys.exit(1)
elif response.status_code != 200:
retries_left -= 1
console.print(f"[b yellow]digpkg: failed to download mineral \"{package_name}\": {response.content.decode()} ({retries_left} retries left)[/]")
if retries_left == 0:
console.print(f"[b red]digpkg: exceeded max retries while downloading mineral \"{package_name}\"[/]")
sys.exit(1)
continue
2026-01-18 21:26:23 +11:00
response.raise_for_status()
2026-01-18 19:59:58 +11:00
break
# create temporary file for tarball
2026-01-18 21:26:23 +11:00
try:
f = tempfile.TemporaryFile("wb+")
f.write(response.content)
f.flush()
f.seek(0)
console.print("[d][:white_check_mark:] Tarball downloaded![/]")
except KeyboardInterrupt:
console.print("[b yellow]digpkg: operation cancelled by user[/]")
return
2026-01-18 19:59:58 +11:00
# extract the tarball to the GROUND_LIBS folder
status.update("Extracting...")
extract_dir = os.getenv("GROUND_LIBS")
if not os.path.isdir(extract_dir): # gotta ensure the folder exists
os.mkdir(extract_dir)
tar_file = tarfile.open(fileobj=f)
tar_file.extractall(extract_dir)
f.close()
2026-01-19 06:32:18 +11:00
console.print(f"[d][:white_check_mark:] Extracted to {extract_dir}.")
console.status("Finishing up...")
2026-01-19 07:03:51 +11:00
2026-01-19 21:06:25 +11:00
package_folder = os.path.join(extract_dir, f"{package_name}/")
if not os.path.isfile(os.path.join(package_folder, "mineral.ini")):
console.print(f"[b red]digpkg: failed to install {package_name}: the mineral doesn't have a mineral.ini file, please contact the maintainer because they've set up the mineral incorrectly.")
console.print("[d]Cleaning up failed install...[/]")
shutil.rmtree(os.path.join(extract_dir, package_name))
sys.exit(1)
config_parser = configparser.ConfigParser()
config_parser.read(os.path.join(package_folder, "mineral.ini"))
dependencies = config_parser["dependencies"]
2026-01-19 07:03:51 +11:00
# create a symlink from the main.so file to the ground libs folder so ground can find it
symlink_path = os.path.join(extract_dir, f"{package_name}.so") # the path where the symlink is
if not os.path.isfile(symlink_path):
os.symlink(os.path.join(extract_dir, package_name, "main.so"), symlink_path)
2026-01-19 21:06:25 +11:00
if is_dependency:
console.print(f"[d][:white_check_mark:] Done installing dependency: {package_name}[/]")
for dependency, dependency_version in dependencies.items():
install_package(dependency, dependency_version, args, True)
if not is_dependency:
console.print(f"\n[b green][:white_check_mark:] Installed {package_name}![/]")
def install(args):
check_sudo()
check_ground_libs_path()
for package in args.names:
# figure out which version to install
package_name = package
version = "1.0.0"
if "@" in package:
split = package.split("@")
package_name = split[0]
version = split[1]
else:
console.print(f"[b red]digpkg: failed to install package: please specify version to install for {package_name}[/]")
sys.exit(1)
install_package(package_name, version, args)