Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Simplify Environment Patching #12562

Merged
merged 6 commits into from
Sep 8, 2016
Merged

Simplify Environment Patching #12562

merged 6 commits into from
Sep 8, 2016

Conversation

joefitzgerald
Copy link
Contributor

@joefitzgerald joefitzgerald commented Aug 31, 2016

This PR simplifies the logic used to determine when to patch the environment for users of linux and macOS. Instead of using a whitelist of shells and trying to detect how Atom was launched with environment variable markers, we simply modify atom.sh to set a environment variable that is only set when launched from the shell. If this environment variable is not detected, the environment is patched with the environment from a new, interactive, login shell.

  • Stop whitelisting shells
  • Introduce ATOM_SUPPRESS_ENV_PATCHING environment variable, which is only set in atom.sh
  • Manually test on Ubuntu
  • Manually test on macOS

Fixes #11910
Fixes #12535

@thomasjo
Copy link
Contributor

LGTM™ 🚀

@thomasjo
Copy link
Contributor

thomasjo commented Sep 7, 2016

Let's get this in before rolling the 🚃 🚃 ? /cc @atom/feedback @nathansobo @lee-dohm

@@ -36,6 +33,10 @@ function updateProcessEnv (launchEnv) {
for (let key in envToAssign) {
if (!ENVIRONMENT_VARIABLES_TO_PRESERVE.has(key)) {
process.env[key] = envToAssign[key]
} else {
if (!process.env[key] && envToAssign[key]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we'll always assign "preserved" environment variables if they're not already defined?

Copy link
Contributor

@nathansobo nathansobo Sep 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this duplicated assignment could be eliminated by making the conditional:

if (!ENVIRONMENT_VARIABLES_TO_PRESERVE.has(key) || !process.env[key]) {
  process.env[key] = envToAssign[key]
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is related to #12562 (diff) but I think this new behavior may be too pessimistic. It would prevent the changing of an existing value in process.env which is not the expected behavior. I will write up a spec to validate this assumption and fix if true.

@nathansobo
Copy link
Contributor

If I'm reading this correctly, it seems like the name of the variable ATOM_SUPPRESS_ENV_PATCHING is a bit misleading. We will update the process.env of an existing instance of Atom regardless of this flag. The flag indicates whether we should attempt to invoke the user's shell to retrieve the environment... am I right about that?

@nathansobo
Copy link
Contributor

What about an environment variable like ATOM_LAUNCHED_FROM_SHELL. That seems like it would more clearly communicate the intent unless I'm missed something.

expect(shouldGetEnvFromShell({SHELL: '/bin/zsh'})).toBe(true)
expect(shouldGetEnvFromShell({SHELL: '/usr/local/bin/zsh'})).toBe(true)
expect(shouldGetEnvFromShell({SHELL: '/bin/fish'})).toBe(true)
expect(shouldGetEnvFromShell({SHELL: '/usr/local/bin/fish'})).toBe(true)
})

it('returns false when the shell should not be patched', function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should be phrased returns false when the environment indicates that Atom was launched from a shell

@joefitzgerald
Copy link
Contributor Author

If I'm reading this correctly, it seems like the name of the variable ATOM_SUPPRESS_ENV_PATCHING is a bit misleading. We will update the process.env of an existing instance of Atom regardless of this flag. The flag indicates whether we should attempt to invoke the user's shell to retrieve the environment... am I right about that?

There are two separate behaviors going on in update-environment:

  1. We are potentially patching the environment by launching a new, interactive, login shell and using that environment - if Atom was not launched from the shell
  2. We are allowing multiple invocations of atom from the shell to update the environment with new environment values; we are also allowing for the scenario where you open atom to a directory, and then subsequently open that same directory via atom ./thedir and allowing the environment to be updated with the environment from the shell

So, there's patching, and there's updating of the environment. They are different. Suppressing the patching should not suppress the updating. Maybe we need new verbs ;)

@joefitzgerald
Copy link
Contributor Author

Also worth mentioning: it should be possible for a user to set ATOM_SUPPRESS_ENV_PATCHING in their environment used by launchd to run apps launched by Dock / Finder / Spotlight to completely suppress environment patching. I believe this will be the minority of users, but I suspect some users will want to do this. It would be nice to provide some other configuration file that could be used to suppress this behavior - possibly residing in ATOM_HOME as a future extension / in a subsequent PR.

- 🎨 Update spec description to more accurately reflect the intent
- The additional (!process.env[key] && envToAssign[key]) check allows “preserved” variables to be set for the first time if they are currently unset
@@ -34,7 +31,7 @@ function updateProcessEnv (launchEnv) {
}

for (let key in envToAssign) {
if (!ENVIRONMENT_VARIABLES_TO_PRESERVE.has(key)) {
if (!ENVIRONMENT_VARIABLES_TO_PRESERVE.has(key) || (!process.env[key] && envToAssign[key])) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would envToAssign[key] be falsy? You're thinking like a blank string environment variable? The key definitely exists because we're looping over keys in the line above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppose you launch atom from Finder. ATOM_SUPPRESS_ENV_PATCHING is not set. It is also a "preserved" environment variable. If you were to subsequently launch Atom via the shell, it would never be set, and would not be preserved in future invocations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that explains the !process.env[key] part of the expression but not the && envToAssign[key]. It's minor though. I'll just merge anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For posterity: That last part is unnecessary because key is always unique.

@nathansobo
Copy link
Contributor

Maybe we need new verbs ;)

We definitely need new verbs. Patching and updating are the same thing. We need a clearer description of what we're suppressing that focuses on how we obtain the thing we're using to update the current environment... DISABLE_SHELLING_OUT_FOR_ENVIRONMENT? I'm not happy with the clarity of the existing naming.

@joefitzgerald
Copy link
Contributor Author

Renamed ATOM_SUPPRESS_ENV_PATCHING to ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT.

@nathansobo nathansobo merged commit 6d76608 into master Sep 8, 2016
@nathansobo nathansobo deleted the jf-patch-linux-environment branch September 8, 2016 19:55
@nathansobo
Copy link
Contributor

Thanks @joefitzgerald. This definitely feels like a more robust approach.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants