Git: Delete Worktree... command for command palette only (#256827)

* Delete worktree picker  command palette

* clean up

* Only allow delete worktree picker from main repository

* Find main repository

* resolve hygiene formatting issues
This commit is contained in:
Christy 😺
2025-07-21 07:48:08 -07:00
committed by GitHub
parent 88b415f570
commit 6187e6deb7
3 changed files with 74 additions and 1 deletions

View File

@@ -9,7 +9,7 @@ import { Command, commands, Disposable, MessageOptions, Position, ProgressLocati
import TelemetryReporter from '@vscode/extension-telemetry';
import { uniqueNamesGenerator, adjectives, animals, colors, NumberDictionary } from '@joaomoreno/unique-names-generator';
import { ForcePushMode, GitErrorCodes, RefType, Status, CommitOptions, RemoteSourcePublisher, Remote, Branch, Ref } from './api/git';
import { Git, Stash } from './git';
import { Git, Stash, Worktree } from './git';
import { Model } from './model';
import { GitResourceGroup, Repository, Resource, ResourceGroupType } from './repository';
import { DiffEditorSelectionHunkToolbarContext, LineChange, applyLineChanges, getIndexDiffInformation, getModifiedRange, getWorkingTreeDiffInformation, intersectDiffWithRange, invertLineChange, toLineChanges, toLineRanges, compareLineChanges } from './staging';
@@ -57,6 +57,19 @@ class RefItemSeparator implements QuickPickItem {
constructor(private readonly refType: RefType) { }
}
class WorktreeItem implements QuickPickItem {
get label(): string {
return `$(list-tree) ${this.worktree.name}`;
}
get description(): string {
return this.worktree.path;
}
constructor(readonly worktree: Worktree) { }
}
class RefItem implements QuickPickItem {
get label(): string {
@@ -215,6 +228,29 @@ class RemoteTagDeleteItem extends RefItem {
}
}
class WorktreeDeleteItem extends WorktreeItem {
async run(mainRepository: Repository): Promise<void> {
if (!this.worktree.path) {
return;
}
try {
await mainRepository.deleteWorktree(this.worktree.path);
} catch (err) {
if (err.gitErrorCode === GitErrorCodes.WorktreeContainsChanges) {
const forceDelete = l10n.t('Force Delete');
const message = l10n.t('The worktree contains modified or untracked files. Do you want to force delete?');
const choice = await window.showWarningMessage(message, { modal: true }, forceDelete);
if (choice === forceDelete) {
await mainRepository.deleteWorktree(this.worktree.path, { force: true });
}
}
}
}
}
class MergeItem extends BranchItem {
async run(repository: Repository): Promise<void> {
@@ -3420,6 +3456,32 @@ export class CommandCenter {
}
}
@command('git.deleteWorktreeFromPalette')
async deleteWorktreeFromPalette(): Promise<void> {
const mainRepository = this.model.repositories.find(repo =>
!repo.dotGit.commonPath
);
if (!mainRepository) {
return;
}
const worktreePicks = async (): Promise<WorktreeDeleteItem[] | QuickPickItem[]> => {
const worktrees = await mainRepository.getWorktrees();
return worktrees.length === 0
? [{ label: l10n.t('$(info) This repository has no worktrees.') }]
: worktrees.map(worktree => new WorktreeDeleteItem(worktree));
};
const placeHolder = l10n.t('Select a worktree to delete');
const choice = await this.pickRef<WorktreeDeleteItem | QuickPickItem>(worktreePicks(), placeHolder);
if (choice instanceof WorktreeDeleteItem) {
await choice.run(mainRepository);
}
}
@command('git.graph.deleteTag', { repository: true })
async deleteTag2(repository: Repository, historyItem?: SourceControlHistoryItem, historyItemRefId?: string): Promise<void> {
const historyItemRef = historyItem?.references?.find(r => r.id === historyItemRefId);