feat: Make the init command more friendly.
This commit is contained in:
parent
224a2fdd28
commit
aea0678f65
|
@ -20,7 +20,7 @@ class Args:
|
||||||
del self.opts[key]
|
del self.opts[key]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def consumeOpt(self, key: str, default: Value) -> Value:
|
def consumeOpt(self, key: str, default: Value = False) -> Value:
|
||||||
if key in self.opts:
|
if key in self.opts:
|
||||||
result = self.opts[key]
|
result = self.opts[key]
|
||||||
del self.opts[key]
|
del self.opts[key]
|
||||||
|
@ -34,9 +34,9 @@ class Args:
|
||||||
return result
|
return result
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def consumeArg(self) -> Optional[str]:
|
def consumeArg(self, default: Optional[str] = None) -> Optional[str]:
|
||||||
if len(self.args) == 0:
|
if len(self.args) == 0:
|
||||||
return None
|
return default
|
||||||
|
|
||||||
first = self.args[0]
|
first = self.args[0]
|
||||||
del self.args[0]
|
del self.args[0]
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import tempfile
|
|
||||||
import requests
|
import requests
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -220,8 +219,7 @@ def grabExtern(extern: dict[str, Extern]):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print(f"Installing {extSpec}-{ext.tag} from {ext.git}...")
|
print(f"Installing {extSpec}-{ext.tag} from {ext.git}...")
|
||||||
shell.popen("git", "clone", "--depth", "1", "--branch",
|
git.Repo.clone_from(ext.git, extPath, branch=ext.tag, depth=1)
|
||||||
ext.tag, ext.git, extPath)
|
|
||||||
|
|
||||||
if os.path.exists(os.path.join(extPath, "project.json")):
|
if os.path.exists(os.path.join(extPath, "project.json")):
|
||||||
grabExtern(context.loadProject(extPath).extern)
|
grabExtern(context.loadProject(extPath).extern)
|
||||||
|
@ -238,13 +236,11 @@ cmds += [Cmd("i", "install", "Install all the external packages", installCmd)]
|
||||||
|
|
||||||
|
|
||||||
def initCmd(args: Args):
|
def initCmd(args: Args):
|
||||||
|
repo = args.consumeOpt('repo', const.DEFAULT_REPO_TEMPLATES)
|
||||||
|
list = args.consumeOpt('list')
|
||||||
|
|
||||||
template = args.consumeArg()
|
template = args.consumeArg()
|
||||||
|
name = 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
|
|
||||||
|
|
||||||
logger.info("Fetching registry...")
|
logger.info("Fetching registry...")
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
|
@ -257,20 +253,35 @@ def initCmd(args: Args):
|
||||||
registry = r.json()
|
registry = r.json()
|
||||||
|
|
||||||
if list:
|
if list:
|
||||||
print('\n'.join(
|
logger.info("Fetching registry...")
|
||||||
f"* {entry['id']} - {entry['description']}" for entry in registry))
|
r = requests.get(
|
||||||
else:
|
f'https://raw.githubusercontent.com/{repo}/main/registry.json')
|
||||||
template_match: Callable[[Json], str] = lambda t: t['id'] == template
|
|
||||||
if not any(filter(template_match, registry)):
|
|
||||||
raise RuntimeError(f"Unknown template {template}")
|
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as tmp:
|
if r.status_code != 200:
|
||||||
shell.exec(*["git", "clone", "-n", "--depth=1",
|
raise RuntimeError('Failed to fetch registry')
|
||||||
"--filter=tree:0", f"https://github.com/{repo}", tmp, "-q"])
|
|
||||||
shell.exec(*["git", "-C", tmp, "sparse-checkout",
|
print('\n'.join(
|
||||||
"set", "--no-cone", template, "-q"])
|
f"* {entry['id']} - {entry['description']}" for entry in json.loads(r.text)))
|
||||||
shell.exec(*["git", "-C", tmp, "checkout", "-q"])
|
return
|
||||||
shell.mv(os.path.join(tmp, template), os.path.join(".", template))
|
|
||||||
|
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)]
|
cmds += [Cmd("I", "init", "Initialize a new project", initCmd)]
|
||||||
|
|
|
@ -9,6 +9,8 @@ import shutil
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import platform
|
import platform
|
||||||
import logging
|
import logging
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from cutekit import const
|
from cutekit import const
|
||||||
|
@ -125,11 +127,18 @@ def wget(url: str, path: Optional[str] = None) -> str:
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
def exec(*args: str):
|
def exec(*args: str, quiet: bool = False) -> bool:
|
||||||
logger.info(f"Executing {args}")
|
logger.info(f"Executing {args}")
|
||||||
|
|
||||||
try:
|
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:
|
except FileNotFoundError:
|
||||||
raise RuntimeError(f"{args[0]}: Command not found")
|
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)
|
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] = {}
|
LATEST_CACHE: dict[str, str] = {}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
BLACK = "\033[0;30m"
|
BLACK = "\033[30m"
|
||||||
RED = "\033[0;31m"
|
RED = "\033[31m"
|
||||||
GREEN = "\033[0;32m"
|
GREEN = "\033[32m"
|
||||||
BROWN = "\033[0;33m"
|
BROWN = "\033[33m"
|
||||||
BLUE = "\033[0;34m"
|
BLUE = "\033[34m"
|
||||||
PURPLE = "\033[0;35m"
|
PURPLE = "\033[35m"
|
||||||
CYAN = "\033[0;36m"
|
CYAN = "\033[36m"
|
||||||
LIGHT_GRAY = "\033[0;37m"
|
WHITE = "\033[37m"
|
||||||
DARK_GRAY = "\033[1;30m"
|
|
||||||
LIGHT_RED = "\033[1;31m"
|
|
||||||
LIGHT_GREEN = "\033[1;32m"
|
BRIGHT_BLACK = "\033[90m"
|
||||||
YELLOW = "\033[1;33m"
|
BRIGHT_RED = "\033[91m"
|
||||||
LIGHT_BLUE = "\033[1;34m"
|
BRIGHT_GREEN = "\033[92m"
|
||||||
LIGHT_PURPLE = "\033[1;35m"
|
BRIGHT_BROWN = "\033[93m"
|
||||||
LIGHT_CYAN = "\033[1;36m"
|
BRIGHT_BLUE = "\033[94m"
|
||||||
LIGHT_WHITE = "\033[1;37m"
|
BRIGHT_PURPLE = "\033[95m"
|
||||||
|
BRIGHT_CYAN = "\033[96m"
|
||||||
|
BRIGHT_WHITE = "\033[97m"
|
||||||
|
|
||||||
BOLD = "\033[1m"
|
BOLD = "\033[1m"
|
||||||
FAINT = "\033[2m"
|
FAINT = "\033[2m"
|
||||||
ITALIC = "\033[3m"
|
ITALIC = "\033[3m"
|
||||||
|
@ -25,7 +28,7 @@ RESET = "\033[0m"
|
||||||
|
|
||||||
|
|
||||||
def title(text: str):
|
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:
|
def wordwrap(text: str, width: int = 60, newline: str = "\n") -> str:
|
||||||
|
|
Loading…
Reference in a new issue