提交 05be96f7 编写于 作者: J Joao Moreno

read environment through node itself

fixes #6375
上级 3d5e0586
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import cp = require('child_process');
export interface IEnv {
[key: string]: string;
}
export function getUnixUserEnvironment(): TPromise<IEnv> {
return new TPromise((c, e) => {
let child = cp.spawn(process.env.SHELL, ['-ilc', 'env'], {
detached: true,
stdio: ['ignore', 'pipe', process.stderr],
});
child.stdout.setEncoding('utf8');
child.on('error', () => c({}));
let buffer = '';
child.stdout.on('data', (d: string) => { buffer += d; });
child.on('close', (code: number, signal: any) => {
if (code !== 0) {
return c({});
}
c(parseEnvOutput(buffer));
});
});
}
/**
* Parse output from `env`, attempting to retain any multiple-line variables.
* Exported for use in tests.
*/
export function parseEnvOutput(output: string): IEnv {
let result: IEnv = Object.create(null);
let vars = output.split('\n');
// Rejoin lines to the preceeding line if it doesn't look like the line is a new variable
let current = 0;
for (let i = 1; i < vars.length; i++) {
if (vars[i].match(/^[\w_][\w\d_]*=/) === null) {
vars[current] += `\n${vars[i]}`;
} else {
vars[++current] = vars[i];
}
}
// Trim any remaining vars that had been moved
vars.length = current + 1;
// Turn the array into a map
vars.forEach(line => {
let pos = line.indexOf('=');
if (pos > 0) {
let key = line.substring(0, pos);
let value = line.substring(pos + 1);
if (!key || typeof result[key] === 'string') {
return;
}
result[key] = value;
}
});
return result;
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import env = require('vs/base/node/env');
suite('Env', () => {
test('Parses multi-line environment variables at end of env', function (done: () => void) {
let vars = env.parseEnvOutput('a=first\nb=multiple\nlines');
assert.equal(Object.keys(vars).length, 2);
assert.equal(vars['a'], 'first');
assert.equal(vars['b'], 'multiple\nlines');
done();
});
test('Parses multi-line environment variables at start of env', function (done: () => void) {
let vars = env.parseEnvOutput('a=multiple\nlines\nb=second');
assert.equal(Object.keys(vars).length, 2);
assert.equal(vars['a'], 'multiple\nlines');
assert.equal(vars['b'], 'second');
done();
});
test('Parses complex multi-line environment variables', function (done: () => void) {
let vars = env.parseEnvOutput('a=1\nb=\n23 =4\n_5c=56\n d=7\nE =8');
assert.equal(Object.keys(vars).length, 3);
assert.equal(vars['a'], '1');
assert.equal(vars['b'], '\n23 =4');
assert.equal(vars['_5c'], '56\n d=7\nE =8');
done();
});
});
\ No newline at end of file
......@@ -18,7 +18,6 @@ import { VSCodeMenu } from 'vs/code/electron-main/menus';
import { ISettingsService, SettingsManager } from 'vs/code/electron-main/settings';
import { IUpdateService, UpdateManager } from 'vs/code/electron-main/update-manager';
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { getUnixUserEnvironment, IEnv } from 'vs/base/node/env';
import { TPromise } from 'vs/base/common/winjs.base';
import { AskpassChannel } from 'vs/workbench/parts/git/common/gitIpc';
import { GitAskpassService } from 'vs/workbench/parts/git/electron-main/askpassService';
......@@ -31,6 +30,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ILogService, MainLogService } from 'vs/code/electron-main/log';
import { IStorageService, StorageService } from 'vs/code/electron-main/storage';
import * as cp from 'child_process';
function quit(accessor: ServicesAccessor, error?: Error);
function quit(accessor: ServicesAccessor, message?: string);
......@@ -278,6 +278,64 @@ services.set(ISettingsService, new SyncDescriptor(SettingsManager));
const instantiationService = new InstantiationService(services);
interface IEnv {
[key: string]: string;
}
function getUnixUserEnvironment(): TPromise<IEnv> {
const promise = new TPromise((c, e) => {
const runAsNode = process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'];
const noAttach = process.env['ELECTRON_NO_ATTACH_CONSOLE'];
const env = assign({}, process.env, {
ATOM_SHELL_INTERNAL_RUN_AS_NODE: '1',
ELECTRON_NO_ATTACH_CONSOLE: '1'
});
const command = `'${process.execPath}' -p 'JSON.stringify(process.env)'`;
const child = cp.spawn(process.env.SHELL, ['-ilc', command], {
detached: true,
stdio: ['ignore', 'pipe', process.stderr],
env
});
const buffers: Buffer[] = [];
child.on('error', () => c({}));
child.stdout.on('data', b => buffers.push(b));
child.on('close', (code: number, signal: any) => {
if (code !== 0) {
return e(new Error('Failed to get environment'));
}
const raw = Buffer.concat(buffers).toString('utf8');
try {
const env = JSON.parse(raw);
if (runAsNode) {
env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = runAsNode;
} else {
delete env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'];
}
if (noAttach) {
env['ELECTRON_NO_ATTACH_CONSOLE'] = noAttach;
} else {
delete env['ELECTRON_NO_ATTACH_CONSOLE'];
}
c(env);
} catch (err) {
e(err);
}
});
});
// swallow errors
return promise.then(null, () => ({}));
}
function getUserEnvironment(): TPromise<IEnv> {
return platform.isWindows ? TPromise.as({}) : getUnixUserEnvironment();
}
......
......@@ -16,7 +16,6 @@ import {assign} from 'vs/base/common/objects';
import uri from 'vs/base/common/uri';
import strings = require('vs/base/common/strings');
import {IResourceInput} from 'vs/platform/editor/common/editor';
import {IEnv} from 'vs/base/node/env';
import {EventService} from 'vs/platform/event/common/eventService';
import {WorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IWorkspace, IConfiguration, IEnvironment} from 'vs/platform/workspace/common/workspace';
......@@ -43,7 +42,7 @@ export interface IMainEnvironment extends IEnvironment {
filesToCreate?: IPath[];
filesToDiff?: IPath[];
extensionsToInstall?: string[];
userEnv: IEnv;
userEnv: { [key: string]: string; };
}
export function startup(environment: IMainEnvironment, globalSettings: IGlobalSettings): winjs.TPromise<void> {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册