diff --git a/extensions/git/package.json b/extensions/git/package.json index c0768e78a54..ce02cce9f57 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -1335,6 +1335,14 @@ "command": "git.deleteWorktree", "when": "false" }, + { + "command": "git.openWorktree", + "when": "false" + }, + { + "command": "git.openWorktreeInNewWindow", + "when": "false" + }, { "command": "git.deleteWorktreeFromPalette", "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount > 1" @@ -1690,13 +1698,13 @@ }, { "command": "git.openWorktree", - "group": "worktree@1", - "when": "scmProvider == git && gitOpenRepositoryCount > 1" + "group": "1_worktree@1", + "when": "scmProvider == git && scmProviderContext == worktree" }, { "command": "git.openWorktreeInNewWindow", - "group": "worktree@2", - "when": "scmProvider == git && gitOpenRepositoryCount > 1" + "group": "1_worktree@2", + "when": "scmProvider == git && scmProviderContext == worktree" } ], "scm/resourceGroup/context": [ diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 7d0790d6e83..ecb12842234 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -3482,9 +3482,8 @@ export class CommandCenter { } @command('git.openWorktree', { repository: true }) - async openWorktreeInCurrentWindow(repository: Repository, ...args: SourceControl[]): Promise { - // If multiple repositories are selected, no action is taken - if (args.length > 0) { + async openWorktreeInCurrentWindow(repository: Repository): Promise { + if (!repository) { return; } @@ -3493,9 +3492,8 @@ export class CommandCenter { } @command('git.openWorktreeInNewWindow', { repository: true }) - async openWorktreeInNewWindow(repository: Repository, ...args: SourceControl[]): Promise { - // If multiple repositories are selected, no action is taken - if (args.length > 0) { + async openWorktreeInNewWindow(repository: Repository): Promise { + if (!repository) { return; } diff --git a/src/vs/workbench/contrib/scm/browser/menus.ts b/src/vs/workbench/contrib/scm/browser/menus.ts index cf72a0315a7..59a953b6dfa 100644 --- a/src/vs/workbench/contrib/scm/browser/menus.ts +++ b/src/vs/workbench/contrib/scm/browser/menus.ts @@ -180,18 +180,11 @@ export class SCMRepositoryMenus implements ISCMRepositoryMenus, IDisposable { private genericRepositoryMenu: IMenu | undefined; private contextualRepositoryMenus: Map | undefined; + private genericRepositoryContextMenu: IMenu | undefined; + private contextualRepositoryContextMenus: Map | undefined; + private readonly resourceGroupMenusItems = new Map(); - private _repositoryContextMenu: IMenu | undefined; - get repositoryContextMenu(): IMenu { - if (!this._repositoryContextMenu) { - this._repositoryContextMenu = this.menuService.createMenu(MenuId.SCMSourceControl, this.contextKeyService); - this.disposables.add(this._repositoryContextMenu); - } - - return this._repositoryContextMenu; - } - private readonly disposables = new DisposableStore(); constructor( @@ -247,6 +240,38 @@ export class SCMRepositoryMenus implements ISCMRepositoryMenus, IDisposable { return item.menu; } + getRepositoryContextMenu(repository: ISCMRepository): IMenu { + const contextValue = repository.provider.contextValue.get(); + if (typeof contextValue === 'undefined') { + if (!this.genericRepositoryContextMenu) { + this.genericRepositoryContextMenu = this.menuService.createMenu(MenuId.SCMSourceControl, this.contextKeyService); + } + + return this.genericRepositoryContextMenu; + } + + if (!this.contextualRepositoryContextMenus) { + this.contextualRepositoryContextMenus = new Map(); + } + + let item = this.contextualRepositoryContextMenus.get(contextValue); + + if (!item) { + const contextKeyService = this.contextKeyService.createOverlay([['scmProviderContext', contextValue]]); + const menu = this.menuService.createMenu(MenuId.SCMSourceControl, contextKeyService); + + item = { + menu, dispose() { + menu.dispose(); + } + }; + + this.contextualRepositoryContextMenus.set(contextValue, item); + } + + return item.menu; + } + getResourceGroupMenu(group: ISCMResourceGroup): IMenu { return this.getOrCreateResourceGroupMenusItem(group).getResourceGroupMenu(group); } diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index 8cb2bb41254..c45fec90357 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -557,7 +557,7 @@ CommandsRegistry.registerCommand('scm.setActiveProvider', async (accessor) => { }); MenuRegistry.appendMenuItem(MenuId.SCMSourceControl, { - group: '100_end', + group: '99_terminal', command: { id: 'scm.openInTerminal', title: localize('open in external terminal', "Open in External Terminal") @@ -571,7 +571,7 @@ MenuRegistry.appendMenuItem(MenuId.SCMSourceControl, { }); MenuRegistry.appendMenuItem(MenuId.SCMSourceControl, { - group: '100_end', + group: '99_terminal', command: { id: 'scm.openInIntegratedTerminal', title: localize('open in integrated terminal', "Open in Integrated Terminal") diff --git a/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts index 0487ee67b8f..58a8ef347ff 100644 --- a/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts @@ -241,7 +241,7 @@ export class SCMRepositoriesViewPane extends ViewPane { const provider = e.element.provider; const menus = this.scmViewService.menus.getRepositoryMenus(provider); - const menu = menus.repositoryContextMenu; + const menu = menus.getRepositoryContextMenu(e.element); const actions = collectContextMenuActions(menu); const disposables = new DisposableStore(); diff --git a/src/vs/workbench/contrib/scm/browser/scmRepositoryRenderer.ts b/src/vs/workbench/contrib/scm/browser/scmRepositoryRenderer.ts index 06afb199824..c0fd32831ac 100644 --- a/src/vs/workbench/contrib/scm/browser/scmRepositoryRenderer.ts +++ b/src/vs/workbench/contrib/scm/browser/scmRepositoryRenderer.ts @@ -37,8 +37,14 @@ export class RepositoryActionRunner extends ActionRunner { return super.runAction(action, context); } + const actionContext = [context]; + + // If the selection contains the repository, add the + // other selected repositories to the action context const selection = this.getSelectedRepositories().map(r => r.provider); - const actionContext = selection.some(s => s === context) ? selection : [context]; + if (selection.some(s => s === context)) { + actionContext.push(...selection.filter(s => s !== context)); + } await action.run(...actionContext); } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 9562568a45d..f19473963a8 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -2625,7 +2625,7 @@ export class SCMViewPane extends ViewPane { if (isSCMRepository(element)) { const menus = this.scmViewService.menus.getRepositoryMenus(element.provider); - const menu = menus.repositoryContextMenu; + const menu = menus.getRepositoryContextMenu(element); context = element.provider; actionRunner = new RepositoryActionRunner(() => this.getSelectedRepositories()); disposables.add(actionRunner); diff --git a/src/vs/workbench/contrib/scm/common/scm.ts b/src/vs/workbench/contrib/scm/common/scm.ts index b30dbc610ea..638f694dce7 100644 --- a/src/vs/workbench/contrib/scm/common/scm.ts +++ b/src/vs/workbench/contrib/scm/common/scm.ts @@ -193,8 +193,8 @@ export interface ISCMTitleMenu { export interface ISCMRepositoryMenus { readonly titleMenu: ISCMTitleMenu; - readonly repositoryContextMenu: IMenu; getRepositoryMenu(repository: ISCMRepository): IMenu; + getRepositoryContextMenu(repository: ISCMRepository): IMenu; getResourceGroupMenu(group: ISCMResourceGroup): IMenu; getResourceMenu(resource: ISCMResource): IMenu; getResourceFolderMenu(group: ISCMResourceGroup): IMenu;