Skip to content

Commit f41136f

Browse files
committed
1 parent 111f670 commit f41136f

3 files changed

Lines changed: 90 additions & 30 deletions

File tree

extensions/git/package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -396,11 +396,11 @@
396396
},
397397
{
398398
"command": "git.clean",
399-
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
399+
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && !gitFreshRepository"
400400
},
401401
{
402402
"command": "git.cleanAll",
403-
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
403+
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && !gitFreshRepository"
404404
},
405405
{
406406
"command": "git.commit",
@@ -631,7 +631,7 @@
631631
{
632632
"command": "git.cleanAll",
633633
"group": "4_stage",
634-
"when": "scmProvider == git"
634+
"when": "scmProvider == git && !gitFreshRepository"
635635
},
636636
{
637637
"command": "git.stashIncludeUntracked",
@@ -689,7 +689,7 @@
689689
},
690690
{
691691
"command": "git.cleanAll",
692-
"when": "scmProvider == git && scmResourceGroup == workingTree",
692+
"when": "scmProvider == git && scmResourceGroup == workingTree && !gitFreshRepository",
693693
"group": "1_modification"
694694
},
695695
{
@@ -699,7 +699,7 @@
699699
},
700700
{
701701
"command": "git.cleanAll",
702-
"when": "scmProvider == git && scmResourceGroup == workingTree",
702+
"when": "scmProvider == git && scmResourceGroup == workingTree && !gitFreshRepository",
703703
"group": "inline"
704704
},
705705
{
@@ -781,12 +781,12 @@
781781
},
782782
{
783783
"command": "git.clean",
784-
"when": "scmProvider == git && scmResourceGroup == workingTree",
784+
"when": "scmProvider == git && scmResourceGroup == workingTree && !gitFreshRepository",
785785
"group": "1_modification"
786786
},
787787
{
788788
"command": "git.clean",
789-
"when": "scmProvider == git && scmResourceGroup == workingTree",
789+
"when": "scmProvider == git && scmResourceGroup == workingTree && !gitFreshRepository",
790790
"group": "inline"
791791
},
792792
{

extensions/git/src/repository.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
'use strict';
77

8-
import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType } from 'vscode';
8+
import { commands, Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType } from 'vscode';
99
import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType, GitError, Submodule, DiffOptions } from './git';
1010
import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent } from './util';
1111
import { memoize, throttle, debounce } from './decorators';
@@ -1041,13 +1041,9 @@ export class Repository implements Disposable {
10411041

10421042
this._sourceControl.count = count;
10431043

1044-
// set context key
1045-
let stateContextKey = '';
1046-
1047-
switch (this.state) {
1048-
case RepositoryState.Idle: stateContextKey = 'idle'; break;
1049-
case RepositoryState.Disposed: stateContextKey = 'norepo'; break;
1050-
}
1044+
// Disable `Discard All Changes` for "fresh" repositories
1045+
// https://github.com/Microsoft/vscode/issues/43066
1046+
commands.executeCommand('setContext', 'gitFreshRepository', !this._HEAD || !this._HEAD.commit);
10511047

10521048
this._onDidChangeStatus.fire();
10531049
}

src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts

