From b76476aeb2b6ddc8e252c004a7647a3dd41ae5b7 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Tue, 11 Jul 2017 11:55:53 -0700 Subject: [PATCH] Pass config dir to C++ as an environment variable --- .../onboarding/lib/onboarding-helpers.es6 | 2 +- .../client-app/src/browser/application.es6 | 6 +- packages/client-app/src/browser/main.js | 21 ++-- .../src/browser/nylas-protocol-handler.es6 | 30 ++--- packages/client-app/src/compile-cache.js | 4 +- .../client-app/src/flux/mailsync-bridge.es6 | 2 +- packages/client-app/src/mailsync-process.es6 | 9 +- packages/client-app/src/nylas-env.es6 | 105 +----------------- 8 files changed, 33 insertions(+), 146 deletions(-) diff --git a/packages/client-app/internal_packages/onboarding/lib/onboarding-helpers.es6 b/packages/client-app/internal_packages/onboarding/lib/onboarding-helpers.es6 index f4d07edde..9dafc09cf 100644 --- a/packages/client-app/internal_packages/onboarding/lib/onboarding-helpers.es6 +++ b/packages/client-app/internal_packages/onboarding/lib/onboarding-helpers.es6 @@ -122,7 +122,7 @@ export function runAuthValidation(accountInfo) { // Send the form data directly to Nylas to get code // If this succeeds, send the received code to N1 server to register the account // Otherwise process the error message from the server and highlight UI as needed - const proc = new MailsyncProcess(data, NylasEnv.getLoadSettings().resourcePath); + const proc = new MailsyncProcess(NylasEnv.getLoadSettings(), data); return proc.test().then((accountJSON) => { return accountJSON; }); diff --git a/packages/client-app/src/browser/application.es6 b/packages/client-app/src/browser/application.es6 index 8b22ef597..030274cf9 100644 --- a/packages/client-app/src/browser/application.es6 +++ b/packages/client-app/src/browser/application.es6 @@ -29,7 +29,7 @@ export default class Application extends EventEmitter { const {resourcePath, configDirPath, version, devMode, specMode, benchmarkMode, safeMode} = options; // Normalize to make sure drive letter case is consistent on Windows - this.resourcePath = path.normalize(resourcePath); + this.resourcePath = resourcePath; this.configDirPath = configDirPath; this.version = version; this.devMode = devMode; @@ -38,10 +38,10 @@ export default class Application extends EventEmitter { this.safeMode = safeMode; this.fileListCache = new FileListCache(); - this.nylasProtocolHandler = new NylasProtocolHandler(this.resourcePath, this.safeMode); + this.nylasProtocolHandler = new NylasProtocolHandler({configDirPath, resourcePath, safeMode}); try { - const mailsync = new MailsyncProcess(null, this.resourcePath); + const mailsync = new MailsyncProcess(options, null); await mailsync.migrate(); } catch (err) { dialog.showMessageBox({ diff --git a/packages/client-app/src/browser/main.js b/packages/client-app/src/browser/main.js index e0617942b..e059ca2bb 100644 --- a/packages/client-app/src/browser/main.js +++ b/packages/client-app/src/browser/main.js @@ -16,26 +16,19 @@ if (typeof process.setFdLimit === 'function') { } const setupConfigDir = (args) => { - let defaultDirName = ".nylas-mail"; + let defaultDirName = "nylas-mail"; if (args.devMode) { - defaultDirName = ".nylas-dev"; + defaultDirName = "nylas-dev"; } if (args.specMode) { - defaultDirName = ".nylas-spec"; + defaultDirName = "nylas-spec"; } if (args.benchmarkMode) { - defaultDirName = ".nylas-bench"; + defaultDirName = "nylas-bench"; } - let configDirPath = path.join(app.getPath('home'), defaultDirName); - - if (args.configDirPath) { - configDirPath = args.configDirPath; - } else if (process.env.NYLAS_HOME) { - configDirPath = process.env.NYLAS_HOME; - } - + const configDirPath = path.join(app.getPath('appData'), defaultDirName); mkdirp.sync(configDirPath); - process.env.NYLAS_HOME = configDirPath; + return configDirPath; }; @@ -99,7 +92,7 @@ const parseCommandLine = (argv) => { const specDirectory = args['spec-directory']; const specFilePattern = args['spec-file-pattern']; const showSpecsInWindow = specMode === "window"; - const resourcePath = path.resolve(path.dirname(path.dirname(__dirname))); + const resourcePath = path.normalize(path.resolve(path.dirname(path.dirname(__dirname)))); const urlsToOpen = []; const pathsToOpen = []; diff --git a/packages/client-app/src/browser/nylas-protocol-handler.es6 b/packages/client-app/src/browser/nylas-protocol-handler.es6 index 6aa87f548..e711bc249 100644 --- a/packages/client-app/src/browser/nylas-protocol-handler.es6 +++ b/packages/client-app/src/browser/nylas-protocol-handler.es6 @@ -1,4 +1,4 @@ -import {app, protocol} from 'electron'; +import {protocol} from 'electron'; import fs from 'fs'; import path from 'path'; @@ -14,15 +14,13 @@ import path from 'path'; // * RESOURCE_PATH/node_modules // export default class NylasProtocolHandler { - constructor(resourcePath, safeMode) { + constructor({configDirPath, resourcePath, safeMode}) { this.loadPaths = []; - this.dotNylasDirectory = path.join(app.getPath('home'), '.nylas-mail'); if (!safeMode) { - this.loadPaths.push(path.join(this.dotNylasDirectory, 'dev', 'packages')); + this.loadPaths.push(path.join(configDirPath, 'dev', 'packages')); } - - this.loadPaths.push(path.join(this.dotNylasDirectory, 'packages')); + this.loadPaths.push(path.join(configDirPath, 'packages')); this.loadPaths.push(path.join(resourcePath, 'internal_packages')); this.registerNylasProtocol(); @@ -34,21 +32,11 @@ export default class NylasProtocolHandler { const relativePath = path.normalize(request.url.substr(7)); let filePath = null; - if (relativePath.indexOf('assets/') === 0) { - const assetsPath = path.join(this.dotNylasDirectory, relativePath); - const assetsStats = fs.statSyncNoException(assetsPath); - if (assetsStats.isFile && assetsStats.isFile()) { - filePath = assetsPath; - } - } - - if (!filePath) { - for (const loadPath of this.loadPaths) { - filePath = path.join(loadPath, relativePath); - const fileStats = fs.statSyncNoException(filePath); - if (fileStats.isFile && fileStats.isFile()) { - break; - } + for (const loadPath of this.loadPaths) { + filePath = path.join(loadPath, relativePath); + const fileStats = fs.statSyncNoException(filePath); + if (fileStats.isFile && fileStats.isFile()) { + break; } } diff --git a/packages/client-app/src/compile-cache.js b/packages/client-app/src/compile-cache.js index 49e4e0b5b..818e222be 100644 --- a/packages/client-app/src/compile-cache.js +++ b/packages/client-app/src/compile-cache.js @@ -1,6 +1,7 @@ /* eslint no-cond-assign: 0 */ const path = require('path') const fs = require('fs') +const mkdirp = require('mkdirp'); const babelCompiler = require('./compile-support/babel') const coffeeCompiler = require('./compile-support/coffee-script') @@ -30,8 +31,9 @@ function readCachedJavascript(relativeCachePath) { function writeCachedJavascript(relativeCachePath, code) { const cacheTmpPath = path.join(cacheDirectory, `${relativeCachePath}.${process.pid}`) const cachePath = path.join(cacheDirectory, relativeCachePath) + mkdirp.sync(path.dirname(cacheTmpPath)); fs.writeFileSync(cacheTmpPath, code, 'utf8') - fs.renameSync(cacheTmpPath, cachePath) + fs.renameSync(cacheTmpPath, cachePath); } function addSourceURL(jsCode, filePath) { diff --git a/packages/client-app/src/flux/mailsync-bridge.es6 b/packages/client-app/src/flux/mailsync-bridge.es6 index 64b4cd4cf..5d39145b1 100644 --- a/packages/client-app/src/flux/mailsync-bridge.es6 +++ b/packages/client-app/src/flux/mailsync-bridge.es6 @@ -48,7 +48,7 @@ export default class MailsyncBridge { } toLaunch.forEach((acct) => { - const client = new MailsyncProcess(acct, NylasEnv.getLoadSettings().resourcePath); + const client = new MailsyncProcess(NylasEnv.getLoadSettings(), acct); client.sync(); client.on('deltas', this.onIncomingMessages); client.on('close', () => { diff --git a/packages/client-app/src/mailsync-process.es6 b/packages/client-app/src/mailsync-process.es6 index 0be4ebb08..b29e508ee 100644 --- a/packages/client-app/src/mailsync-process.es6 +++ b/packages/client-app/src/mailsync-process.es6 @@ -27,15 +27,20 @@ const LocalizedErrorStrings = { }; export default class MailsyncProcess extends EventEmitter { - constructor(account, resourcePath) { + constructor({configDirPath, resourcePath}, account) { super(); + this.configDirPath = configDirPath; this.account = account; this.binaryPath = path.join(resourcePath, 'MailSync'); this._proc = null; } _spawnProcess(mode) { - this._proc = spawn(this.binaryPath, [`--mode`, mode]); + this._proc = spawn(this.binaryPath, [`--mode`, mode], { + env: { + CONFIG_DIR_PATH: this.configDirPath, + }, + }); if (this.account) { this._proc.stdout.once('data', () => { this._proc.stdin.write(`${JSON.stringify(this.account)}\n`); diff --git a/packages/client-app/src/nylas-env.es6 b/packages/client-app/src/nylas-env.es6 index e7bdde3c4..2f65ca369 100644 --- a/packages/client-app/src/nylas-env.es6 +++ b/packages/client-app/src/nylas-env.es6 @@ -1,12 +1,10 @@ /* eslint global-require: 0 */ /* eslint import/no-dynamic-require: 0 */ +import fs from 'fs'; import path from 'path'; - -import { ipcRenderer, remote, shell } from 'electron'; - +import { ipcRenderer, remote } from 'electron'; import _ from 'underscore'; import { Emitter } from 'event-kit'; -import fs from 'fs'; import { convertStackTrace } from 'coffeestack'; import { mapSourcePosition } from 'source-map-support'; @@ -193,15 +191,9 @@ export default class NylasEnvConstructor { // by default) to support these symlinked modules require('module').globalPaths.push(path.join(resourcePath, 'node_modules')); - // Still set NODE_PATH since tasks may need it. - process.env.NODE_PATH = globalPath; - // Make react.js faster if (!devMode && process.env.NODE_ENV == null) process.env.NODE_ENV = 'production'; - // Set NylasEnv's home so packages don't have to guess it - process.env.NYLAS_HOME = configDirPath; - // Setup config and load it immediately so it's available to our singletons this.config = new Config({configDirPath, resourcePath}); @@ -224,8 +216,6 @@ export default class NylasEnvConstructor { this.windowEventHandler = new WindowEventHandler(); - this.globalWindowEmitter = new Emitter(); - if (!this.inSpecMode()) { this.mailsyncBridge = new MailsyncBridge(); this.actionBridge = new ActionBridge(ipcRenderer); @@ -403,15 +393,6 @@ export default class NylasEnvConstructor { Section: Event Subscription */ - // Extended: Invoke the given callback whenever {::beep} is called. - // - // * `callback` {Function} to be called whenever {::beep} is called. - // - // Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. - onDidBeep(callback) { - return this.emitter.on('did-beep', callback); - } - // Extended: Invoke the given callback when there is an unhandled error, but // before the devtools pop open // @@ -909,8 +890,6 @@ export default class NylasEnvConstructor { // This also means that the windowType has changed and a different set of // plugins needs to be loaded. populateHotWindow(event, loadSettings) { - console.log('populateHotWindow called') - console.log(loadSettings); this.loadSettings = loadSettings; this.constructor.loadSettings = loadSettings; @@ -966,55 +945,6 @@ export default class NylasEnvConstructor { if (maximize) this.maximize(); } - // Essential: Visually and audibly trigger a beep. - beep() { - if (this.config.get('core.audioBeep')) { shell.beep(); } - return this.emitter.emit('did-beep'); - } - - // Essential: A flexible way to open a dialog akin to an alert dialog. - // - // ## Examples - // - // ```coffee - // NylasEnv.confirm - // message: 'How you feeling?' - // detailedMessage: 'Be honest.' - // buttons: - // Good: -> window.alert('good to hear') - // Bad: -> window.alert('bummer') - // ``` - // - // * `options` An {Object} with the following keys: - // * `message` The {String} message to display. - // * `detailedMessage` (optional) The {String} detailed message to display. - // * `buttons` (optional) Either an array of strings or an object where keys are - // button names and the values are callbacks to invoke when clicked. - // - // Returns the chosen button index {Number} if the buttons option was an array. - confirm({message, detailedMessage, buttons} = {}) { - let buttonLabels; - if (_.isArray(buttons)) { - buttonLabels = buttons; - } else { - buttonLabels = Object.keys(buttons || {}); - } - - const chosen = remote.dialog.showMessageBox(this.getCurrentWindow(), { - type: 'info', - message, - detail: detailedMessage, - buttons: buttonLabels, - } - ); - - if (_.isArray(buttons)) { - return chosen; - } - const callback = buttons[buttonLabels[chosen]]; - return callback ? callback() : undefined; - } - /* Section: Managing the Dev Tools */ @@ -1158,37 +1088,6 @@ export default class NylasEnvConstructor { return process.crash(); } - // Require the module with the given globals. - // - // The globals will be set on the `window` object and removed after the - // require completes. - // - // * `id` The {String} module name or path. - // * `globals` An optinal {Object} to set as globals during require. - requireWithGlobals(id, globals = {}) { - const existingGlobals = {}; - for (const key of globals) { - const value = globals[key]; - existingGlobals[key] = window[key]; - window[key] = value; - } - - require(id); - - return (() => { - const result = []; - for (const key of existingGlobals) { - const value = existingGlobals[key]; - if (value === undefined) { - result.push(delete window[key]); - } else { - result.push(window[key] = value); - } - } - return result; - })(); - } - onUpdateAvailable(callback) { return this.emitter.on('update-available', callback); }