Compare commits
6 Commits
6ea078c80d
...
4de2819109
| Author | SHA1 | Date | |
|---|---|---|---|
| 4de2819109 | |||
| dd7697fcc7 | |||
| 28b56e71ab | |||
| dd204788e3 | |||
| 57e763a24f | |||
| 81c33d100f |
@@ -6,36 +6,19 @@ import tarfile
|
||||
|
||||
from rich.console import Console
|
||||
from rich.progress import SpinnerColumn
|
||||
from util import check_ground_libs_path, check_sudo
|
||||
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
def install(args):
|
||||
# check if we are sudo
|
||||
if os.getuid() != 0:
|
||||
console.print("[b red]digpkg: the install command requires sudo to run[/]")
|
||||
sys.exit(1)
|
||||
|
||||
# ensure the GROUND_LIBS var is set
|
||||
if not os.getenv("GROUND_LIBS"):
|
||||
console.print("digpkg: the [i]GROUND_LIBS[/] environment variable is not set, defaulting to /usr/lib/ground/")
|
||||
os.environ["GROUND_LIBS"] = "/usr/lib/ground/"
|
||||
|
||||
# figure out which version to install
|
||||
package_name = args.name
|
||||
version = "latest"
|
||||
if "@" in args.name:
|
||||
split = package_name.split("@")
|
||||
package_name = split[0]
|
||||
version = split[1]
|
||||
|
||||
def install_package(package_name, version, args):
|
||||
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
|
||||
response = requests.get(f"https://chookspace.com/api/packages/SpookyDervish/generic/{package_name}/{version}/mineral.tar")
|
||||
response = requests.get(f"https://chookspace.com/api/packages/ground/generic/{package_name}/{version}/mineral.tar")
|
||||
|
||||
# check response code for errors
|
||||
if response.status_code == 404: # package doesn't exist
|
||||
@@ -79,3 +62,28 @@ def install(args):
|
||||
f.close()
|
||||
|
||||
console.print(f"[d][:white_check_mark:] Extracted to {extract_dir}.")
|
||||
|
||||
console.status("Finishing up...")
|
||||
|
||||
# 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)
|
||||
|
||||
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)
|
||||
38
src/list.py
Normal file
38
src/list.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import os
|
||||
import configparser
|
||||
from rich import print
|
||||
from rich.table import Table
|
||||
|
||||
from util import check_ground_libs_path
|
||||
|
||||
|
||||
def list_cmd(args):
|
||||
check_ground_libs_path()
|
||||
|
||||
ground_libs_folder = os.getenv("GROUND_LIBS")
|
||||
folders = os.listdir(ground_libs_folder)
|
||||
|
||||
table = Table("Name", "Version", "Description", title="Installed")
|
||||
config_parser = configparser.ConfigParser()
|
||||
|
||||
for folder in folders:
|
||||
full_path = os.path.join(ground_libs_folder, folder)
|
||||
|
||||
# skip anything that isnt a folder
|
||||
if not os.path.isdir(full_path):
|
||||
continue
|
||||
|
||||
# read the mineral.ini file to figure out the version and description
|
||||
ini_path = os.path.join(full_path, "mineral.ini")
|
||||
if not os.path.isfile(ini_path):
|
||||
continue
|
||||
|
||||
config_parser.read(ini_path)
|
||||
|
||||
table.add_row(
|
||||
f"[b]{folder}",
|
||||
f"[blue]{config_parser.get('package', 'version')}",
|
||||
config_parser.get("package", "description"),
|
||||
)
|
||||
|
||||
print(table)
|
||||
25
src/main.py
25
src/main.py
@@ -4,6 +4,8 @@ import os, sys
|
||||
from install import install
|
||||
from publish import publish
|
||||
from remove import remove
|
||||
from list import list_cmd
|
||||
from uninstall import uninstall
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
@@ -13,7 +15,7 @@ def parse_arguments():
|
||||
|
||||
# install command
|
||||
install_command = sub_parsers.add_parser(name="install", description="install a mineral")
|
||||
install_command.add_argument("name", help="name of the mineral to install")
|
||||
install_command.add_argument("names", help="name of the minerals to install", nargs="+")
|
||||
install_command.add_argument("--max-retries", help="max number of download retries before giving up", default=3, type=int)
|
||||
|
||||
# uninstall command
|
||||
@@ -22,7 +24,6 @@ def parse_arguments():
|
||||
|
||||
# list command
|
||||
list_command = sub_parsers.add_parser(name="list", description="list all minerals installed in the current environment")
|
||||
list_command.add_argument("--env_name", help="list all minerals from a specific environment.", default=None, required=False)
|
||||
|
||||
# publish command
|
||||
publish_command = sub_parsers.add_parser(name="publish", description="publish a package to the repository")
|
||||
@@ -34,28 +35,12 @@ def parse_arguments():
|
||||
remove_command.add_argument("name", help="name and version of the package")
|
||||
|
||||
# env command
|
||||
"""env_command = sub_parsers.add_parser(name="env", description="manage Ground environments")
|
||||
env_sub_parsers = env_command.add_subparsers(dest="env_command")
|
||||
|
||||
env_new_command = env_sub_parsers.add_parser(name="new", description="create a new environment")
|
||||
env_new_command.add_argument("name", help="name of the new environment")
|
||||
env_new_command.add_argument("--dont-use", help="by default, the newly created environment will be set as the current environment. if this argument is parsed, then it will be created but not activated.", action="store_true")
|
||||
|
||||
env_destroy_command = env_sub_parsers.add_parser(name="destroy", description="delete an environment")
|
||||
env_destroy_command.add_argument("name", help="name of the environment to DESTROYYY")
|
||||
env_destroy_command.add_argument("--confirm-yes", action="store_true", help="don't ask for confirmation (DANGEROUS)")
|
||||
|
||||
env_list_command = env_sub_parsers.add_parser(name="list", description="list all environments")"""
|
||||
|
||||
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
if not args.command:
|
||||
arg_parser.print_help()
|
||||
sys.exit(0)
|
||||
if args.command == "env" and not args.env_command:
|
||||
env_command.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
if args.command == "install":
|
||||
install(args)
|
||||
@@ -63,6 +48,10 @@ def parse_arguments():
|
||||
publish(args)
|
||||
elif args.command == "remove":
|
||||
remove(args)
|
||||
elif args.command == "list":
|
||||
list_cmd(args)
|
||||
elif args.command == "uninstall":
|
||||
uninstall(args)
|
||||
|
||||
def main():
|
||||
parse_arguments()
|
||||
|
||||
@@ -39,8 +39,21 @@ def publish(args):
|
||||
|
||||
console.print()
|
||||
|
||||
with console.status("Compressing...", spinner="bouncingBall", spinner_style="blue") as status:
|
||||
with console.status("Authenticating...", spinner="bouncingBall", spinner_style="blue") as status:
|
||||
# check if we have permission to link the package to the repo
|
||||
repo_perms_request = requests.get(
|
||||
url=f"https://chookspace.com/api/v1/users/{username}/orgs/ground/permissions",
|
||||
auth=HTTPBasicAuth(username, password)
|
||||
)
|
||||
if repo_perms_request.status_code == 401:
|
||||
console.print(f"[b red]digpkg: failed to publish mineral: checking authorization failed: invalid password[/b red]")
|
||||
sys.exit(1)
|
||||
elif not repo_perms_request.ok:
|
||||
console.print(f"[b red]digpkg: failed to publish mineral: checking authorization failed: {repo_perms_request.content.decode()}[/b red]")
|
||||
sys.exit(1)
|
||||
|
||||
# compress to a tar file
|
||||
console.status("Compressing")
|
||||
f = tempfile.TemporaryFile(mode="wb+")
|
||||
with tarfile.open(fileobj=f, mode="w:gz") as tar_file:
|
||||
tar_file.add(args.folder_path, arcname=os.path.basename(args.folder_path))
|
||||
@@ -52,22 +65,25 @@ def publish(args):
|
||||
# send the request
|
||||
status.update("Uploading...")
|
||||
response = requests.put(
|
||||
url=f"https://chookspace.com/api/packages/{username}/generic/{mineral_name}/{version}/mineral.tar",
|
||||
url=f"https://chookspace.com/api/packages/ground/generic/{mineral_name}/{version}/mineral.tar",
|
||||
data=f,
|
||||
auth=HTTPBasicAuth(username, password)
|
||||
)
|
||||
|
||||
f.close()
|
||||
|
||||
if response.status_code == 401:
|
||||
match response.status_code:
|
||||
case 401:
|
||||
console.print("[b red]digpkg: failed to publish mineral: authentication failed[/]")
|
||||
sys.exit(1)
|
||||
elif response.status_code == 400:
|
||||
case 400:
|
||||
console.print("[b red]digpkg: failed to publish mineral: the package name or version number are invalid[/]")
|
||||
sys.exit(1)
|
||||
elif response.status_code == 409:
|
||||
case 409:
|
||||
console.print("[b red]digpkg: failed to publish mineral: that version number is already in use[/]")
|
||||
sys.exit(1)
|
||||
|
||||
response.raise_for_status()
|
||||
console.print("[d][:white_check_mark:] Uploaded![/]")
|
||||
|
||||
console.print("[:white_check_mark:] Done!")
|
||||
@@ -30,7 +30,7 @@ def remove(args):
|
||||
|
||||
# send the request
|
||||
response = requests.delete(
|
||||
url=f"https://chookspace.com/api/packages/{username}/generic/{mineral_name}/{version}",
|
||||
url=f"https://chookspace.com/api/packages/ground/generic/{mineral_name}/{version}",
|
||||
auth=HTTPBasicAuth(username, password)
|
||||
)
|
||||
|
||||
@@ -42,4 +42,4 @@ def remove(args):
|
||||
sys.exit(1)
|
||||
|
||||
response.raise_for_status()
|
||||
console.print("[d][:white_check_mark:] Success![/]")
|
||||
console.print("[d][:white_check_mark:] Done![/]")
|
||||
36
src/uninstall.py
Normal file
36
src/uninstall.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import os, sys
|
||||
import shutil
|
||||
|
||||
from util import check_ground_libs_path, check_sudo
|
||||
from rich.console import Console
|
||||
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
def uninstall(args):
|
||||
check_sudo()
|
||||
check_ground_libs_path()
|
||||
|
||||
with console.status(status=f"Looking for [i]{args.name}[/]...", spinner="bouncingBall", spinner_style="blue") as status:
|
||||
mineral_path = os.path.join(os.getenv("GROUND_LIBS"), args.name)
|
||||
symlink_path = os.path.join(os.getenv("GROUND_LIBS"), f"{args.name}.so")
|
||||
|
||||
# check to make sure the mineral is installed
|
||||
if not os.path.isdir(mineral_path):
|
||||
console.print(f"[b red]digpkg: failed to uninstall [i]{args.name}[/]: mineral is not installed[/b red]")
|
||||
sys.exit(1)
|
||||
|
||||
# remove the symlink
|
||||
status.update("Removing symlink...")
|
||||
if os.path.islink(symlink_path):
|
||||
os.unlink(symlink_path)
|
||||
console.print(f"[d][:white_check_mark:] Removed symlink!")
|
||||
|
||||
# delete the folder
|
||||
shutil.rmtree(mineral_path)
|
||||
console.print(f"[d][:white_check_mark:] Removed mineral folder!")
|
||||
|
||||
|
||||
console.print(f"[:white_check_mark:] Done!")
|
||||
|
||||
16
src/util.py
Normal file
16
src/util.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import os, sys
|
||||
|
||||
from rich import print
|
||||
|
||||
|
||||
def check_ground_libs_path():
|
||||
# ensure the GROUND_LIBS var is set
|
||||
if not os.getenv("GROUND_LIBS"):
|
||||
print("digpkg: the [i]GROUND_LIBS[/] environment variable is not set, defaulting to /usr/lib/ground/")
|
||||
os.environ["GROUND_LIBS"] = "/usr/lib/ground/"
|
||||
|
||||
def check_sudo():
|
||||
# check if we are sudo
|
||||
if os.getuid() != 0:
|
||||
print("[b red]digpkg: that command requires sudo to run[/]")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user