Lines changed: 79 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import { fillInActions, ContextAwareMenuItemActionItem } from 'vs/platform/actio
3737
import { SCMMenus } from './scmMenus';
3838
import { ActionBar, IActionItemProvider, Separator, ActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
3939
import { IThemeService, LIGHT } from 'vs/platform/theme/common/themeService';
40-
import { isSCMResource } from './scmUtil';
40+
import { isSCMResource, getSCMResourceContextKey } from './scmUtil';
4141
import { attachBadgeStyler, attachInputBoxStyler } from 'vs/platform/theme/common/styler';
4242
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
4343
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
@@ -367,9 +367,11 @@ class ResourceGroupRenderer implements IRenderer<ISCMResourceGroup, ResourceGrou
367367
get templateId(): string { return ResourceGroupRenderer.TEMPLATE_ID; }
368368

369369
constructor(
370-
private scmMenus: SCMMenus,
371370
private actionItemProvider: IActionItemProvider,
372-
private themeService: IThemeService
371+
private themeService: IThemeService,
372+
private contextKeyService: IContextKeyService,
373+
private contextMenuService: IContextMenuService,
374+
private menuService: IMenuService
373375
) { }
374376

375377
renderTemplate(container: HTMLElement): ResourceGroupTemplate {
@@ -396,11 +398,36 @@ class ResourceGroupRenderer implements IRenderer<ISCMResourceGroup, ResourceGrou
396398
template.name.textContent = group.label;
397399
template.actionBar.clear();
398400
template.actionBar.context = group;
399-
template.actionBar.push(this.scmMenus.getResourceGroupActions(group), { icon: true, label: false });
401+
402+
const disposables: IDisposable[] = [];
403+
404+
const contextKeyService = this.contextKeyService.createScoped();
405+
disposables.push(contextKeyService);
406+
407+
contextKeyService.createKey('scmProvider', group.provider.contextValue);
408+
contextKeyService.createKey('scmResourceGroup', getSCMResourceContextKey(group));
409+
410+
const menu = this.menuService.createMenu(MenuId.SCMResourceGroupContext, contextKeyService);
411+
disposables.push(menu);
412+
413+
const updateActions = () => {
414+
const primary: IAction[] = [];
415+
const secondary: IAction[] = [];
416+
const result = { primary, secondary };
417+
fillInActions(menu, { shouldForwardArgs: true }, result, this.contextMenuService, g => /^inline/.test(g));
418+
419+
template.actionBar.clear();
420+
template.actionBar.push(primary, { icon: true, label: false });
421+
};
422+
423+
menu.onDidChange(updateActions, null, disposables);
424+
updateActions();
400425

401426
const updateCount = () => template.count.setCount(group.elements.length);
402-
template.elementDisposable = group.onDidSplice(updateCount);
427+
group.onDidSplice(updateCount, null, disposables);
403428
updateCount();
429+
430+
template.elementDisposable = combinedDisposable(disposables);
404431
}
405432

406433
disposeTemplate(template: ResourceGroupTemplate): void {
@@ -446,12 +473,13 @@ class ResourceRenderer implements IRenderer<ISCMResource, ResourceTemplate> {
446473
get templateId(): string { return ResourceRenderer.TEMPLATE_ID; }
447474

448475
constructor(
449-
private scmMenus: SCMMenus,
450476
private actionItemProvider: IActionItemProvider,
451477
private getSelectedResources: () => ISCMResource[],
452-
@IThemeService private themeService: IThemeService,
453-
@IInstantiationService private instantiationService: IInstantiationService,
454-
@IConfigurationService private configurationService: IConfigurationService
478+
private themeService: IThemeService,
479+
private instantiationService: IInstantiationService,
480+
private contextKeyService: IContextKeyService,
481+
private contextMenuService: IContextMenuService,
482+
private menuService: IMenuService
455483
) { }
456484

457485
renderTemplate(container: HTMLElement): ResourceTemplate {
@@ -483,12 +511,28 @@ class ResourceRenderer implements IRenderer<ISCMResource, ResourceTemplate> {
483511
template.fileLabel.setFile(resource.sourceUri, { fileDecorations: { colors: false, badges: !icon, data: resource.decorations } });
484512
template.actionBar.context = resource;
485513

514+
const disposables: IDisposable[] = [];
515+
516+
const contextKeyService = this.contextKeyService.createScoped();
517+
disposables.push(contextKeyService);
518+
519+
contextKeyService.createKey('scmProvider', resource.resourceGroup.provider.contextValue);
520+
contextKeyService.createKey('scmResourceGroup', getSCMResourceContextKey(resource.resourceGroup));
521+
522+
const menu = this.menuService.createMenu(MenuId.SCMResourceGroupContext, contextKeyService);
523+
disposables.push(menu);
524+
486525
const updateActions = () => {
526+
const primary: IAction[] = [];
527+
const secondary: IAction[] = [];
528+
const result = { primary, secondary };
529+
fillInActions(menu, { shouldForwardArgs: true }, result, this.contextMenuService, g => /^inline/.test(g));
530+
487531
template.actionBar.clear();
488-
template.actionBar.push(this.scmMenus.getResourceActions(resource), { icon: true, label: false });
532+
template.actionBar.push(primary, { icon: true, label: false });
489533
};
490534

491-
template.elementDisposable = this.configurationService.onDidChangeConfiguration(updateActions);
535+
menu.onDidChange(updateActions, null, disposables);
492536
updateActions();
493537

494538
toggleClass(template.name, 'strike-through', resource.decorations.strikeThrough);
@@ -504,6 +548,7 @@ class ResourceRenderer implements IRenderer<ISCMResource, ResourceTemplate> {
504548
}
505549

506550
template.element.setAttribute('data-tooltip', resource.decorations.tooltip);
551+
template.elementDisposable = combinedDisposable(disposables);
507552
}
508553

509554
disposeTemplate(template: ResourceTemplate): void {
@@ -687,6 +732,10 @@ export class RepositoryPanel extends ViewletPanel {
687732
private menus: SCMMenus;
688733
private visibilityDisposables: IDisposable[] = [];
689734

735+
get onDidChangeTitle(): Event<void> {
736+
return this.menus.onDidChangeTitle;
737+
}
738+
690739
constructor(
691740
readonly repository: ISCMRepository,
692741
private viewModel: IViewModel,
@@ -699,7 +748,9 @@ export class RepositoryPanel extends ViewletPanel {
699748
@IWorkbenchEditorService protected editorService: IWorkbenchEditorService,
700749
@IEditorGroupService protected editorGroupService: IEditorGroupService,
701750
@IInstantiationService protected instantiationService: IInstantiationService,
702-
@IConfigurationService protected configurationService: IConfigurationService
751+
@IConfigurationService protected configurationService: IConfigurationService,
752+
@IContextKeyService protected contextKeyService: IContextKeyService,
753+
@IMenuService protected menuService: IMenuService
703754
) {
704755
super(repository.provider.label, {}, keybindingService, contextMenuService);
705756
this.menus = instantiationService.createInstance(SCMMenus, repository.provider);
@@ -811,8 +862,8 @@ export class RepositoryPanel extends ViewletPanel {
811862
const actionItemProvider = (action: IAction) => this.getActionItem(action);
812863

813864
const renderers = [
814-
new ResourceGroupRenderer(this.menus, actionItemProvider, this.themeService),
815-
this.instantiationService.createInstance(ResourceRenderer, this.menus, actionItemProvider, () => this.getSelectedResources()),
865+
new ResourceGroupRenderer(actionItemProvider, this.themeService, this.contextKeyService, this.contextMenuService, this.menuService),
866+
new ResourceRenderer(actionItemProvider, () => this.getSelectedResources(), this.themeService, this.instantiationService, this.contextKeyService, this.contextMenuService, this.menuService)
816867
];
817868

818869
this.list = this.instantiationService.createInstance(WorkbenchList, this.listContainer, delegate, renderers, {
@@ -978,6 +1029,7 @@ export class SCMViewlet extends PanelViewlet implements IViewModel {
9781029
private mainPanelDisposable: IDisposable = EmptyDisposable;
9791030
private _repositories: ISCMRepository[] = [];
9801031
private repositoryPanels: RepositoryPanel[] = [];
1032+
private singleRepositoryPanelTitleActionsDisposable: IDisposable = EmptyDisposable;
9811033
private disposables: IDisposable[] = [];
9821034

9831035
private _onDidSplice = new Emitter<ISpliceEvent<ISCMRepository>>();
@@ -1162,6 +1214,8 @@ export class SCMViewlet extends PanelViewlet implements IViewModel {
11621214
}
11631215

11641216
private onSelectionChange(repositories: ISCMRepository[]): void {
1217+
const wasSingleView = this.isSingleView();
1218+
11651219
// Collect unselected panels
11661220
const panelsToRemove = this.repositoryPanels
11671221
.filter(p => repositories.every(r => p.repository !== r));
@@ -1195,10 +1249,20 @@ export class SCMViewlet extends PanelViewlet implements IViewModel {
11951249
const height = typeof this.height === 'number' ? this.height : 1000;
11961250
const mainPanelHeight = this.getPanelSize(this.mainPanel);
11971251
const size = (height - mainPanelHeight) / repositories.length;
1198-
11991252
for (const panel of this.repositoryPanels) {
12001253
this.resizePanel(panel, size);
12011254
}
1255+
1256+
// React to menu changes for single view mode
1257+
if (wasSingleView !== this.isSingleView()) {
1258+
this.singleRepositoryPanelTitleActionsDisposable.dispose();
1259+
1260+
if (this.isSingleView()) {
1261+
this.singleRepositoryPanelTitleActionsDisposable = this.repositoryPanels[0].onDidChangeTitle(this.updateTitleArea, this);
1262+
}
1263+
1264+
this.updateTitleArea();
1265+
}
12021266
}
12031267

12041268
protected isSingleView(): boolean {

0 commit comments

Comments
 (0)