create clean command

This commit is contained in:
Waylon Walker 2025-11-28 10:54:59 -06:00
parent 6d93dc8177
commit 04b07c3ef4

View file

@ -1315,6 +1315,94 @@ def diff_workspace(
if not any_diffs:
console.print("[green]No changes to diff in any repo.[/green]")
def get_branches_merged(repo_dir: Path, remote: bool = False, main_branch: str="main") -> list[str]:
cmd = ["git", "branch", "--merged", main_branch]
if remote:
cmd.append("--remotes")
branches = run_cmd(cmd, cwd=repo_dir)
current_branch = get_current_branch(repo_dir)
branches = [b.strip() for b in branches[1].splitlines() if not b.startswith("*") and not b.startswith("+")]
branches = [
b for b in branches
if b not in {main_branch, f"origin/{main_branch}", "origin/HEAD -> origin/main", current_branch}
and "->" not in b # filters symbolic refs
]
return branches
@app.command("clean")
def clean_workspace(
ctx: typer.Context,
workspace: str | None = typer.Option(
None,
"--workspace",
"-w",
help=(
"Workspace directory name to diff. "
"If omitted, uses the workspace containing the current directory."
),
),
dry_run: bool = typer.Option(
False,
"--dry-run",
"-n",
help="Print what would be deleted, but don't actually delete.",
),
):
"""Show detailed status for the current (or specified) workspace.
For each repo in the workspace:
- look up all local branches that are merged into main
- ask user to delete local branches that are merged into main
- look up all remote branches that are merged into main
- ask user to delete remote branches that are merged into main
"""
_settings, _repos_dir, workspaces_dir = get_ctx_paths(ctx)
ws_dir = find_workspace_dir(workspaces_dir, workspace)
workspace = ws_dir.name
if not ws_dir:
console.print(f"[red]Workspace '{workspace}' does not exist at {ws_dir}[/red]")
raise typer.Exit(1)
repos = [directory for directory in ws_dir.iterdir() if directory.is_dir()]
repo = pick_repo_with_iterfzf(repos)
title, _desc = read_workspace_readme(ws_dir)
console.print(
f"Cleaning workspace [bold]{title or ws_dir.name}[/bold] (dir: {repo.name})"
)
local_branches_merged = get_branches_merged(repo, remote=False)
remote_branches_merged = get_branches_merged(repo, remote=True)
console.print(
f"[green]Would delete {len(local_branches_merged)} local branches[/green]"
)
for b in local_branches_merged:
console.print(f"[yellow]{b}[/yellow]")
console.print(
f"[green]Would delete {len(remote_branches_merged)} remote branches[/green]"
)
for b in remote_branches_merged:
console.print(f"[yellow]{b}[/yellow]")
if dry_run:
console.print("[grey]Dry run. Exiting.[/grey]")
raise typer.Exit(0)
if not Confirm.ask("Delete these branches?"):
console.print("[red]Aborting.[/red]")
raise typer.Exit(1)
for b in local_branches_merged:
cmd = ["git", "branch", "-D", b]
run_cmd(cmd, cwd=repo)
for b in remote_branches_merged:
cmd = ["git", "push", "origin", "--delete", b]
def in_tmux() -> bool:
"""Return True if inside tmux"""