/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { IPath, win32, posix } from 'vs/base/common/path'; import { OperatingSystem, OS } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; export const IPathService = createDecorator('path'); /** * Provides access to path related properties that will match the * environment. If the environment is connected to a remote, the * path properties will match that of the remotes operating system. */ export interface IPathService { readonly _serviceBrand: undefined; /** * The correct path library to use for the target environment. If * the environment is connected to a remote, this will be the * path library of the remote file system. Otherwise it will be * the local file system's path library depending on the OS. */ readonly path: Promise; /** * Converts the given path to a file URI to use for the target * environment. If the environment is connected to a remote, it * will use the path separators according to the remote file * system. Otherwise it will use the local file system's path * separators. */ fileURI(path: string): Promise; /** * Resolves the user-home directory for the target environment. * If the envrionment is connected to a remote, this will be the * remote's user home directory, otherwise the local one unless * `preferLocal` is set to `true`. */ userHome(options?: { preferLocal: boolean }): Promise; /** * @deprecated use `userHome` instead. */ readonly resolvedUserHome: URI | undefined; } export abstract class AbstractPathService implements IPathService { declare readonly _serviceBrand: undefined; private resolveOS: Promise; private resolveUserHome: Promise; private maybeUnresolvedUserHome: URI | undefined; constructor( private localUserHome: URI, @IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService ) { // OS this.resolveOS = (async () => { const env = await this.remoteAgentService.getEnvironment(); return env?.os || OS; })(); // User Home this.resolveUserHome = (async () => { const env = await this.remoteAgentService.getEnvironment(); const userHome = this.maybeUnresolvedUserHome = env?.userHome || localUserHome; return userHome; })(); } async userHome(options?: { preferLocal: boolean }): Promise { return options?.preferLocal ? this.localUserHome : this.resolveUserHome; } get resolvedUserHome(): URI | undefined { return this.maybeUnresolvedUserHome; } get path(): Promise { return this.resolveOS.then(os => { return os === OperatingSystem.Windows ? win32 : posix; }); } async fileURI(_path: string): Promise { let authority = ''; // normalize to fwd-slashes on windows, // on other systems bwd-slashes are valid // filename character, eg /f\oo/ba\r.txt const os = await this.resolveOS; if (os === OperatingSystem.Windows) { _path = _path.replace(/\\/g, '/'); } // check for authority as used in UNC shares // or use the path as given if (_path[0] === '/' && _path[1] === '/') { const idx = _path.indexOf('/', 2); if (idx === -1) { authority = _path.substring(2); _path = '/'; } else { authority = _path.substring(2, idx); _path = _path.substring(idx) || '/'; } } // return new _URI('file', authority, path, '', ''); return URI.from({ scheme: 'file', authority, path: _path, query: '', fragment: '' }); } }