2026-01-18 19:59:58 +11:00
|
|
|
import requests
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
import tempfile
|
|
|
|
|
import tarfile
|
|
|
|
|
|
|
|
|
|
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 07:29:55 +11:00
|
|
|
def install_package(package_name, version, args):
|
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:
|
|
|
|
|
while retries_left > 0:
|
|
|
|
|
# grab the tar ball
|
2026-01-19 06:27:44 +11:00
|
|
|
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
|
|
|
|
|
|
|
|
# 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 07:29:55 +11:00
|
|
|
console.print("[:white_check_mark:] Done!")
|
|
|
|
|
|
|
|
|
|
def install(args):
|
|
|
|
|
|
|
|
|
|
check_sudo()
|
|
|
|
|
check_ground_libs_path()
|
|
|
|
|
|
|
|
|
|
for package in args.names:
|
|
|
|
|
# figure out which version to install
|
|
|
|
|
package_name = package
|
|
|
|
|
version = "latest"
|
|
|
|
|
if "@" in package:
|
|
|
|
|
split = package.split("@")
|
|
|
|
|
package_name = split[0]
|
|
|
|
|
version = split[1]
|
|
|
|
|
|
|
|
|
|
install_package(package_name, version, args)
|