from pathlib import Path from typing import Optional import shutil import jinja2 from dots_manager.config import Constants, Environment from dots_manager.utils import is_some, parallelize def is_template(path: Path) -> bool: return path.suffix == Constants.template_extension def find_templates_under(destination: Path) -> list[Path]: return [ t for t in destination.glob("**/*" + Constants.template_extension) if t.is_file() and is_template(t) ] def render_template_to( template: Path, destination: Path, env: Environment ) -> Optional[Path]: env.logger.debug(f"rendering template {template} to {destination} ✧*ฺ") if not is_template(template): env.logger.error(f"{template} is not a valid template D:") return None jinja_env = jinja2.Environment( loader=jinja2.BaseLoader(), undefined=jinja2.StrictUndefined, trim_blocks=True, lstrip_blocks=True, ) rendered = render(template, jinja_env, env) if not rendered: env.logger.error(f"failed to render template {template}") return None destination.write_text(rendered) destination.chmod(template.stat().st_mode) return destination def render( source: Path, jinja_env: jinja2.Environment, env: Environment ) -> Optional[str]: try: env.logger.debug(f"rendering template {source} <_mood.happy>") return jinja_env.from_string(source.read_text()).render(**env.context) except Exception as e: env.logger.error(f"couldn’t render {source}: {e} <_mood.sad>") return None def compile_dotfiles(source: Path, output: Path, env: Environment) -> bool: env.logger.info(f"compiling {source} to {output} <_mood.anxious>") output.mkdir(exist_ok=True, parents=True) shutil.copytree(source, output, dirs_exist_ok=True) tasks = parallelize( lambda template: is_some( render_template_to, template, template.with_suffix(""), env, )[0] and (template.unlink() is None), find_templates_under(output), env.logger, ) return all(tasks)