'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
}

// Fix for #11302 because `process.env` on Windows is a magic object that offers case-insensitive
// environment variable matching.
function cloneEnv (env) {
  for (var key in process.env) {
    delete process.env[key]
  }

  Object.assign(process.env, env)
}

function normalize (options = {}) {
  if (options && options.env) {
    cloneEnv(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 = Object.assign({}, process.env)
      cloneEnv(shellEnv)
    }
  }
}

function replace (env) {
  if (!env || !env.PATH) {
    return
  }

  cloneEnv(env)
}

export default { getFromShell, needsPatching, normalize, replace }

@@ -1729,16 +1729,104 @@
 atching.
+ By always cloning to %60process.env%60 we prevent breaking the%0A// underlying functionality.
 %0Afunctio
@@ -1836,16 +1836,18 @@
 lone
-Env (env
+ (to, from
 ) %7B%0A
@@ -1864,27 +1864,18 @@
  key in 
-process.env
+to
 ) %7B%0A    
@@ -1881,27 +1881,18 @@
  delete 
-process.env
+to
 %5Bkey%5D%0A  
@@ -1914,24 +1914,16 @@
 ign(
-process.env, env
+to, from
 )%0A%7D%0A
@@ -2000,20 +2000,30 @@
    clone
-Env(
+(process.env, 
 options.
@@ -2476,20 +2476,30 @@
    clone
-Env(
+(process.env, 
 shellEnv
@@ -2588,20 +2588,30 @@
 %0A  clone
-Env(
+(process.env, 
 env)%0A%7D%0A%0A

Make the clone function more generic