diff --git a/projects/cram/src/python/cram/__main__.py b/projects/cram/src/python/cram/__main__.py index ec8621a..5aa99dd 100644 --- a/projects/cram/src/python/cram/__main__.py +++ b/projects/cram/src/python/cram/__main__.py @@ -6,6 +6,7 @@ import os from pathlib import Path import pickle from typing import List +import sys from . import ( __author__, @@ -17,6 +18,7 @@ from .v0 import PackageV0, ProfileV0 from .v1 import PackageV1, ProfileV1 import click +import toml from toposort import toposort_flatten from vfs import Vfs @@ -294,12 +296,28 @@ def do_state(confdir, state_file): print(*e) -@cli.command("migrate-to-toml") +@cli.command("fmt") @click.argument("confdir", type=Path) @click.argument("requirement", type=str) -def do_migrate(confdig, requirement): +def do_migrate(confdir, requirement): """Convert from the 0.0.0 config format to the 0.1.0 TOML format""" + root = confdir.resolve() + if not root.is_dir(): + log.fatal(f"{confdir} does not exist!") + _exit(1) + + packages = load_packages(root) + pkg = packages[requirement] + json = pkg.json() + + for suffix in pkg.SPECIAL_FILES: + f = (root / requirement / suffix) + if f.exists(): + f.unlink() + + with open(root / requirement / "pkg.toml", "w") as fp: + toml.dump(json, fp) if __name__ == "__main__" or 1: logging.basicConfig( diff --git a/projects/cram/src/python/cram/v0.py b/projects/cram/src/python/cram/v0.py index b9b2ac0..ab8c5db 100644 --- a/projects/cram/src/python/cram/v0.py +++ b/projects/cram/src/python/cram/v0.py @@ -52,6 +52,34 @@ class PackageV0(Package): if postf.exists(): fs.exec(self.root, sh([str(postf)])) + def _read(self, p: Path): + if p.exists(): + with open(p) as fp: + return fp.read() + else: + return None + + def json(self): + buildt = self._read(self.root / "BUILD") + pret = self._read(self.root / "PRE_INSTALL") + installt = self._read(self.root / "INSTALL") + postt = self._read(self.root / "POST_INSTALL") + + o = {"cram": {"version": 1}, "package": {"require": []}} + + if buildt: + o["package"]["build"] = [{"run": buildt}] + if pret: + o["package"]["pre_install"] = [{"run": pret}] + if installt: + o["package"]["install"] = [{"run": installt}] + if postt: + o["package"]["install"] = [{"run": postt}] + + o["package"]["require"] = [{"name": it} for it in sorted(self.requires())] + + return o + class ProfileV0(PackageV0): def requires(self): diff --git a/projects/cram/src/python/cram/v1.py b/projects/cram/src/python/cram/v1.py index a6efaa1..72462b3 100644 --- a/projects/cram/src/python/cram/v1.py +++ b/projects/cram/src/python/cram/v1.py @@ -39,8 +39,14 @@ class PackageV1(Package): def requires(self): """Get the dependencies of this package.""" - return self.config().get("package", {}).get("requires") or [ - it["name"] for it in self.config().get("package", {}).get("require", []) + def _name(it): + if isinstance(it, str): + return it + elif isinstance(it, dict): + return it["name"] + + return [ + _name(it) for it in self.config().get("package", {}).get("require", []) ] def do_sh_or_script(self, content: Optional[Union[List[str], str]], fs: Vfs, dest: Path, cwd: Path = "/tmp"): @@ -48,10 +54,11 @@ class PackageV1(Package): pass elif isinstance(content, list): - return any(self.do_sh_or_script(c, fs, dest) for c in content) + for c in content: + self.do_sh_or_script(c, fs, dest) elif isinstance(content, dict): - return self.do_sh_or_script( + self.do_sh_or_script( content["run"], fs, dest, @@ -66,14 +73,13 @@ class PackageV1(Package): installf = self.root / content if installf.exists(): with open(installf, "r") as fp: - return self.do_sh_or_script(fp.read(), fs, dest) + self.do_sh_or_script(fp.read(), fs, dest) elif content: f = tempf(f"{sum}.sh") with open(f, "w") as fp: fp.write(content) fs.exec(cwd, sh([f])) - return True def do_build(self, fs: Vfs, dest: Path): self.do_sh_or_script(self.config().get("package", {}).get("build"), fs, dest) @@ -89,6 +95,10 @@ class PackageV1(Package): self.do_sh_or_script(self.config().get("package", {}).get("post_install"), fs, dest) + def json(self): + return self.config() + + class ProfileV1(PackageV1): """Unline packages, profiles don't support recursive stow of contents."""