Merge pull request #11054 from atom/ld-osx-environment

Patch Environment On OSX And Allow A Different Environment Per Window
This commit is contained in:
Lee Dohm
2016-03-11 20:25:19 -08:00
6 changed files with 274 additions and 15 deletions

View File

@@ -4,6 +4,7 @@ path = require 'path'
_ = require 'underscore-plus'
{deprecate} = require 'grim'
environmentHelpers = require('./environment-helpers')
{CompositeDisposable, Disposable, Emitter} = require 'event-kit'
fs = require 'fs-plus'
{mapSourcePosition} = require 'source-map-support'
@@ -127,6 +128,7 @@ class AtomEnvironment extends Model
# Call .loadOrCreate instead
constructor: (params={}) ->
environmentHelpers.normalize(params)
{@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params
@unloaded = false

View File

@@ -85,16 +85,16 @@ class AtomApplication
else
@loadState(options) or @openPath(options)
openWithOptions: ({initialPaths, pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, profileStartup, timeout, clearWindowState, addToLastWindow}) ->
openWithOptions: ({initialPaths, pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, profileStartup, timeout, clearWindowState, addToLastWindow, env}) ->
if test
@runTests({headless: true, devMode, @resourcePath, executedFrom, pathsToOpen, logFile, timeout})
@runTests({headless: true, devMode, @resourcePath, executedFrom, pathsToOpen, logFile, timeout, env})
else if pathsToOpen.length > 0
@openPaths({initialPaths, pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, clearWindowState, addToLastWindow})
@openPaths({initialPaths, pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, clearWindowState, addToLastWindow, env})
else if urlsToOpen.length > 0
@openUrl({urlToOpen, devMode, safeMode}) for urlToOpen in urlsToOpen
@openUrl({urlToOpen, devMode, safeMode, env}) for urlToOpen in urlsToOpen
else
# Always open a editor window if this is the first instance of Atom.
@openPath({initialPaths, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, clearWindowState, addToLastWindow})
@openPath({initialPaths, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, clearWindowState, addToLastWindow, env})
# Public: Removes the {AtomWindow} from the global window list.
removeWindow: (window) ->
@@ -134,7 +134,8 @@ class AtomApplication
@deleteSocketFile()
server = net.createServer (connection) =>
connection.on 'data', (data) =>
@openWithOptions(JSON.parse(data))
options = JSON.parse(data)
@openWithOptions(options)
server.listen @socketPath
server.on 'error', (error) -> console.error 'Application server failed', error
@@ -418,8 +419,8 @@ class AtomApplication
# :profileStartup - Boolean to control creating a profile of the startup time.
# :window - {AtomWindow} to open file paths in.
# :addToLastWindow - Boolean of whether this should be opened in last focused window.
openPath: ({initialPaths, pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window, clearWindowState, addToLastWindow} = {}) ->
@openPaths({initialPaths, pathsToOpen: [pathToOpen], pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window, clearWindowState, addToLastWindow})
openPath: ({initialPaths, pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window, clearWindowState, addToLastWindow, env} = {}) ->
@openPaths({initialPaths, pathsToOpen: [pathToOpen], pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window, clearWindowState, addToLastWindow, env})
# Public: Opens multiple paths, in existing windows if possible.
#
@@ -432,7 +433,7 @@ class AtomApplication
# :windowDimensions - Object with height and width keys.
# :window - {AtomWindow} to open file paths in.
# :addToLastWindow - Boolean of whether this should be opened in last focused window.
openPaths: ({initialPaths, pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, profileStartup, window, clearWindowState, addToLastWindow}={}) ->
openPaths: ({initialPaths, pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, profileStartup, window, clearWindowState, addToLastWindow, env}={}) ->
devMode = Boolean(devMode)
safeMode = Boolean(safeMode)
clearWindowState = Boolean(clearWindowState)
@@ -469,7 +470,7 @@ class AtomApplication
windowInitializationScript ?= require.resolve('../initialize-application-window')
resourcePath ?= @resourcePath
windowDimensions ?= @getDimensionsForNewWindow()
openedWindow = new AtomWindow({initialPaths, locationsToOpen, windowInitializationScript, resourcePath, devMode, safeMode, windowDimensions, profileStartup, clearWindowState})
openedWindow = new AtomWindow({initialPaths, locationsToOpen, windowInitializationScript, resourcePath, devMode, safeMode, windowDimensions, profileStartup, clearWindowState, env})
if pidToKillWhenClosed?
@pidsToOpenWindows[pidToKillWhenClosed] = openedWindow
@@ -532,7 +533,7 @@ class AtomApplication
# :urlToOpen - The atom:// url to open.
# :devMode - Boolean to control the opened window's dev mode.
# :safeMode - Boolean to control the opened window's safe mode.
openUrl: ({urlToOpen, devMode, safeMode}) ->
openUrl: ({urlToOpen, devMode, safeMode, env}) ->
unless @packages?
PackageManager = require '../package-manager'
@packages = new PackageManager
@@ -547,7 +548,7 @@ class AtomApplication
packagePath = @packages.resolvePackagePath(packageName)
windowInitializationScript = path.resolve(packagePath, pack.urlMain)
windowDimensions = @getDimensionsForNewWindow()
new AtomWindow({windowInitializationScript, @resourcePath, devMode, safeMode, urlToOpen, windowDimensions})
new AtomWindow({windowInitializationScript, @resourcePath, devMode, safeMode, urlToOpen, windowDimensions, env})
else
console.log "Package '#{pack.name}' does not have a url main: #{urlToOpen}"
else
@@ -562,7 +563,7 @@ class AtomApplication
# :specPath - The directory to load specs from.
# :safeMode - A Boolean that, if true, won't run specs from ~/.atom/packages
# and ~/.atom/dev/packages, defaults to false.
runTests: ({headless, resourcePath, executedFrom, pathsToOpen, logFile, safeMode, timeout}) ->
runTests: ({headless, resourcePath, executedFrom, pathsToOpen, logFile, safeMode, timeout, env}) ->
if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath)
resourcePath = @resourcePath
@@ -592,7 +593,7 @@ class AtomApplication
devMode = true
isSpec = true
safeMode ?= false
new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode})
new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode, env})
resolveTestRunnerPath: (testPath) ->
FindParentDir ?= require 'find-parent-dir'

