diff --git a/neb/src/install.py b/neb/src/install.py index 5f26c69..a2a05db 100644 --- a/neb/src/install.py +++ b/neb/src/install.py @@ -1,8 +1,13 @@ -from .console import print_error_message +from .console import print_error_message, console from .util import ensure_libs_env, comet_dir, get_package_index +import tempfile +import subprocess import os import sys +import json +import shutil +import glob def install(args): @@ -10,23 +15,85 @@ def install(args): # install each package in given list for name in args.names: - version = "latest" - - # get version number - name: str = name - if '@' in name: - version: str = (name.rsplit('@', 1)[-1]) - name = name.rpartition('@')[0] + with console.status("Getting package index...") as status: + version = "latest" - if version == "": - print_error_message("did not provide version") - return + # get version number + name: str = name + if '@' in name: + version: str = (name.rsplit('@', 1)[-1]) + name = name.rpartition('@')[0] + + if version == "": + print_error_message("Did not provide version!") + sys.exit(1) + + index = get_package_index() - index = get_package_index() - - package = index.get(name, None) - if package == None: - print_error_message(f"No package was found with the name \"{name}\"") - sys.exit(1) - - print(index) \ No newline at end of file + package = index.get(name, None) + if package == None: + print_error_message(f"No rock was found with the name \"{name}\"") + sys.exit(1) + + status.update(f"Downloading [b]{name}[/]...", spinner="moon") + with tempfile.TemporaryDirectory() as temp_dir: + result = subprocess.run(["git", "clone", package["repository"], temp_dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.DEVNULL) + if result.returncode != 0: + print_error_message(f"Failed to download \"{name}\": \"{result.stderr.decode()}\"") + sys.exit(1) + + console.print("[b][:white_check_mark:] Downloaded.[/]") + + status.update(f"Installing [b]{name}[/]...") + rock_file = os.path.join(temp_dir, "rock.json") + if not os.path.isfile(rock_file): + print_error_message(f"Failed to install [b]{name}[/]: no \"rock.json\" file was found in the downloaded rock!") + sys.exit(1) + + try: + with open(rock_file, "r") as f: + data = json.load(f) + except json.JSONDecodeError as e: + print_error_message(f"Failed to install [b]{name}[/]: failed to read \"rock.json\" file: {e}") + sys.exit(1) + + # build source code + rock_info = data.get("rock", {}) + + libs_path = os.getenv("COMET_LIBS") + out_path = os.path.join(libs_path, f"{name}.cometlib") + + + + status.stop() + console.print("You may need to type your admin password: ") + try: + if not os.path.isdir(libs_path): + subprocess.run(["sudo", "mkdir", libs_path], check=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + + os.chdir(temp_dir) + subprocess.run( + ["sudo", "gcc"] + glob.glob("src/*.c", recursive=True) + ["-fPIC", "-shared", "-Wl,-undefined,symbol_lookup", "-o", out_path] + rock_info.get("gccArgs", []), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=subprocess.PIPE, + check=True + ) + except KeyError as e: + print_error_message(f"Failed to install [b]{name}[/]: \"rock.json\" is missing the key \"{e.args[0]}\"") + sys.exit(1) + except subprocess.CalledProcessError as e: + print_error_message(f"Failed to install [b]{name}[/]: build failed: \"{e.stderr.decode()}\"") + sys.exit(1) + + lib_data_path = os.path.join(libs_path, name) + if not os.path.isdir(lib_data_path): + subprocess.run(["sudo", "mkdir", lib_data_path], check=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + + subprocess.run(["sudo", "cp", os.path.join(temp_dir, "rock.json"), os.path.join(lib_data_path, "rock.json")], check=True) + + docs_path = os.path.join(temp_dir, "docs/") + if os.path.isdir(docs_path): + subprocess.run(["sudo", "cp", "-R", docs_path, os.path.join(lib_data_path, "docs/")], check=True) + + console.print(f"[b][:white_check_mark:] Installed [green]{name}[/green]![/b]") \ No newline at end of file diff --git a/neb/src/util.py b/neb/src/util.py index ad06e5b..a5d5eb2 100644 --- a/neb/src/util.py +++ b/neb/src/util.py @@ -19,7 +19,7 @@ def get_needed_headers() -> bool: if not should_continue: return False - with console.status("Cloning git repo...") as status: + with console.status("Cloning git repo...", spinner="moon") as status: with tempfile.TemporaryDirectory() as temp_dir: repo_url = "https://chookspace.com/Comet/Comet" result = subprocess.run(["git", "clone", repo_url, temp_dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -38,7 +38,7 @@ def get_needed_headers() -> bool: status.update("Installing...") status.stop() - console.print("You will need to type your admin password: ") + console.print("You may need to type your admin password: ") result = subprocess.run(["sudo", "make", "install"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) if result.returncode != 0: print_error_message(f"failed to install: {result.stderr.decode()}") @@ -48,12 +48,19 @@ def get_needed_headers() -> bool: def get_package_index() -> dict: if not os.path.isfile(os.path.join(comet_dir(), "package_index.json")): - package_data = requests.get("https://chookspace.com/Comet/Nebula/raw/branch/main/package_index.json") - if not package_data.ok: - print_error_message(f"Failed to download package index: {package_data.reason}") - sys.exit(1) + with console.status("Downloading package index...", spinner="moon") as status: + package_data = requests.get("https://chookspace.com/Comet/Nebula/raw/branch/main/package_index.json") + if not package_data.ok: + print_error_message(f"Failed to download package index: {package_data.reason}") + sys.exit(1) + + status.update("Saving package index...") + data = package_data.json() + + with open(os.path.join(comet_dir(), "package_index.json"), "w") as f: + json.dump(data, f) - return package_data.json() + return data with open(os.path.join(comet_dir(), "package_index.json"), "r") as f: package_data = json.load(f) @@ -92,7 +99,9 @@ def ensure_includes_exist() -> list[str]: def ensure_libs_env() -> None: if not os.getenv("COMET_LIBS"): - os.environ["COMET_LIBS"] = "/usr/lib/comet" + default_loc = "/usr/lib/comet" + os.environ["COMET_LIBS"] = default_loc + console.print(f"[b cyan]note:[/] Using default install location ({default_loc}). Set the $COMET_LIBS variable to silence this.") if not ensure_includes_exist(): exit(0) \ No newline at end of file