Compare commits
No commits in common. "9ceb1915e1049f6c281f1c9cbe1c1b3d8e35f94b" and "6d93dc81776c4c7b9b4c01c3093de8998cf0c9be" have entirely different histories.
9ceb1915e1
...
6d93dc8177
1 changed files with 0 additions and 112 deletions
112
workspaces.py
112
workspaces.py
|
|
@ -1315,118 +1315,6 @@ def diff_workspace(
|
||||||
if not any_diffs:
|
if not any_diffs:
|
||||||
console.print("[green]No changes to diff in any repo.[/green]")
|
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})"
|
|
||||||
)
|
|
||||||
|
|
||||||
run_cmd(["git", "fetch", "--all", "--prune"], cwd=repo)
|
|
||||||
local_branches_merged = get_branches_merged(repo, remote=False)
|
|
||||||
remote_branches_merged = get_branches_merged(repo, remote=True)
|
|
||||||
|
|
||||||
if len(local_branches_merged) == 0 and len(remote_branches_merged) == 0:
|
|
||||||
console.print("[green]No branches to delete.[/green]")
|
|
||||||
raise typer.Exit(0)
|
|
||||||
|
|
||||||
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:
|
|
||||||
# b looks like "origin/feat/workspaces-tmux-support"
|
|
||||||
if "->" in b:
|
|
||||||
# safety: skip symbolic refs like "origin/HEAD -> origin/main"
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
remote, branch = b.split("/", 1)
|
|
||||||
except ValueError:
|
|
||||||
# fallback: no slash? assume origin + raw name
|
|
||||||
remote, branch = "origin", b
|
|
||||||
|
|
||||||
cmd = ["git", "push", remote, "--delete", branch]
|
|
||||||
|
|
||||||
status, out, err = run_cmd(cmd, cwd=repo)
|
|
||||||
|
|
||||||
if status != 0:
|
|
||||||
console.print(f"[red]Failed to delete {remote}/{branch}:[/red]\n{err}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
console.print("[green]Done.[/green]")
|
|
||||||
|
|
||||||
|
|
||||||
def in_tmux() -> bool:
|
def in_tmux() -> bool:
|
||||||
"""Return True if inside tmux"""
|
"""Return True if inside tmux"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue