Skip to content

Commit

Permalink
portable mode
Browse files Browse the repository at this point in the history
  • Loading branch information
joaomoreno committed Jun 18, 2018
2 parents c473c55 + 76f39b2 commit e43ab4e
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 110 deletions.
33 changes: 33 additions & 0 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,39 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

Error.stackTraceLimit = 100; // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API)

const fs = require('fs');
const path = require('path');
const product = require('../product.json');
const appRoot = path.dirname(__dirname);

function getApplicationPath() {
if (process.env['VSCODE_DEV']) {
return appRoot;
} else if (process.platform === 'darwin') {
return path.dirname(path.dirname(path.dirname(appRoot)));
} else {
return path.dirname(path.dirname(appRoot));
}
}

const portableDataName = product.portable || `${product.applicationName}-portable-data`;
const portableDataPath = path.join(path.dirname(getApplicationPath()), portableDataName);
const isPortable = fs.existsSync(portableDataPath);
const portableTempPath = path.join(portableDataPath, 'tmp');
const isTempPortable = isPortable && fs.existsSync(portableTempPath);

if (isPortable) {
process.env['VSCODE_PORTABLE'] = portableDataPath;
} else {
delete process.env['VSCODE_PORTABLE'];
}

if (isTempPortable) {
process.env[process.platform === 'win32' ? 'TEMP' : 'TMPDIR'] = portableTempPath;
}

//#region Add support for using node_modules.asar
(function () {
const path = require('path');
Expand Down
184 changes: 77 additions & 107 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,45 @@
*--------------------------------------------------------------------------------------------*/
'use strict';

let perf = require('./vs/base/common/performance');
const perf = require('./vs/base/common/performance');
perf.mark('main:started');

// Perf measurements
global.perfStartTime = Date.now();

Error.stackTraceLimit = 100; // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API)

const fs = require('fs');
const path = require('path');
const product = require('../product.json');
const appRoot = path.dirname(__dirname);

function getApplicationPath() {
if (process.env['VSCODE_DEV']) {
return appRoot;
} else if (process.platform === 'darwin') {
return path.dirname(path.dirname(path.dirname(appRoot)));
} else {
return path.dirname(path.dirname(appRoot));
}
}

const portableDataName = product.portable || `${product.applicationName}-portable-data`;
const portableDataPath = process.env['VSCODE_PORTABLE'] || path.join(path.dirname(getApplicationPath()), portableDataName);
const isPortable = fs.existsSync(portableDataPath);
const portableTempPath = path.join(portableDataPath, 'tmp');
const isTempPortable = isPortable && fs.existsSync(portableTempPath);

if (isPortable) {
process.env['VSCODE_PORTABLE'] = portableDataPath;
} else {
delete process.env['VSCODE_PORTABLE'];
}

if (isTempPortable) {
process.env[process.platform === 'win32' ? 'TEMP' : 'TMPDIR'] = portableTempPath;
}

//#region Add support for using node_modules.asar
(function () {
const path = require('path');
Expand All @@ -36,23 +67,27 @@ Error.stackTraceLimit = 100; // increase number of stack frames (from 10, https:
})();
//#endregion

let app = require('electron').app;
const app = require('electron').app;

// TODO@Ben Electron 2.0.x: prevent localStorage migration from SQLite to LevelDB due to issues
app.commandLine.appendSwitch('disable-mojo-local-storage');

// TODO@Ben Electron 2.0.x: force srgb color profile (for https://github.com/Microsoft/vscode/issues/51791)
app.commandLine.appendSwitch('force-color-profile', 'srgb');

let fs = require('fs');
let path = require('path');
let minimist = require('minimist');
let paths = require('./paths');
const minimist = require('minimist');
const paths = require('./paths');

let args = minimist(process.argv, {
string: ['user-data-dir', 'locale']
const args = minimist(process.argv, {
string: [
'user-data-dir',
'locale',
'js-flags',
'max-memory'
]
});

//#region NLS
function stripComments(content) {
let regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g;
let result = content.replace(regexp, function (match, m1, m2, m3, m4) {
Expand All @@ -77,113 +112,38 @@ function stripComments(content) {
return result;
}

let _commit;
function getCommit() {
if (_commit) {
return _commit;
}
if (_commit === null) {
return undefined;
}
try {
let productJson = require(path.join(__dirname, '../product.json'));
if (productJson.commit) {
_commit = productJson.commit;
} else {
_commit = null;
}
} catch (exp) {
_commit = null;
}
return _commit || undefined;
}
const mkdir = dir => new Promise((c, e) => fs.mkdir(dir, err => (err && err.code !== 'EEXIST') ? e(err) : c()));
const exists = file => new Promise(c => fs.exists(file, c));
const readFile = file => new Promise((c, e) => fs.readFile(file, 'utf8', (err, data) => err ? e(err) : c(data)));
const writeFile = (file, content) => new Promise((c, e) => fs.writeFile(file, content, 'utf8', err => err ? e(err) : c()));
const touch = file => new Promise((c, e) => { const d = new Date(); fs.utimes(file, d, d, err => err ? e(err) : c()); });

function mkdirp(dir) {
return mkdir(dir)
.then(null, (err) => {
if (err && err.code === 'ENOENT') {
let parent = path.dirname(dir);
if (parent !== dir) { // if not arrived at root
return mkdirp(parent)
.then(() => {
return mkdir(dir);
});
}
}
throw err;
});
}

function mkdir(dir) {
return new Promise((resolve, reject) => {
fs.mkdir(dir, (err) => {
if (err && err.code !== 'EEXIST') {
reject(err);
} else {
resolve(dir);
}
});
});
}

function exists(file) {
return new Promise((resolve) => {
fs.exists(file, (result) => {
resolve(result);
});
});
}

function readFile(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, 'utf8', (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
return mkdir(dir).then(null, err => {
if (err && err.code === 'ENOENT') {
const parent = path.dirname(dir);

function writeFile(file, content) {
return new Promise((resolve, reject) => {
fs.writeFile(file, content, 'utf8', (err) => {
if (err) {
reject(err);
return;
if (parent !== dir) { // if not arrived at root
return mkdirp(parent).then(() => mkdir(dir));
}
resolve(undefined);
});
});
}
}

function touch(file) {
return new Promise((resolve, reject) => {
let d = new Date();
fs.utimes(file, d, d, (err) => {
if (err) {
reject(err);
return;
}
resolve(undefined);
});
throw err;
});
}

function resolveJSFlags() {
let jsFlags = [];
const jsFlags = [];

if (args['js-flags']) {
jsFlags.push(args['js-flags']);
}

if (args['max-memory'] && !/max_old_space_size=(\d+)/g.exec(args['js-flags'])) {
jsFlags.push(`--max_old_space_size=${args['max-memory']}`);
}
if (jsFlags.length > 0) {
return jsFlags.join(' ');
} else {
return null;
}

return jsFlags.length > 0 ? jsFlags.join(' ') : null;
}

// Language tags are case insensitve however an amd loader is case sensitive
Expand Down Expand Up @@ -288,7 +248,7 @@ function getNLSConfiguration(locale) {
}

perf.mark('nlsGeneration:start');
let defaultResult = function(locale) {
let defaultResult = function (locale) {
let isCoreLanguage = true;
if (locale) {
isCoreLanguage = ['de', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh-cn', 'zh-tw'].some((language) => {
Expand All @@ -299,13 +259,13 @@ function getNLSConfiguration(locale) {
let result = resolveLocale(locale);
perf.mark('nlsGeneration:end');
return Promise.resolve(result);
} else {
} else {
perf.mark('nlsGeneration:end');
return Promise.resolve({ locale: locale, availableLanguages: {} });
}
};
try {
let commit = getCommit();
let commit = product.commit;
if (!commit) {
return defaultResult(locale);
}
Expand Down Expand Up @@ -342,7 +302,7 @@ function getNLSConfiguration(locale) {
return exists(coreLocation).then((fileExists) => {
if (fileExists) {
// We don't wait for this. No big harm if we can't touch
touch(coreLocation).catch(() => {});
touch(coreLocation).catch(() => { });
perf.mark('nlsGeneration:end');
return result;
}
Expand Down Expand Up @@ -395,7 +355,9 @@ function getNLSConfiguration(locale) {
return defaultResult(locale);
}
}
//#endregion

//#region Cached Data Dir
function getNodeCachedDataDir() {
// flag to disable cached data support
if (process.argv.indexOf('--no-cached-data') > 0) {
Expand All @@ -408,7 +370,7 @@ function getNodeCachedDataDir() {
}

// find commit id
let commit = getCommit();
let commit = product.commit;
if (!commit) {
return Promise.resolve(undefined);
}
Expand All @@ -417,10 +379,18 @@ function getNodeCachedDataDir() {

return mkdirp(dir).then(undefined, function () { /*ignore*/ });
}
//#endregion

function getUserDataPath() {
if (isPortable) {
return path.join(portableDataPath, 'user-data');
}

return path.resolve(args['user-data-dir'] || paths.getDefaultUserDataPath(process.platform));
}

// Set userData path before app 'ready' event and call to process.chdir
let userData = path.resolve(args['user-data-dir'] || paths.getDefaultUserDataPath(process.platform));
app.setPath('userData', userData);
app.setPath('userData', getUserDataPath());

// Update cwd based on environment and platform
try {
Expand Down
5 changes: 5 additions & 0 deletions src/vs/code/electron-main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@ function main() {
VSCODE_NLS_CONFIG: process.env['VSCODE_NLS_CONFIG'],
VSCODE_LOGS: process.env['VSCODE_LOGS']
};

if (process.env['VSCODE_PORTABLE']) {
instanceEnv['VSCODE_PORTABLE'] = process.env['VSCODE_PORTABLE'];
}

assign(process.env, instanceEnv);

// Startup
Expand Down
22 changes: 20 additions & 2 deletions src/vs/platform/environment/node/environmentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,13 @@ export class EnvironmentService implements IEnvironmentService {
get userHome(): string { return os.homedir(); }

@memoize
get userDataPath(): string { return parseUserDataDir(this._args, process); }
get userDataPath(): string {
if (process.env['VSCODE_PORTABLE']) {
return path.join(process.env['VSCODE_PORTABLE'], 'user-data');
}

return parseUserDataDir(this._args, process);
}

get appNameLong(): string { return product.nameLong; }

Expand Down Expand Up @@ -127,7 +133,19 @@ export class EnvironmentService implements IEnvironmentService {
get installSourcePath(): string { return path.join(this.userDataPath, 'installSource'); }

@memoize
get extensionsPath(): string { return parsePathArg(this._args['extensions-dir'], process) || process.env['VSCODE_EXTENSIONS'] || path.join(this.userHome, product.dataFolderName, 'extensions'); }
get extensionsPath(): string {
const fromArgs = parsePathArg(this._args['extensions-dir'], process);

if (fromArgs) {
return fromArgs;
} else if (process.env['VSCODE_EXTENSIONS']) {
return process.env['VSCODE_EXTENSIONS'];
} else if (process.env['VSCODE_PORTABLE']) {
return path.join(process.env['VSCODE_PORTABLE'], 'extensions');
} else {
return path.join(this.userHome, product.dataFolderName, 'extensions');
}
}

@memoize
get extensionDevelopmentPath(): string { return this._args.extensionDevelopmentPath ? path.normalize(this._args.extensionDevelopmentPath) : this._args.extensionDevelopmentPath; }
Expand Down
1 change: 1 addition & 0 deletions src/vs/platform/node/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export interface IProductConfiguration {
'darwin': string;
};
logUploaderUrl: string;
portable?: string;
}

export interface ISurveyData {
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/parts/terminal/node/terminalProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ function cleanEnv() {
'PTYCOLS',
'PTYROWS',
'PTYSHELLCMDLINE',
'VSCODE_LOGS'
'VSCODE_LOGS',
'VSCODE_PORTABLE'
];
keys.forEach(function (key) {
if (process.env[key]) {
Expand Down

0 comments on commit e43ab4e

Please sign in to comment.