import configparser import tarfile import tempfile import os, sys import requests from requests.auth import HTTPBasicAuth from rich.console import Console from rich.prompt import Prompt console = Console() def publish(args): mineral_name = os.path.basename(args.folder_path) # sanity checks if not os.path.isdir(args.folder_path): console.print(f"[b red]digpkg: failed to publish mineral: \"{args.folder_path}\" is not a directory") sys.exit(1) if not os.path.isfile(os.path.join(args.folder_path, "mineral.ini")): console.print(f"[b red]digpkg: failed to publish mineral: mineral has no \"mineral.ini\" file") sys.exit(1) if os.path.basename(os.path.normpath(args.folder_path)).endswith("_build"): console.print(f"\n[b yellow]You didn't remove the \"_build\" suffix from your mineral's folder name!\n\nIf this is intentional you can ignore this message, however it is bad practice.\nIf this is not intentional, you will be unable to install your package properly using dig.[/]") config_parser = configparser.ConfigParser() config_parser.read(os.path.join(args.folder_path, "mineral.ini")) version = config_parser["package"]["version"] # ask for user and pass console.print("[b]Please authenticate.\n[/]") try: username = Prompt.ask("Username", console=console) password = Prompt.ask("Password (or PAT)", console=console, password=True) except KeyboardInterrupt: return console.print() 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", spinner_style="green") 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)) f.flush() f.seek(0) console.print("[d][:white_check_mark:] Compressed![/]") # send the request status.update("Uploading...", spinner_style="blue") response = requests.put( url=f"https://chookspace.com/api/packages/ground/generic/{mineral_name}/{version}/mineral.tar", data=f, auth=HTTPBasicAuth(username, password) ) f.close() match response.status_code: case 401: console.print("[b red]digpkg: failed to publish mineral: authentication failed[/]") sys.exit(1) case 400: console.print("[b red]digpkg: failed to publish mineral: the package name or version number are invalid[/]") sys.exit(1) 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!")