Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79 (#14050)

* Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79

* Fix breaks

* Extension management fixes

* Fix breaks in windows bundling

* Fix/skip failing tests

* Update distro

* Add clear to nuget.config

* Add hygiene task

* Bump distro

* Fix hygiene issue

* Add build to hygiene exclusion

* Update distro

* Update hygiene

* Hygiene exclusions

* Update tsconfig

* Bump distro for server breaks

* Update build config

* Update darwin path

* Add done calls to notebook tests

* Skip failing tests

* Disable smoke tests
This commit is contained in:
Karl Burtram
2021-02-09 16:15:05 -08:00
committed by GitHub
parent 6f192f9af5
commit ce612a3d96
1929 changed files with 68012 additions and 34564 deletions

View File

@@ -23,6 +23,7 @@ function shouldSpawnCliProcess(argv: NativeParsedArgs): boolean {
return !!argv['install-source']
|| !!argv['list-extensions']
|| !!argv['install-extension']
|| !!argv['install-builtin-extension']
|| !!argv['uninstall-extension']
|| !!argv['locate-extension']
|| !!argv['telemetry'];
@@ -95,9 +96,9 @@ export async function main(argv: string[]): Promise<any> {
// On Windows we use a different strategy of saving the file
// by first truncating the file and then writing with r+ mode.
// This helps to save hidden files on Windows
// (see https://github.com/Microsoft/vscode/issues/931) and
// (see https://github.com/microsoft/vscode/issues/931) and
// prevent removing alternate data streams
// (see https://github.com/Microsoft/vscode/issues/6363)
// (see https://github.com/microsoft/vscode/issues/6363)
fs.truncateSync(target, 0);
writeFileSync(target, data, { flag: 'r+' });
} else {
@@ -122,10 +123,6 @@ export async function main(argv: string[]): Promise<any> {
'ELECTRON_NO_ATTACH_CONSOLE': '1'
};
if (args['force-user-env']) {
env['VSCODE_FORCE_USER_ENV'] = '1';
}
delete env['ELECTRON_RUN_AS_NODE'];
const processCallbacks: ((child: ChildProcess) => Promise<void>)[] = [];
@@ -138,7 +135,7 @@ export async function main(argv: string[]): Promise<any> {
child.stdout!.on('data', (data: Buffer) => console.log(data.toString('utf8').trim()));
child.stderr!.on('data', (data: Buffer) => console.log(data.toString('utf8').trim()));
await new Promise<void>(c => child.once('exit', () => c()));
await new Promise<void>(resolve => child.once('exit', () => resolve()));
});
}
@@ -154,43 +151,41 @@ export async function main(argv: string[]): Promise<any> {
// Read from stdin: we require a single "-" argument to be passed in order to start reading from
// stdin. We do this because there is no reliable way to find out if data is piped to stdin. Just
// checking for stdin being connected to a TTY is not enough (https://github.com/Microsoft/vscode/issues/40351)
// checking for stdin being connected to a TTY is not enough (https://github.com/microsoft/vscode/issues/40351)
if (args._.length === 0) {
if (hasReadStdinArg) {
stdinFilePath = getStdinFilePath();
if (hasReadStdinArg) {
stdinFilePath = getStdinFilePath();
// returns a file path where stdin input is written into (write in progress).
try {
readFromStdin(stdinFilePath, !!verbose); // throws error if file can not be written
// returns a file path where stdin input is written into (write in progress).
try {
readFromStdin(stdinFilePath, !!verbose); // throws error if file can not be written
// Make sure to open tmp file
addArg(argv, stdinFilePath);
// Make sure to open tmp file
addArg(argv, stdinFilePath);
// Enable --wait to get all data and ignore adding this to history
addArg(argv, '--wait');
addArg(argv, '--skip-add-to-recently-opened');
args.wait = true;
// Enable --wait to get all data and ignore adding this to history
addArg(argv, '--wait');
addArg(argv, '--skip-add-to-recently-opened');
args.wait = true;
console.log(`Reading from stdin via: ${stdinFilePath}`);
} catch (e) {
console.log(`Failed to create file to read via stdin: ${e.toString()}`);
stdinFilePath = undefined;
}
} else {
// If the user pipes data via stdin but forgot to add the "-" argument, help by printing a message
// if we detect that data flows into via stdin after a certain timeout.
processCallbacks.push(_ => stdinDataListener(1000).then(dataReceived => {
if (dataReceived) {
if (isWindows) {
console.log(`Run with '${product.applicationName} -' to read output from another program (e.g. 'echo Hello World | ${product.applicationName} -').`);
} else {
console.log(`Run with '${product.applicationName} -' to read from stdin (e.g. 'ps aux | grep code | ${product.applicationName} -').`);
}
}
}));
console.log(`Reading from stdin via: ${stdinFilePath}`);
} catch (e) {
console.log(`Failed to create file to read via stdin: ${e.toString()}`);
stdinFilePath = undefined;
}
} else {
// If the user pipes data via stdin but forgot to add the "-" argument, help by printing a message
// if we detect that data flows into via stdin after a certain timeout.
processCallbacks.push(_ => stdinDataListener(1000).then(dataReceived => {
if (dataReceived) {
if (isWindows) {
console.log(`Run with '${product.applicationName} -' to read output from another program (e.g. 'echo Hello World | ${product.applicationName} -').`);
} else {
console.log(`Run with '${product.applicationName} -' to read from stdin (e.g. 'ps aux | grep code | ${product.applicationName} -').`);
}
}
}));
}
}
@@ -332,13 +327,13 @@ export async function main(argv: string[]): Promise<any> {
const child = spawn(process.execPath, argv.slice(2), options);
if (args.wait && waitMarkerFilePath) {
return new Promise<void>(c => {
return new Promise<void>(resolve => {
// Complete when process exits
child.once('exit', () => c(undefined));
child.once('exit', () => resolve(undefined));
// Complete when wait marker file is deleted
whenDeleted(waitMarkerFilePath!).then(c, c);
whenDeleted(waitMarkerFilePath!).then(resolve, resolve);
}).then(() => {
// Make sure to delete the tmp stdin file if we have any

View File

@@ -5,6 +5,7 @@
import { localize } from 'vs/nls';
import { raceTimeout } from 'vs/base/common/async';
import * as semver from 'vs/base/common/semver/semver';
import product from 'vs/platform/product/common/product';
import * as path from 'vs/base/common/path';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
@@ -13,8 +14,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { IExtensionManagementService, IExtensionGalleryService, IGalleryExtension, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
import { IExtensionManagementService, IExtensionGalleryService, IGalleryExtension, ILocalExtension, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -30,7 +31,7 @@ import { mkdirp, writeFile } from 'vs/base/node/pfs';
import { getBaseLabel } from 'vs/base/common/labels';
import { IStateService } from 'vs/platform/state/node/state';
import { StateService } from 'vs/platform/state/node/stateService';
import { ILogService, getLogLevel } from 'vs/platform/log/common/log';
import { ILogService, getLogLevel, LogLevel, ConsoleLogService, MultiplexLogService } from 'vs/platform/log/common/log';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { areSameExtensions, adoptToGalleryExtensionId, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { URI } from 'vs/base/common/uri';
@@ -69,14 +70,15 @@ export function getIdAndVersion(id: string): [string, string | undefined] {
return [adoptToGalleryExtensionId(id), undefined];
}
type InstallExtensionInfo = { id: string, version?: string, installOptions: InstallOptions };
export class Main {
constructor(
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IEnvironmentService private readonly environmentService: INativeEnvironmentService,
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
) { }
async run(argv: NativeParsedArgs): Promise<void> {
@@ -84,14 +86,14 @@ export class Main {
await this.setInstallSource(argv['install-source']);
} else if (argv['list-extensions']) {
await this.listExtensions(!!argv['show-versions'], argv['category']);
} else if (argv['install-extension']) {
await this.installExtensions(argv['install-extension'], !!argv['force'], !!argv['do-not-sync']);
} else if (argv['install-extension'] || argv['install-builtin-extension']) {
await this.installExtensions(argv['install-extension'] || [], argv['install-builtin-extension'] || [], !!argv['do-not-sync'], !!argv['force']);
} else if (argv['uninstall-extension']) {
await this.uninstallExtension(argv['uninstall-extension']);
await this.uninstallExtension(argv['uninstall-extension'], !!argv['force']);
} else if (argv['locate-extension']) {
await this.locateExtension(argv['locate-extension']);
} else if (argv['telemetry']) {
console.log(buildTelemetryMessage(this.environmentService.appRoot, this.environmentService.extensionsPath ? this.environmentService.extensionsPath : undefined));
console.log(buildTelemetryMessage(this.environmentService.appRoot, this.environmentService.extensionsPath));
}
}
@@ -124,88 +126,164 @@ export class Main {
extensions.forEach(e => console.log(getId(e.manifest, showVersions)));
}
private async installExtensions(extensions: string[], force: boolean, doNotSync: boolean): Promise<void> {
async installExtensions(extensions: string[], builtinExtensionIds: string[], isMachineScoped: boolean, force: boolean): Promise<void> {
const failed: string[] = [];
const installedExtensionsManifests: IExtensionManifest[] = [];
if (extensions.length) {
console.log(localize('installingExtensions', "Installing extensions..."));
}
for (const extension of extensions) {
try {
const manifest = await this.installExtension(extension, force, doNotSync);
if (manifest) {
installedExtensionsManifests.push(manifest);
const installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
const checkIfNotInstalled = (id: string, version?: string): boolean => {
const installedExtension = installed.find(i => areSameExtensions(i.identifier, { id }));
if (installedExtension) {
if (!version && !force) {
console.log(localize('alreadyInstalled-checkAndUpdate', "Extension '{0}' v{1} is already installed. Use '--force' option to update to latest version or provide '@<version>' to install a specific version, for example: '{2}@1.2.3'.", id, installedExtension.manifest.version, id));
return false;
}
if (version && installedExtension.manifest.version === version) {
console.log(localize('alreadyInstalled', "Extension '{0}' is already installed.", `${id}@${version}`));
return false;
}
}
return true;
};
const vsixs: string[] = [];
const installExtensionInfos: InstallExtensionInfo[] = [];
for (const extension of extensions) {
if (/\.vsix$/i.test(extension)) {
vsixs.push(extension);
} else {
const [id, version] = getIdAndVersion(extension);
if (checkIfNotInstalled(id, version)) {
installExtensionInfos.push({ id, version, installOptions: { isBuiltin: false, isMachineScoped } });
}
} catch (err) {
console.error(err.message || err.stack || err);
failed.push(extension);
}
}
for (const extension of builtinExtensionIds) {
const [id, version] = getIdAndVersion(extension);
if (checkIfNotInstalled(id, version)) {
installExtensionInfos.push({ id, version, installOptions: { isBuiltin: true, isMachineScoped: false } });
}
}
if (vsixs.length) {
await Promise.all(vsixs.map(async vsix => {
try {
const manifest = await this.installVSIX(vsix, force);
if (manifest) {
installedExtensionsManifests.push(manifest);
}
} catch (err) {
console.error(err.message || err.stack || err);
failed.push(vsix);
}
}));
}
if (installExtensionInfos.length) {
const galleryExtensions = await this.getGalleryExtensions(installExtensionInfos);
await Promise.all(installExtensionInfos.map(async extensionInfo => {
const gallery = galleryExtensions.get(extensionInfo.id.toLowerCase());
if (gallery) {
try {
const manifest = await this.installFromGallery(extensionInfo, gallery, installed, force);
if (manifest) {
installedExtensionsManifests.push(manifest);
}
} catch (err) {
console.error(err.message || err.stack || err);
failed.push(extensionInfo.id);
}
} else {
console.error(`${notFound(extensionInfo.version ? `${extensionInfo.id}@${extensionInfo.version}` : extensionInfo.id)}\n${useId}`);
failed.push(extensionInfo.id);
}
}));
}
if (installedExtensionsManifests.some(manifest => isLanguagePackExtension(manifest))) {
await this.updateLocalizationsCache();
}
return failed.length ? Promise.reject(localize('installation failed', "Failed Installing Extensions: {0}", failed.join(', '))) : Promise.resolve();
if (failed.length) {
throw new Error(localize('installation failed', "Failed Installing Extensions: {0}", failed.join(', ')));
}
}
private async installExtension(extension: string, force: boolean, doNotSync: boolean): Promise<IExtensionManifest | null> {
if (/\.vsix$/i.test(extension)) {
extension = path.isAbsolute(extension) ? extension : path.join(process.cwd(), extension);
const manifest = await getManifest(extension);
const valid = await this.validate(manifest, force);
if (valid) {
return this.extensionManagementService.install(URI.file(extension), doNotSync).then(id => {
console.log(localize('successVsixInstall', "Extension '{0}' was successfully installed.", getBaseLabel(extension)));
return manifest;
}, error => {
if (isPromiseCanceledError(error)) {
console.log(localize('cancelVsixInstall', "Cancelled installing extension '{0}'.", getBaseLabel(extension)));
return null;
} else {
return Promise.reject(error);
}
});
private async installVSIX(vsix: string, force: boolean): Promise<IExtensionManifest | null> {
vsix = path.isAbsolute(vsix) ? vsix : path.join(process.cwd(), vsix);
const manifest = await getManifest(vsix);
const valid = await this.validate(manifest, force);
if (valid) {
try {
await this.extensionManagementService.install(URI.file(vsix));
console.log(localize('successVsixInstall', "Extension '{0}' was successfully installed.", getBaseLabel(vsix)));
return manifest;
} catch (error) {
if (isPromiseCanceledError(error)) {
console.log(localize('cancelVsixInstall', "Cancelled installing extension '{0}'.", getBaseLabel(vsix)));
return null;
} else {
throw error;
}
}
return null;
}
return null;
}
private async getGalleryExtensions(extensions: InstallExtensionInfo[]): Promise<Map<string, IGalleryExtension>> {
const extensionIds = extensions.filter(({ version }) => version === undefined).map(({ id }) => id);
const extensionsWithIdAndVersion = extensions.filter(({ version }) => version !== undefined);
const galleryExtensions = new Map<string, IGalleryExtension>();
await Promise.all([
(async () => {
const result = await this.extensionGalleryService.getExtensions(extensionIds, CancellationToken.None);
result.forEach(extension => galleryExtensions.set(extension.identifier.id.toLowerCase(), extension));
})(),
Promise.all(extensionsWithIdAndVersion.map(async ({ id, version }) => {
const extension = await this.extensionGalleryService.getCompatibleExtension({ id }, version);
if (extension) {
galleryExtensions.set(extension.identifier.id.toLowerCase(), extension);
}
}))
]);
return galleryExtensions;
}
private async installFromGallery({ id, version, installOptions }: InstallExtensionInfo, galleryExtension: IGalleryExtension, installed: ILocalExtension[], force: boolean): Promise<IExtensionManifest | null> {
const manifest = await this.extensionGalleryService.getManifest(galleryExtension, CancellationToken.None);
const installedExtension = installed.find(e => areSameExtensions(e.identifier, galleryExtension.identifier));
if (installedExtension) {
if (galleryExtension.version === installedExtension.manifest.version) {
console.log(localize('alreadyInstalled', "Extension '{0}' is already installed.", version ? `${id}@${version}` : id));
return null;
}
console.log(localize('updateMessage', "Updating the extension '{0}' to the version {1}", id, galleryExtension.version));
}
const [id, version] = getIdAndVersion(extension);
return this.extensionManagementService.getInstalled(ExtensionType.User)
.then(installed => this.extensionGalleryService.getCompatibleExtension({ id }, version)
.then<IGalleryExtension>(null, err => {
if (err.responseText) {
try {
const response = JSON.parse(err.responseText);
return Promise.reject(response.message);
} catch (e) {
// noop
}
}
return Promise.reject(err);
})
.then(async extension => {
if (!extension) {
return Promise.reject(new Error(`${notFound(version ? `${id}@${version}` : id)}\n${useId}`));
}
const manifest = await this.extensionGalleryService.getManifest(extension, CancellationToken.None);
const [installedExtension] = installed.filter(e => areSameExtensions(e.identifier, { id }));
if (installedExtension) {
if (extension.version === installedExtension.manifest.version) {
console.log(localize('alreadyInstalled', "Extension '{0}' is already installed.", version ? `${id}@${version}` : id));
return Promise.resolve(null);
}
if (!version && !force) {
console.log(localize('forceUpdate', "Extension '{0}' v{1} is already installed, but a newer version {2} is available in the marketplace. Use '--force' option to update to newer version.", id, installedExtension.manifest.version, extension.version));
return Promise.resolve(null);
}
console.log(localize('updateMessage', "Updating the extension '{0}' to the version {1}", id, extension.version));
}
await this.installFromGallery(id, extension, doNotSync);
return manifest;
}));
try {
if (installOptions.isBuiltin) {
console.log(localize('installing builtin ', "Installing builtin extension '{0}' v{1}...", id, galleryExtension.version));
} else {
console.log(localize('installing', "Installing extension '{0}' v{1}...", id, galleryExtension.version));
}
await this.extensionManagementService.installFromGallery(galleryExtension, installOptions);
console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed.", id, galleryExtension.version));
return manifest;
} catch (error) {
if (isPromiseCanceledError(error)) {
console.log(localize('cancelInstall', "Cancelled installing extension '{0}'.", id));
return null;
} else {
throw error;
}
}
}
private async validate(manifest: IExtensionManifest, force: boolean): Promise<boolean> {
@@ -213,8 +291,6 @@ export class Main {
throw new Error('Invalid vsix');
}
const semver = await import('semver-umd');
const extensionIdentifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name) };
const installedExtensions = await this.extensionManagementService.getInstalled(ExtensionType.User);
const newer = installedExtensions.find(local => areSameExtensions(extensionIdentifier, local.identifier) && semver.gt(local.manifest.version, manifest.version));
@@ -227,22 +303,7 @@ export class Main {
return true;
}
private async installFromGallery(id: string, extension: IGalleryExtension, doNotSync: boolean): Promise<void> {
console.log(localize('installing', "Installing extension '{0}' v{1}...", id, extension.version));
try {
await this.extensionManagementService.installFromGallery(extension, doNotSync);
console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed.", id, extension.version));
} catch (error) {
if (isPromiseCanceledError(error)) {
console.log(localize('cancelVsixInstall', "Cancelled installing extension '{0}'.", id));
} else {
throw error;
}
}
}
private async uninstallExtension(extensions: string[]): Promise<void> {
private async uninstallExtension(extensions: string[], force: boolean): Promise<void> {
async function getExtensionId(extensionDescription: string): Promise<string> {
if (!/\.vsix$/i.test(extensionDescription)) {
return extensionDescription;
@@ -256,13 +317,21 @@ export class Main {
const uninstalledExtensions: ILocalExtension[] = [];
for (const extension of extensions) {
const id = await getExtensionId(extension);
const installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
const [extensionToUninstall] = installed.filter(e => areSameExtensions(e.identifier, { id }));
const installed = await this.extensionManagementService.getInstalled();
const extensionToUninstall = installed.find(e => areSameExtensions(e.identifier, { id }));
if (!extensionToUninstall) {
return Promise.reject(new Error(`${notInstalled(id)}\n${useId}`));
throw new Error(`${notInstalled(id)}\n${useId}`);
}
if (extensionToUninstall.type === ExtensionType.System) {
console.log(localize('builtin', "Extension '{0}' is a Built-in extension and cannot be installed", id));
return;
}
if (extensionToUninstall.isBuiltin && !force) {
console.log(localize('forceUninstall', "Extension '{0}' is marked as a Built-in extension by user. Please use '--force' option to uninstall it.", id));
return;
}
console.log(localize('uninstalling', "Uninstalling {0}...", id));
await this.extensionManagementService.uninstall(extensionToUninstall, true);
await this.extensionManagementService.uninstall(extensionToUninstall);
uninstalledExtensions.push(extensionToUninstall);
console.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id));
}
@@ -299,8 +368,14 @@ export async function main(argv: NativeParsedArgs): Promise<void> {
const services = new ServiceCollection();
const disposables = new DisposableStore();
const environmentService = new EnvironmentService(argv);
const logService: ILogService = new SpdLogService('cli', environmentService.logsPath, getLogLevel(environmentService));
const environmentService = new NativeEnvironmentService(argv);
const logLevel = getLogLevel(environmentService);
const loggers: ILogService[] = [];
loggers.push(new SpdLogService('cli', environmentService.logsPath, logLevel));
if (logLevel === LogLevel.Trace) {
loggers.push(new ConsoleLogService(logLevel));
}
const logService = new MultiplexLogService(loggers);
process.once('exit', () => logService.dispose());
logService.info('main', argv);
@@ -321,6 +396,8 @@ export async function main(argv: NativeParsedArgs): Promise<void> {
await configurationService.initialize();
services.set(IEnvironmentService, environmentService);
services.set(INativeEnvironmentService, environmentService);
services.set(ILogService, logService);
services.set(IConfigurationService, configurationService);
services.set(IStateService, new SyncDescriptor(StateService));
@@ -341,14 +418,14 @@ export async function main(argv: NativeParsedArgs): Promise<void> {
const appenders: AppInsightsAppender[] = [];
if (isBuilt && !extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) {
if (product.aiConfig && product.aiConfig.asimovKey) {
appenders.push(new AppInsightsAppender(eventPrefix, null, product.aiConfig.asimovKey, logService));
appenders.push(new AppInsightsAppender(eventPrefix, null, product.aiConfig.asimovKey));
}
const config: ITelemetryServiceConfig = {
appender: combinedAppender(...appenders),
sendErrorTelemetry: false,
commonProperties: resolveCommonProperties(product.commit, product.version, stateService.getItem('telemetry.machineId'), product.msftInternalDomains, installSourcePath),
piiPaths: extensionsPath ? [appRoot, extensionsPath] : [appRoot]
piiPaths: [appRoot, extensionsPath]
};
services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [config]));

View File

@@ -7,9 +7,57 @@ import { spawn } from 'child_process';
import { generateUuid } from 'vs/base/common/uuid';
import { isWindows } from 'vs/base/common/platform';
import { ILogService } from 'vs/platform/log/common/log';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper';
import { toErrorMessage } from 'vs/base/common/errorMessage';
function getUnixShellEnvironment(logService: ILogService): Promise<typeof process.env> {
/**
* We need to get the environment from a user's shell.
* This should only be done when Code itself is not launched
* from within a shell.
*/
export async function resolveShellEnv(logService: ILogService, args: NativeParsedArgs, env: NodeJS.ProcessEnv): Promise<typeof process.env> {
// Skip if --force-disable-user-env
if (args['force-disable-user-env']) {
logService.trace('resolveShellEnv(): skipped (--force-disable-user-env)');
return {};
}
// Skip on windows
else if (isWindows) {
logService.trace('resolveShellEnv(): skipped (Windows)');
return {};
}
// Skip if running from CLI already
else if (isLaunchedFromCli(env) && !args['force-user-env']) {
logService.trace('resolveShellEnv(): skipped (VSCODE_CLI is set)');
return {};
}
// Otherwise resolve (macOS, Linux)
else {
if (isLaunchedFromCli(env)) {
logService.trace('resolveShellEnv(): running (--force-user-env)');
} else {
logService.trace('resolveShellEnv(): running (macOS/Linux)');
}
if (!unixShellEnvPromise) {
unixShellEnvPromise = doResolveUnixShellEnv(logService);
}
return unixShellEnvPromise;
}
}
let unixShellEnvPromise: Promise<typeof process.env> | undefined = undefined;
async function doResolveUnixShellEnv(logService: ILogService): Promise<typeof process.env> {
const promise = new Promise<typeof process.env>((resolve, reject) => {
const runAsNode = process.env['ELECTRON_RUN_AS_NODE'];
logService.trace('getUnixShellEnvironment#runAsNode', runAsNode);
@@ -66,7 +114,7 @@ function getUnixShellEnvironment(logService: ILogService): Promise<typeof proces
delete env['ELECTRON_NO_ATTACH_CONSOLE'];
}
// https://github.com/Microsoft/vscode/issues/22593#issuecomment-336050758
// https://github.com/microsoft/vscode/issues/22593#issuecomment-336050758
delete env['XDG_RUNTIME_DIR'];
logService.trace('getUnixShellEnvironment#result', env);
@@ -78,33 +126,11 @@ function getUnixShellEnvironment(logService: ILogService): Promise<typeof proces
});
});
// swallow errors
return promise.catch(() => ({}));
}
try {
return await promise;
} catch (error) {
logService.error('getUnixShellEnvironment#error', toErrorMessage(error));
let shellEnvPromise: Promise<typeof process.env> | undefined = undefined;
/**
* We need to get the environment from a user's shell.
* This should only be done when Code itself is not launched
* from within a shell.
*/
export function getShellEnvironment(logService: ILogService, environmentService: INativeEnvironmentService): Promise<typeof process.env> {
if (!shellEnvPromise) {
if (environmentService.args['disable-user-env-probe']) {
logService.trace('getShellEnvironment: disable-user-env-probe set, skipping');
shellEnvPromise = Promise.resolve({});
} else if (isWindows) {
logService.trace('getShellEnvironment: running on Windows, skipping');
shellEnvPromise = Promise.resolve({});
} else if (process.env['VSCODE_CLI'] === '1' && process.env['VSCODE_FORCE_USER_ENV'] !== '1') {
logService.trace('getShellEnvironment: running on CLI, skipping');
shellEnvPromise = Promise.resolve({});
} else {
logService.trace('getShellEnvironment: running on Unix');
shellEnvPromise = getUnixShellEnvironment(logService);
}
return {}; // ignore any errors
}
return shellEnvPromise;
}