diff --git a/CHANGELOG.md b/CHANGELOG.md index 17f4f03b657be..9fd93ec74f92e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - Adds _Open Comparison on Remote_ command to branch comparisons in views - Adds _Open in Worktree_ context menu command to branches and pull requests in views and the _Commit Graph_ - Adds an option to delete a worktree along with its branch from the _Git Delete Worktree_ command +- Adds a step to delete the worktree of a branch first if one exists when using the _Git Delete Branch_ command ### Changed diff --git a/src/commands/git/branch.ts b/src/commands/git/branch.ts index eb5b1154cfc1c..3004c3bdcb12d 100644 --- a/src/commands/git/branch.ts +++ b/src/commands/git/branch.ts @@ -3,6 +3,7 @@ import type { Container } from '../../container'; import type { GitBranchReference, GitReference } from '../../git/models/reference'; import { getNameWithoutRemote, getReferenceLabel, isRevisionReference } from '../../git/models/reference'; import { Repository } from '../../git/models/repository'; +import type { GitWorktree } from '../../git/models/worktree'; import type { QuickPickItemOfT } from '../../quickpicks/items/common'; import { createQuickPickSeparator } from '../../quickpicks/items/common'; import type { FlagsQuickPickItem } from '../../quickpicks/items/flags'; @@ -422,7 +423,10 @@ export class BranchGitCommand extends QuickCommand { return canPickStepContinue(step, state, selection) ? selection[0].item : StepResultBreak; } - private *deleteCommandSteps(state: DeleteStepState | PruneStepState, context: Context): StepResultGenerator { + private async *deleteCommandSteps( + state: DeleteStepState | PruneStepState, + context: Context, + ): AsyncStepResultGenerator { const prune = state.subcommand === 'prune'; if (state.flags == null) { state.flags = []; @@ -463,6 +467,29 @@ export class BranchGitCommand extends QuickCommand { ); assertStateStepDeleteBranches(state); + + const worktrees = await this.getWorktreesOfSelectedBranches(state); + if (worktrees.length) { + const result = yield* getSteps( + this.container, + { + command: 'worktree', + state: { + subcommand: 'delete', + repo: state.repo, + uris: worktrees.map(wt => wt.uri), + flags: ['--deleting-of-selected-branches'], + }, + }, + this.pickedVia, + ); + if (result !== StepResultBreak) { + // we get here if it was a step back from the delete worktrees picker + state.counter--; + continue; + } + } + const result = yield* this.deleteCommandConfirmStep(state, context); if (result === StepResultBreak) continue; @@ -476,6 +503,20 @@ export class BranchGitCommand extends QuickCommand { } } + private async getWorktreesOfSelectedBranches(state: DeleteStepState | PruneStepState): Promise { + const worktrees = await state.repo.getWorktrees(); + + const refs = new Set( + Array.isArray(state.references) + ? state.references.map(r => r.name) + : state.references != null + ? [state.references.name] + : undefined, + ); + + return worktrees.filter(wt => wt.branch && refs.has(wt.branch.name)); + } + private *deleteCommandConfirmStep( state: | DeleteStepState> diff --git a/src/commands/git/worktree.ts b/src/commands/git/worktree.ts index eb5544c8c70bb..e270678b6cfb1 100644 --- a/src/commands/git/worktree.ts +++ b/src/commands/git/worktree.ts @@ -103,7 +103,7 @@ interface CreateState { skipWorktreeConfirmations?: boolean; } -type DeleteFlags = '--force' | '--delete-branches'; +type DeleteFlags = '--force' | '--delete-branches' | '--deleting-of-selected-branches'; interface DeleteState { subcommand: 'delete'; @@ -953,7 +953,9 @@ export class WorktreeGitCommand extends QuickCommand { private *deleteCommandConfirmStep(state: DeleteStepState, context: Context): StepResultGenerator { context.title = state.uris.length === 1 ? 'Delete Worktree' : 'Delete Worktrees'; const label = state.uris.length === 1 ? 'Delete Worktree' : 'Delete Worktrees'; + const deletingOfSelectedBranches = state.flags.includes('--deleting-of-selected-branches'); const branchesLabel = state.uris.length === 1 ? 'Branch' : 'Branches'; + const selectedBranchesLabelSuffix = !deletingOfSelectedBranches ? '' : ` of ${branchesLabel}`; const description = state.uris.length === 1 ? `delete worktree in $(folder) ${getWorkspaceFriendlyPath(state.uris[0])}` @@ -964,23 +966,27 @@ export class WorktreeGitCommand extends QuickCommand { appendReposToTitle(`Confirm ${context.title}`, state, context), [ createFlagsQuickPickItem(state.flags, [], { - label: label, + label: `${label}${selectedBranchesLabelSuffix}`, detail: `Will ${description}`, }), createFlagsQuickPickItem(state.flags, ['--force'], { - label: `Force ${label}`, + label: `Force ${label}${selectedBranchesLabelSuffix}`, description: 'includes ANY UNCOMMITTED changes', detail: `Will forcibly ${description}`, }), - createFlagsQuickPickItem(state.flags, ['--delete-branches'], { - label: `${label} & ${branchesLabel}`, - detail: `Will ${description} ${branchesDescription}`, - }), - createFlagsQuickPickItem(state.flags, ['--force', '--delete-branches'], { - label: `Force ${label} & ${branchesLabel}`, - description: 'includes ANY UNCOMMITTED changes', - detail: `Will forcibly ${description} ${branchesDescription}`, - }), + ...(deletingOfSelectedBranches + ? [] + : [ + createFlagsQuickPickItem(state.flags, ['--delete-branches'], { + label: `${label} & ${branchesLabel}`, + detail: `Will ${description} ${branchesDescription}`, + }), + createFlagsQuickPickItem(state.flags, ['--force', '--delete-branches'], { + label: `Force ${label} & ${branchesLabel}`, + description: 'includes ANY UNCOMMITTED changes', + detail: `Will forcibly ${description} ${branchesDescription}`, + }), + ]), ], context, );