diff --git a/neb/README.md b/neb/README.md index 84f5f13..9f2d49b 100644 --- a/neb/README.md +++ b/neb/README.md @@ -19,6 +19,10 @@ neb install packageName@1.0.0 (replace the number with the version number of the package you want to install) ## Changelog +### 1.1.0 +- Switched from getting the latest commit of packages to getting the latest release +- Added the `uninstall` subcommand + ### 1.0.1 - Fix long description hopefully diff --git a/neb/src/install.py b/neb/src/install.py index 39feb0f..1fa78f7 100644 --- a/neb/src/install.py +++ b/neb/src/install.py @@ -3,11 +3,14 @@ from .util import libs_dir, comet_dir, get_package_index import tempfile import subprocess +import requests import os import sys import json import shutil import glob +import io +import tarfile def install(args): @@ -38,12 +41,41 @@ def install(args): status.update(f"Downloading [b]{name}[/]...", spinner="moon") with tempfile.TemporaryDirectory() as temp_dir: os.chdir(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.log(f"[d][:white_check_mark:] Downloaded {name}.[/]") + result: requests.Response = None + if version == "latest": + result = requests.get(f"https://chookspace.com/api/v1/repos/{package["gitAuthor"]}/{name}/releases/latest") + else: + result = requests.get(f"https://chookspace.com/api/v1/repos/{package["gitAuthor"]}/{name}/releases/tags/{version}") + + if result.status_code == 404: + print_error_message(f"That version was not found for the rock \"{name}\". Check that the version number is correct and that your index isn't out of date.") + sys.exit(1) + elif not result.ok: + print_error_message(f"Failed to download \"{name}\": \"{result.reason}\"") + sys.exit(1) + + status.update("Pulling tarball...") + tar_file_data = requests.get(result.json()["tarball_url"]) + tar_file_data.raise_for_status() + console.log(f"[d][:white_check_mark:] Downloaded tarball for {name}.[/]") + + + tar_file_io = io.BytesIO(tar_file_data.content) + + status.update("Extracting...") + with tarfile.open(fileobj=tar_file_io, mode="r:gz") as tar: + # extract all in the root dir + members = [] + for member in tar.getmembers(): + if '/' in member.name and member.name != "/": + member.name = member.name.split("/", 1)[1] + if member.name: + members.append(member) + + tar.extractall(path=temp_dir, members=members, filter="data") + + console.log(f"[d][:white_check_mark:] Extracted tarball for {name}.[/]") status.update(f"Installing [b]{name}[/]...") rock_file = os.path.join(temp_dir, "rock.json") @@ -85,13 +117,13 @@ def install(args): # this feels really fragile but who caresssss.... lib_data_path = os.path.join(data_path, name) if not os.path.isdir(lib_data_path): - subprocess.run(["mkdir", "-p", lib_data_path], check=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + os.makedirs(lib_data_path, exist_ok=True) - subprocess.run(["cp", os.path.join(temp_dir, "rock.json"), os.path.join(lib_data_path, "rock.json")], check=True) + shutil.copy(os.path.join(temp_dir, "rock.json"), os.path.join(lib_data_path, "rock.json")) docs_path = os.path.join(temp_dir, "docs/") if os.path.isdir(docs_path): - subprocess.run(["cp", "-R", docs_path, os.path.join(lib_data_path, "docs/")], check=True) + shutil.copytree(docs_path, os.path.join(lib_data_path, "docs/")) console.log(f"[d][:white_check_mark:] Copied data for {name}.[/]") diff --git a/neb/src/list.py b/neb/src/list.py index 0a02d8e..bd65152 100644 --- a/neb/src/list.py +++ b/neb/src/list.py @@ -1,5 +1,5 @@ from .console import console -from .util import libs_dir +from .util import installed_libs, data_dir from rich.box import ROUNDED from rich.table import Table @@ -9,13 +9,17 @@ import os def list_packages(args) -> None: + data_path = data_dir() + installed = installed_libs() + + if len(installed) == 0: + console.print("No rocks are installed.") + return + packages_table = Table("Name", "Version", "Description", "Author", box=ROUNDED, header_style="bold blue", ) - data_dir = os.path.join(libs_dir(), "lib_data/") - libs = os.listdir(data_dir) - - for name in libs: - lib_data_dir = os.path.join(data_dir, name) + for name in installed: + lib_data_dir = os.path.join(data_path, name) rock_file = os.path.join(lib_data_dir, "rock.json") json_data = {} diff --git a/neb/src/main.py b/neb/src/main.py index 776bdb8..80470ff 100644 --- a/neb/src/main.py +++ b/neb/src/main.py @@ -5,16 +5,14 @@ import os from .install import install from .pull import pull from .list import list_packages - -__VERSION__ = "1.0.1" +from .uninstall import uninstall def main() -> int: # parse cli args arg_parser = argparse.ArgumentParser( prog="neb", - description="Nebula, the package manager for the Comet programming language.", - epilog="Version " + __VERSION__ + description="Nebula, the package manager for the Comet programming language." ) sub_parsers = arg_parser.add_subparsers(dest="cmd") @@ -28,6 +26,10 @@ def main() -> int: # list command list_cmd = sub_parsers.add_parser(name="list", description="list installed rocks") + + # uninstall command + uninstall_cmd = sub_parsers.add_parser(name="uninstall", description="uninstall an installed rock(s)") + uninstall_cmd.add_argument("names", help="name of the rocks to uninstall", nargs="+") args = arg_parser.parse_args() @@ -43,6 +45,8 @@ def main() -> int: pull(args) case "list": list_packages(args) + case "uninstall": + uninstall(args) # really feeling like a C programmer lmao return 0 diff --git a/neb/src/uninstall.py b/neb/src/uninstall.py new file mode 100644 index 0000000..8d083a2 --- /dev/null +++ b/neb/src/uninstall.py @@ -0,0 +1,23 @@ +from .util import installed_libs, libs_dir, data_dir +from .console import print_error_message, console + +import sys +import shutil +import os + + +def uninstall(args): + installed = installed_libs() + libs_path = libs_dir() + + for name in args.names: + if name not in installed: + print_error_message(f"No rock with the name \"{name}\" is installed.") + sys.exit(1) + + actual_lib = os.path.join(libs_path, f"{name}.cometlib") + if os.path.isfile(actual_lib): + os.remove(actual_lib) + + shutil.rmtree(os.path.join(data_dir(), name)) + console.log(f"[b][:white_check_mark:] Uninstalled [green]{name}[/green]![/b]") \ No newline at end of file diff --git a/neb/src/util.py b/neb/src/util.py index ab4e215..4706dbf 100644 --- a/neb/src/util.py +++ b/neb/src/util.py @@ -47,6 +47,13 @@ def get_needed_headers() -> bool: console.log("[b][:white_check_mark:] Comet headers are installed![/b]\n") return True + +def data_dir() -> str: + return os.path.join(libs_dir(), "lib_data/") + +def installed_libs() -> list: + libs = os.listdir(data_dir()) + return libs def update_package_index() -> dict: with console.status("Downloading package index...", spinner="moon") as status: diff --git a/setup.py b/setup.py index 3928248..d392924 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,11 @@ from setuptools import setup, find_packages -from neb.src.main import __VERSION__ with open("neb/README.md", "r") as f: long_description = f.read() setup( name="nebpkg", - version=__VERSION__, + version="1.1.0", description="Nebula, the package manager for the Comet programming language.", classifiers=[ "Development Status :: 4 - Beta",