diff --git a/.github/workflows/python-publish.yml b/.github/workflows/publish.yml similarity index 100% rename from .github/workflows/python-publish.yml rename to .github/workflows/publish.yml diff --git a/cutekit/args.py b/cutekit/args.py index 6982366..6109b92 100644 --- a/cutekit/args.py +++ b/cutekit/args.py @@ -20,7 +20,7 @@ class Args: del self.opts[key] return result - def consumeOpt(self, key: str, default: Value) -> Value: + def consumeOpt(self, key: str, default: Value = False) -> Value: if key in self.opts: result = self.opts[key] del self.opts[key] @@ -34,9 +34,9 @@ class Args: return result return None - def consumeArg(self) -> Optional[str]: + def consumeArg(self, default: Optional[str] = None) -> Optional[str]: if len(self.args) == 0: - return None + return default first = self.args[0] del self.args[0] diff --git a/cutekit/cmds.py b/cutekit/cmds.py index 28f666b..812c0c8 100644 --- a/cutekit/cmds.py +++ b/cutekit/cmds.py @@ -1,6 +1,5 @@ import os import logging -import tempfile import requests import sys @@ -220,8 +219,7 @@ def grabExtern(extern: dict[str, Extern]): continue print(f"Installing {extSpec}-{ext.tag} from {ext.git}...") - shell.popen("git", "clone", "--depth", "1", "--branch", - ext.tag, ext.git, extPath) + git.Repo.clone_from(ext.git, extPath, branch=ext.tag, depth=1) if os.path.exists(os.path.join(extPath, "project.json")): grabExtern(context.loadProject(extPath).extern) @@ -238,13 +236,11 @@ cmds += [Cmd("i", "install", "Install all the external packages", installCmd)] def initCmd(args: Args): + repo = args.consumeOpt('repo', const.DEFAULT_REPO_TEMPLATES) + list = args.consumeOpt('list') + template = args.consumeArg() - - if template is None: - raise RuntimeError("No template was provided") - - repo = const.DEFAULT_REPO_TEMPLATES if not "repo" in args.opts else args.opts["repo"] - list = "list" in args.opts + name = args.consumeArg() logger.info("Fetching registry...") r = requests.get( @@ -257,20 +253,35 @@ def initCmd(args: Args): registry = r.json() if list: - print('\n'.join( - f"* {entry['id']} - {entry['description']}" for entry in registry)) - else: - template_match: Callable[[Json], str] = lambda t: t['id'] == template - if not any(filter(template_match, registry)): - raise RuntimeError(f"Unknown template {template}") + logger.info("Fetching registry...") + r = requests.get( + f'https://raw.githubusercontent.com/{repo}/main/registry.json') - with tempfile.TemporaryDirectory() as tmp: - shell.exec(*["git", "clone", "-n", "--depth=1", - "--filter=tree:0", f"https://github.com/{repo}", tmp, "-q"]) - shell.exec(*["git", "-C", tmp, "sparse-checkout", - "set", "--no-cone", template, "-q"]) - shell.exec(*["git", "-C", tmp, "checkout", "-q"]) - shell.mv(os.path.join(tmp, template), os.path.join(".", template)) + if r.status_code != 200: + raise RuntimeError('Failed to fetch registry') + + print('\n'.join( + f"* {entry['id']} - {entry['description']}" for entry in json.loads(r.text))) + return + + if not template: + raise RuntimeError('Template not specified') + + if not name: + raise RuntimeError('Name not specified') + + if os.path.exists(name): + raise RuntimeError(f"Directory {name} already exists") + + print(f"Creating project {name} from template {template}...") + shell.cloneDir(f"https://github.com/{repo}", template, name) + print(f"Project {name} created\n") + + print("We suggest that you begin by typing:") + print(f" {vt100.GREEN}cd {name}{vt100.RESET}") + print(f" {vt100.GREEN}cutekit install{vt100.BRIGHT_BLACK} # Install external packages{vt100.RESET}") + print( + f" {vt100.GREEN}cutekit build{vt100.BRIGHT_BLACK} # Build the project{vt100.RESET}") cmds += [Cmd("I", "init", "Initialize a new project", initCmd)] diff --git a/cutekit/shell.py b/cutekit/shell.py index c9d5946..aca09a4 100644 --- a/cutekit/shell.py +++ b/cutekit/shell.py @@ -9,6 +9,8 @@ import shutil import fnmatch import platform import logging +import tempfile + from typing import Optional from cutekit import const @@ -125,11 +127,18 @@ def wget(url: str, path: Optional[str] = None) -> str: return path -def exec(*args: str): +def exec(*args: str, quiet: bool = False) -> bool: logger.info(f"Executing {args}") try: - proc = subprocess.run(args) + proc = subprocess.run( + args, stdout=sys.stdout if not quiet else subprocess.PIPE, stderr=sys.stderr if not quiet else subprocess.PIPE) + + if proc.stdout: + logger.info(proc.stdout.decode('utf-8')) + + if proc.stderr: + logger.error(proc.stderr.decode('utf-8')) except FileNotFoundError: raise RuntimeError(f"{args[0]}: Command not found") @@ -192,6 +201,19 @@ def cpTree(src: str, dst: str): shutil.copytree(src, dst, dirs_exist_ok=True) +def cloneDir(url: str, path: str, dest: str) -> str: + with tempfile.TemporaryDirectory() as tmp: + mkdir(tmp) + exec(*["git", "clone", "-n", "--depth=1", + "--filter=tree:0", url, tmp, "-q"], quiet=True) + exec(*["git", "-C", tmp, "sparse-checkout", + "set", "--no-cone", path, "-q"], quiet=True) + exec(*["git", "-C", tmp, "checkout", "-q", "--no-progress"], quiet=True) + mv(os.path.join(tmp, path), dest) + + return dest + + LATEST_CACHE: dict[str, str] = {} diff --git a/cutekit/vt100.py b/cutekit/vt100.py index 61ff2c6..f293828 100644 --- a/cutekit/vt100.py +++ b/cutekit/vt100.py @@ -1,19 +1,22 @@ -BLACK = "\033[0;30m" -RED = "\033[0;31m" -GREEN = "\033[0;32m" -BROWN = "\033[0;33m" -BLUE = "\033[0;34m" -PURPLE = "\033[0;35m" -CYAN = "\033[0;36m" -LIGHT_GRAY = "\033[0;37m" -DARK_GRAY = "\033[1;30m" -LIGHT_RED = "\033[1;31m" -LIGHT_GREEN = "\033[1;32m" -YELLOW = "\033[1;33m" -LIGHT_BLUE = "\033[1;34m" -LIGHT_PURPLE = "\033[1;35m" -LIGHT_CYAN = "\033[1;36m" -LIGHT_WHITE = "\033[1;37m" +BLACK = "\033[30m" +RED = "\033[31m" +GREEN = "\033[32m" +BROWN = "\033[33m" +BLUE = "\033[34m" +PURPLE = "\033[35m" +CYAN = "\033[36m" +WHITE = "\033[37m" + + +BRIGHT_BLACK = "\033[90m" +BRIGHT_RED = "\033[91m" +BRIGHT_GREEN = "\033[92m" +BRIGHT_BROWN = "\033[93m" +BRIGHT_BLUE = "\033[94m" +BRIGHT_PURPLE = "\033[95m" +BRIGHT_CYAN = "\033[96m" +BRIGHT_WHITE = "\033[97m" + BOLD = "\033[1m" FAINT = "\033[2m" ITALIC = "\033[3m" @@ -25,7 +28,7 @@ RESET = "\033[0m" def title(text: str): - print(f"{LIGHT_WHITE}{text}{RESET}:") + print(f"{BOLD}{text}{RESET}:") def wordwrap(text: str, width: int = 60, newline: str = "\n") -> str: