diff --git a/setup.py b/setup.py index ddf7a4d..d414598 100755 --- a/setup.py +++ b/setup.py @@ -206,6 +206,26 @@ class Resolved: system_installs: list[str] +def apply_filter(ctx: Context, resolved: Resolved, filters: list[str]) -> Resolved: + wanted = set(filters) + symlinks = [p for p in resolved.symlinks if p in wanted] + symlink_map = {s: d for s, d in resolved.symlink_map.items() if s in wanted} + copies = [p for p in resolved.copies if p in wanted] + system_installs = [p for p in resolved.system_installs if p in wanted] + + matched = set(symlinks) | set(symlink_map) | set(copies) | set(system_installs) + for f in wanted - matched: + ctx.error(f"--filter path not in selected profiles: {f!r}") + + return Resolved( + pkgs=[], + symlinks=symlinks, + symlink_map=symlink_map, + copies=copies, + system_installs=system_installs, + ) + + def resolve_profiles(ctx: Context, profile_names: list[str]) -> Resolved: pkgs: list[Pkg] = [] symlinks: list[str] = [] @@ -461,7 +481,7 @@ def parse_args() -> argparse.Namespace: description="Install dotfiles and system configuration.", ) parser.add_argument( - "-f", + "-F", "--force", action="store_true", help="Overwrite any existing links or files", @@ -491,6 +511,19 @@ def parse_args() -> argparse.Namespace: metavar="PROFILE", help=f"Extra profiles to apply on top of base (available: {', '.join(extras)})", ) + parser.add_argument( + "-f", + "--filter", + action="append", + metavar="PATH", + default=[], + dest="filters", + help=( + "Restrict the run to a single repo-relative path from the " + "selected profiles. Repeat to allow multiple paths. Skips " + "package and terminfo checks." + ), + ) return parser.parse_args() @@ -499,11 +532,15 @@ def main() -> int: ctx = Context(args) resolved = resolve_profiles(ctx, ["base", *args.profiles]) + if args.filters: + resolved = apply_filter(ctx, resolved, args.filters) + if args.remove_existing: remove_all_symlinks(ctx, resolved.symlinks, resolved.symlink_map) else: - check_terminfo(ctx) - check_packages_installed(ctx, resolved.pkgs) + if not args.filters: + check_terminfo(ctx) + check_packages_installed(ctx, resolved.pkgs) create_all_symlinks(ctx, resolved.symlinks, resolved.symlink_map) copy_all_items(ctx, resolved.copies) install_all_system_files(ctx, resolved.system_installs)