diff --git a/hokusai/builder.py b/hokusai/builder.py index c085da8..08774b5 100644 --- a/hokusai/builder.py +++ b/hokusai/builder.py @@ -145,6 +145,9 @@ async def _build_single_target( provider_index: dict[str, Provider], ) -> None: """Build a single target by dispatching to the appropriate provider.""" + # Ensure parent directories exist for targets in subfolders. + (project_dir / target_name).parent.mkdir(parents=True, exist_ok=True) + target_cfg = config.targets[target_name] if isinstance(target_cfg, DownloadTargetConfig): diff --git a/hokusai/cli.py b/hokusai/cli.py index f58ad1b..df96bc5 100644 --- a/hokusai/cli.py +++ b/hokusai/cli.py @@ -194,12 +194,26 @@ def clean() -> None: state_name = state_filename(_project_name(config_path)) removed = 0 + dirs_to_check: set[Path] = set() for target_name in config.targets: target_path = project_dir / target_name if target_path.exists(): target_path.unlink() click.echo(click.style(" rm ", fg="red") + target_name) removed += 1 + # Track parent dirs that may now be empty. + parent = target_path.parent + if parent != project_dir: + dirs_to_check.add(parent) + + # Remove empty subdirectories left behind, bottom-up. + for d in sorted(dirs_to_check, key=lambda p: len(p.parts), reverse=True): + while d != project_dir and d.exists() and not any(d.iterdir()): + d.rmdir() + click.echo( + click.style(" rm ", fg="red") + str(d.relative_to(project_dir)) + "/" + ) + d = d.parent state_path = project_dir / state_name if state_path.exists():