Skip to content

Commit dc6e6da

Browse files
author
Benjamin Pasero
committed
uris - use biased version in a few selected places in electron-main
1 parent dbe4f5c commit dc6e6da

9 files changed

Lines changed: 61 additions & 42 deletions

File tree

src/vs/platform/backup/electron-main/backupMainService.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ import { IFilesConfiguration, HotExitConfiguration } from 'vs/platform/files/com
1717
import { ILogService } from 'vs/platform/log/common/log';
1818
import { IWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
1919
import { URI } from 'vs/base/common/uri';
20-
import { isEqual as areResourcesEquals, getComparisonKey } from 'vs/base/common/resources';
2120
import { isEqual } from 'vs/base/common/extpath';
2221
import { Schemas } from 'vs/base/common/network';
22+
import { fileUriComparer } from 'vs/platform/windows/node/window';
2323

2424
export class BackupMainService implements IBackupMainService {
2525

@@ -32,6 +32,12 @@ export class BackupMainService implements IBackupMainService {
3232
private folders: URI[] = [];
3333
private emptyWindows: IEmptyWindowBackupInfo[] = [];
3434

35+
// Comparers for paths and resources that will
36+
// - ignore path casing on Windows/macOS
37+
// - respect path casing on Linux
38+
private readonly backupUriComparer = fileUriComparer;
39+
private readonly backupPathComparer = { isEqual: (pathA: string, pathB: string) => isEqual(pathA, pathB, !platform.isLinux) };
40+
3541
constructor(
3642
@IEnvironmentService environmentService: INativeEnvironmentService,
3743
@IConfigurationService private readonly configurationService: IConfigurationService,
@@ -196,7 +202,7 @@ export class BackupMainService implements IBackupMainService {
196202
}
197203

198204
registerFolderBackupSync(folderUri: URI): string {
199-
if (!this.folders.some(folder => areResourcesEquals(folderUri, folder))) {
205+
if (!this.folders.some(folder => this.backupUriComparer.isEqual(folderUri, folder))) {
200206
this.folders.push(folderUri);
201207
this.saveSync();
202208
}
@@ -205,7 +211,7 @@ export class BackupMainService implements IBackupMainService {
205211
}
206212

207213
unregisterFolderBackupSync(folderUri: URI): void {
208-
const index = this.folders.findIndex(folder => areResourcesEquals(folderUri, folder));
214+
const index = this.folders.findIndex(folder => this.backupUriComparer.isEqual(folderUri, folder));
209215
if (index !== -1) {
210216
this.folders.splice(index, 1);
211217
this.saveSync();
@@ -216,7 +222,7 @@ export class BackupMainService implements IBackupMainService {
216222

217223
// Generate a new folder if this is a new empty workspace
218224
const backupFolder = backupFolderCandidate || this.getRandomEmptyWindowId();
219-
if (!this.emptyWindows.some(emptyWindow => !!emptyWindow.backupFolder && isEqual(emptyWindow.backupFolder, backupFolder, !platform.isLinux))) {
225+
if (!this.emptyWindows.some(emptyWindow => !!emptyWindow.backupFolder && this.backupPathComparer.isEqual(emptyWindow.backupFolder, backupFolder))) {
220226
this.emptyWindows.push({ backupFolder, remoteAuthority });
221227
this.saveSync();
222228
}
@@ -225,7 +231,7 @@ export class BackupMainService implements IBackupMainService {
225231
}
226232

227233
unregisterEmptyWindowBackupSync(backupFolder: string): void {
228-
const index = this.emptyWindows.findIndex(emptyWindow => !!emptyWindow.backupFolder && isEqual(emptyWindow.backupFolder, backupFolder, !platform.isLinux));
234+
const index = this.emptyWindows.findIndex(emptyWindow => !!emptyWindow.backupFolder && this.backupPathComparer.isEqual(emptyWindow.backupFolder, backupFolder));
229235
if (index !== -1) {
230236
this.emptyWindows.splice(index, 1);
231237
this.saveSync();
@@ -282,7 +288,7 @@ export class BackupMainService implements IBackupMainService {
282288
const result: URI[] = [];
283289
const seenIds: Set<string> = new Set();
284290
for (let folderURI of folderWorkspaces) {
285-
const key = getComparisonKey(folderURI);
291+
const key = this.backupUriComparer.getComparisonKey(folderURI);
286292
if (!seenIds.has(key)) {
287293
seenIds.add(key);
288294

@@ -350,7 +356,7 @@ export class BackupMainService implements IBackupMainService {
350356

351357
// New empty window backup
352358
let newBackupFolder = this.getRandomEmptyWindowId();
353-
while (this.emptyWindows.some(emptyWindow => !!emptyWindow.backupFolder && isEqual(emptyWindow.backupFolder, newBackupFolder, platform.isLinux))) {
359+
while (this.emptyWindows.some(emptyWindow => !!emptyWindow.backupFolder && this.backupPathComparer.isEqual(emptyWindow.backupFolder, newBackupFolder))) {
354360
newBackupFolder = this.getRandomEmptyWindowId();
355361
}
356362

@@ -371,7 +377,7 @@ export class BackupMainService implements IBackupMainService {
371377

372378
// New empty window backup
373379
let newBackupFolder = this.getRandomEmptyWindowId();
374-
while (this.emptyWindows.some(emptyWindow => !!emptyWindow.backupFolder && isEqual(emptyWindow.backupFolder, newBackupFolder, platform.isLinux))) {
380+
while (this.emptyWindows.some(emptyWindow => !!emptyWindow.backupFolder && this.backupPathComparer.isEqual(emptyWindow.backupFolder, newBackupFolder))) {
375381
newBackupFolder = this.getRandomEmptyWindowId();
376382
}
377383

src/vs/platform/windows/electron-main/windowsMainService.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMai
2020
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
2121
import { ILogService } from 'vs/platform/log/common/log';
2222
import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest } from 'vs/platform/windows/common/windows';
23-
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri, INativeWindowConfiguration, OpenContext, IPathsToWaitFor } from 'vs/platform/windows/node/window';
23+
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri, INativeWindowConfiguration, OpenContext, IPathsToWaitFor, fileUriComparer } from 'vs/platform/windows/node/window';
2424
import { Emitter } from 'vs/base/common/event';
2525
import product from 'vs/platform/product/common/product';
2626
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode, IOpenEmptyConfiguration } from 'vs/platform/windows/electron-main/windows';
@@ -30,7 +30,7 @@ import { IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, hasWorkspaceFi
3030
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
3131
import { Schemas } from 'vs/base/common/network';
3232
import { URI } from 'vs/base/common/uri';
33-
import { getComparisonKey, isEqual, normalizePath, originalFSPath, removeTrailingPathSeparator } from 'vs/base/common/resources';
33+
import { normalizePath, originalFSPath, removeTrailingPathSeparator } from 'vs/base/common/resources';
3434
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
3535
import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/platform/windows/electron-main/windowsStateStorage';
3636
import { getWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
@@ -365,7 +365,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
365365
else if (!win.isExtensionDevelopmentHost && (!!win.openedWorkspace || !!win.openedFolderUri)) {
366366
this.windowsState.openedWindows.forEach(o => {
367367
const sameWorkspace = win.openedWorkspace && o.workspace && o.workspace.id === win.openedWorkspace.id;
368-
const sameFolder = win.openedFolderUri && o.folderUri && isEqual(o.folderUri, win.openedFolderUri);
368+
const sameFolder = win.openedFolderUri && o.folderUri && fileUriComparer.isEqual(o.folderUri, win.openedFolderUri);
369369

370370
if (sameWorkspace || sameFolder) {
371371
o.uiState = state.uiState;
@@ -673,7 +673,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
673673
}
674674

675675
// Handle folders to open (instructed and to restore)
676-
const allFoldersToOpen = arrays.distinct(foldersToOpen, folder => getComparisonKey(folder.folderUri)); // prevent duplicates
676+
const allFoldersToOpen = arrays.distinct(foldersToOpen, folder => fileUriComparer.getComparisonKey(folder.folderUri)); // prevent duplicates
677677
if (allFoldersToOpen.length > 0) {
678678

679679
// Check for existing instances
@@ -696,7 +696,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
696696
// Open remaining ones
697697
allFoldersToOpen.forEach(folderToOpen => {
698698

699-
if (windowsOnFolderPath.some(win => isEqual(win.openedFolderUri, folderToOpen.folderUri))) {
699+
if (windowsOnFolderPath.some(win => fileUriComparer.isEqual(win.openedFolderUri, folderToOpen.folderUri))) {
700700
return; // ignore folders that are already open
701701
}
702702

@@ -1526,7 +1526,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
15261526

15271527
// Known Folder - load from stored settings
15281528
if (configuration.folderUri) {
1529-
const stateForFolder = this.windowsState.openedWindows.filter(o => o.folderUri && isEqual(o.folderUri, configuration.folderUri)).map(o => o.uiState);
1529+
const stateForFolder = this.windowsState.openedWindows.filter(o => o.folderUri && fileUriComparer.isEqual(o.folderUri, configuration.folderUri)).map(o => o.uiState);
15301530
if (stateForFolder.length) {
15311531
return stateForFolder[0];
15321532
}

src/vs/platform/windows/node/window.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import { URI, UriComponents } from 'vs/base/common/uri';
88
import * as platform from 'vs/base/common/platform';
99
import * as extpath from 'vs/base/common/extpath';
1010
import { IWorkspaceIdentifier, IResolvedWorkspace, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
11-
import { isEqual, isEqualOrParent } from 'vs/base/common/resources';
11+
import { ExtUri } from 'vs/base/common/resources';
1212
import { LogLevel } from 'vs/platform/log/common/log';
1313
import { ExportData } from 'vs/base/common/performance';
1414
import { ParsedArgs } from 'vs/platform/environment/node/argv';
15+
import { Schemas } from 'vs/base/common/network';
1516

1617
export const enum OpenContext {
1718

@@ -115,6 +116,11 @@ export function findBestWindowOrFolderForFile<W extends IWindowContext>({ window
115116
return !newWindow ? getLastActiveWindow(windows) : undefined;
116117
}
117118

119+
// Comparers for resources that will
120+
// - ignore path casing on Windows/macOS
121+
// - respect path casing on Linux
122+
export const fileUriComparer = new ExtUri(uri => uri && uri.scheme === Schemas.file ? !platform.isLinux : false);
123+
118124
function findWindowOnFilePath<W extends IWindowContext>(windows: W[], fileUri: URI, localWorkspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null): W | null {
119125

120126
// First check for windows with workspaces that have a parent folder of the provided path opened
@@ -124,20 +130,20 @@ function findWindowOnFilePath<W extends IWindowContext>(windows: W[], fileUri: U
124130
const resolvedWorkspace = localWorkspaceResolver(workspace);
125131
if (resolvedWorkspace) {
126132
// workspace could be resolved: It's in the local file system
127-
if (resolvedWorkspace.folders.some(folder => isEqualOrParent(fileUri, folder.uri))) {
133+
if (resolvedWorkspace.folders.some(folder => fileUriComparer.isEqualOrParent(fileUri, folder.uri))) {
128134
return window;
129135
}
130136
} else {
131137
// use the config path instead
132-
if (isEqualOrParent(fileUri, workspace.configPath)) {
138+
if (fileUriComparer.isEqualOrParent(fileUri, workspace.configPath)) {
133139
return window;
134140
}
135141
}
136142
}
137143
}
138144

139145
// Then go with single folder windows that are parent of the provided file path
140-
const singleFolderWindowsOnFilePath = windows.filter(window => window.openedFolderUri && isEqualOrParent(fileUri, window.openedFolderUri));
146+
const singleFolderWindowsOnFilePath = windows.filter(window => window.openedFolderUri && fileUriComparer.isEqualOrParent(fileUri, window.openedFolderUri));
141147
if (singleFolderWindowsOnFilePath.length) {
142148
return singleFolderWindowsOnFilePath.sort((a, b) => -(a.openedFolderUri!.path.length - b.openedFolderUri!.path.length))[0];
143149
}
@@ -156,7 +162,7 @@ export function findWindowOnWorkspace<W extends IWindowContext>(windows: W[], wo
156162
for (const window of windows) {
157163
// match on folder
158164
if (isSingleFolderWorkspaceIdentifier(workspace)) {
159-
if (window.openedFolderUri && isEqual(window.openedFolderUri, workspace)) {
165+
if (window.openedFolderUri && fileUriComparer.isEqual(window.openedFolderUri, workspace)) {
160166
return window;
161167
}
162168
}
@@ -195,12 +201,12 @@ export function findWindowOnWorkspaceOrFolderUri<W extends IWindowContext>(windo
195201
}
196202
for (const window of windows) {
197203
// check for workspace config path
198-
if (window.openedWorkspace && isEqual(window.openedWorkspace.configPath, uri)) {
204+
if (window.openedWorkspace && fileUriComparer.isEqual(window.openedWorkspace.configPath, uri)) {
199205
return window;
200206
}
201207

202208
// check for folder path
203-
if (window.openedFolderUri && isEqual(window.openedFolderUri, uri)) {
209+
if (window.openedFolderUri && fileUriComparer.isEqual(window.openedFolderUri, uri)) {
204210
return window;
205211
}
206212
}

src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { isWindows, isMacintosh } from 'vs/base/common/platform';
1414
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IRecentlyOpened, isRecentWorkspace, isRecentFolder, IRecent, isRecentFile, IRecentFolder, IRecentWorkspace, IRecentFile, toStoreData, restoreRecentlyOpened, RecentlyOpenedStorageData } from 'vs/platform/workspaces/common/workspaces';
1515
import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
1616
import { ThrottledDelayer } from 'vs/base/common/async';
17-
import { isEqual as areResourcesEqual, dirname, originalFSPath, basename } from 'vs/base/common/resources';
17+
import { isEqual, dirname, originalFSPath, basename } from 'vs/base/common/resources';
1818
import { URI } from 'vs/base/common/uri';
1919
import { Schemas } from 'vs/base/common/network';
2020
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@@ -152,8 +152,8 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
152152
removeRecentlyOpened(toRemove: URI[]): void {
153153
const keep = (recent: IRecent) => {
154154
const uri = location(recent);
155-
for (const r of toRemove) {
156-
if (areResourcesEqual(r, uri)) {
155+
for (const resource of toRemove) {
156+
if (isEqual(resource, uri)) {
157157
return false;
158158
}
159159
}
@@ -411,9 +411,9 @@ function indexOfWorkspace(arr: IRecent[], candidate: IWorkspaceIdentifier): numb
411411
}
412412

413413
function indexOfFolder(arr: IRecent[], candidate: ISingleFolderWorkspaceIdentifier): number {
414-
return arr.findIndex(folder => isRecentFolder(folder) && areResourcesEqual(folder.folderUri, candidate));
414+
return arr.findIndex(folder => isRecentFolder(folder) && isEqual(folder.folderUri, candidate));
415415
}
416416

417417
function indexOfFile(arr: IRecentFile[], candidate: URI): number {
418-
return arr.findIndex(file => areResourcesEqual(file.fileUri, candidate));
418+
return arr.findIndex(file => isEqual(file.fileUri, candidate));
419419
}

src/vs/platform/workspaces/electron-main/workspacesMainService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { toWorkspaceFolders } from 'vs/platform/workspace/common/workspace';
1818
import { URI } from 'vs/base/common/uri';
1919
import { Schemas } from 'vs/base/common/network';
2020
import { Disposable } from 'vs/base/common/lifecycle';
21-
import { originalFSPath, joinPath, isEqual, basename } from 'vs/base/common/resources';
21+
import { originalFSPath, joinPath, basename } from 'vs/base/common/resources';
2222
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
2323
import { ICodeWindow } from 'vs/platform/windows/electron-main/windows';
2424
import { localize } from 'vs/nls';
@@ -27,7 +27,7 @@ import { MessageBoxOptions, BrowserWindow } from 'electron';
2727
import { withNullAsUndefined } from 'vs/base/common/types';
2828
import { IBackupMainService } from 'vs/platform/backup/electron-main/backup';
2929
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
30-
import { findWindowOnWorkspace } from 'vs/platform/windows/node/window';
30+
import { findWindowOnWorkspace, fileUriComparer } from 'vs/platform/windows/node/window';
3131

3232
export const IWorkspacesMainService = createDecorator<IWorkspacesMainService>('workspacesMainService');
3333

@@ -274,7 +274,7 @@ export class WorkspacesMainService extends Disposable implements IWorkspacesMain
274274
return true;
275275
}
276276

277-
if (window.openedWorkspace && isEqual(window.openedWorkspace.configPath, path)) {
277+
if (window.openedWorkspace && fileUriComparer.isEqual(window.openedWorkspace.configPath, path)) {
278278
return false; // window is already opened on a workspace with that path
279279
}
280280

src/vs/workbench/contrib/files/browser/fileCommands.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile
4343
import { openEditorWith } from 'vs/workbench/contrib/files/common/openWith';
4444
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
4545
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
46+
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
4647

4748
// Commands
4849

@@ -509,10 +510,10 @@ CommandsRegistry.registerCommand({
509510
handler: (accessor, resource: URI | object) => {
510511
const workspaceEditingService = accessor.get(IWorkspaceEditingService);
511512
const contextService = accessor.get(IWorkspaceContextService);
513+
const uriIdentityService = accessor.get(IUriIdentityService);
512514
const workspace = contextService.getWorkspace();
513-
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService), accessor.get(IExplorerService)).filter(r =>
514-
// Need to verify resources are workspaces since multi selection can trigger this command on some non workspace resources
515-
workspace.folders.some(f => isEqual(f.uri, r))
515+
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService), accessor.get(IExplorerService)).filter(resource =>
516+
workspace.folders.some(folder => uriIdentityService.extUri.isEqual(folder.uri, resource)) // Need to verify resources are workspaces since multi selection can trigger this command on some non workspace resources
516517
);
517518

518519
return workspaceEditingService.removeFolders(resources);

0 commit comments

Comments
 (0)