View File

@@ -13,6 +13,7 @@ console.log = require 'nslog'
start = ->
args = parseCommandLine()
args.env = process.env
setupAtomHome(args)
setupCompileCache()
return if handleStartupEventWithSquirrel()

View File

@@ -0,0 +1,94 @@
'use babel'
import {spawnSync} from 'child_process'
import os from 'os'
// Gets a dump of the user's configured shell environment.
//
// Returns the output of the `env` command or `undefined` if there was an error.
function getRawShellEnv () {
let shell = getUserShell()
// The `-ilc` set of options was tested to work with the OS X v10.11
// default-installed versions of bash, zsh, sh, and ksh. It *does not*
// work with csh or tcsh.
let results = spawnSync(shell, ['-ilc', 'env'], {encoding: 'utf8'})
if (results.error || !results.stdout || results.stdout.length <= 0) {
return
}
return results.stdout
}
function getUserShell () {
if (process.env.SHELL) {
return process.env.SHELL
}
return '/bin/bash'
}
// Gets the user's configured shell environment.
//
// Returns a copy of the user's shell enviroment.
function getFromShell () {
let shellEnvText = getRawShellEnv()
if (!shellEnvText) {
return
}
let env = {}
for (let line of shellEnvText.split(os.EOL)) {
if (line.includes('=')) {
let components = line.split('=')
if (components.length === 2) {
env[components[0]] = components[1]
} else {
let k = components.shift()
let v = components.join('=')
env[k] = v
}
}
}
return env
}
function needsPatching (options = { platform: process.platform, env: process.env }) {
if (options.platform === 'darwin' && !options.env.PWD) {
let shell = getUserShell()
if (shell.endsWith('csh') || shell.endsWith('tcsh')) {
return false
}
return true
}
return false
}
function normalize (options = {}) {
if (options && options.env) {
process.env = options.env
}
if (!options.env) {
options.env = process.env
}
if (!options.platform) {
options.platform = process.platform
}
if (needsPatching(options)) {
// Patch the `process.env` on startup to fix the problem first documented
// in #4126. Retain the original in case someone needs it.
let shellEnv = getFromShell()
if (shellEnv && shellEnv.PATH) {
process._originalEnv = process.env
process.env = shellEnv
}
}
}
export default { getFromShell, needsPatching, normalize }

View File

@@ -4,7 +4,7 @@ module.exports = ({blobStore}) ->
require './window'
{getWindowLoadSettings} = require './window-load-settings-helpers'
{resourcePath, isSpec, devMode} = getWindowLoadSettings()
{resourcePath, isSpec, devMode, env} = getWindowLoadSettings()
# Add application-specific exports to module search path.
exportsPath = path.join(resourcePath, 'exports')
@@ -21,6 +21,7 @@ module.exports = ({blobStore}) ->
applicationDelegate: new ApplicationDelegate,
configDirPath: process.env.ATOM_HOME
enablePersistence: true
env: env
})
atom.startEditorWindow().then ->