Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to set environment variables without clearing environment #82

Open
9999years opened this issue Aug 16, 2024 · 3 comments
Open

Comments

@9999years
Copy link
Contributor

With setEnvInherit, a process can be executed with the environment variables inherited from the parent:

ghci> runProcess_ $ proc "sh" ["-c", "env"]
SHELL=/opt/homebrew/bin/fish
ITERM_PROFILE=Default
COLORTERM=truecolor
XPC_FLAGS=0x0
TERM_PROGRAM_VERSION=3.4
...

setEnv can be used to set environment variables, but doing so prevents the subprocess from inheriting any environment variables from its parent:

ghci> runProcess_ $ setEnv [("a", "b")] $ proc "sh" ["-c", "env"]
sh: line 1: env: command not found
*** Exception: Received ExitFailure 127 when running
Raw command: sh -c env

I'd like to (e.g.) run a program with environment variables inherited but with some changes.

@tomjaguarpaw
Copy link
Collaborator

How about getEnvironment followed by making your changes followed by setEnv?

@9999years
Copy link
Contributor Author

@tomjaguarpaw That sounds like a decent workaround, but it's challenging to compose without fetching the environment multiple times. getEnvironment would also mean constructing the ProcessConfig has to happen within IO.

I'd really like something closer to the Rust Command API:

  • env(k, v) appends an environment variable to the subprocess
  • envs([(k1, v1), (k2, v2), ...]) appends multiple environment variables
  • env_clear() prevents the subprocess from inheriting variables, equivalent to setEnv []
  • env_remove(k) removes an environment variable from the subprocess

This supports the standard case nicely (inheriting the parent environment but adding or modifying a few variables), composes well (env, envs, and env_remove all have sensible behavior when called multiple times), and gives users an opt-in to not inherit the environment with env_clear.

Maybe we could have:

  • addEnv :: String -> String -> ProcessConfig i o e -> ProcessConfig i o e
  • addEnvs :: [(String, String)] -> ProcessConfig i o e -> ProcessConfig i o e
  • clearEnv :: ProcessConfig i o e -> ProcessConfig i o e
    Equivalent to setEnv [] today
  • removeEnv :: String -> ProcessConfig i o e -> ProcessConfig i o e

And we could add a note on setEnv to indicate that it might not do what users expect.

@tomjaguarpaw
Copy link
Collaborator

tomjaguarpaw commented Aug 17, 2024

How about just modifyEnv :: [(String, String)] -> ProcessConfig i o e -> ProcessConfig i o e, in terms of which all others can easily be done?

For example

  • addEnv k v = modifyEnv ((k, v) :)
  • addEnvs envs = modifyEnv (envs ++)
  • clearEnv = modifyEnv (const [])
  • removeEnv: not sure but something like Data.List.deleteBy. I don't know if we have something quite right in base

Is having separately named functions for each of these things important to you? If so then perhaps as an alternative we could have

  • add k v = ((k, v) :)
  • adds = (++)
  • clear = const []
  • remove = <something>

and then use

modifyEnv (add k v), modifyEnv (adds envs), mofifyEnv clear, modifyEnv (remove k).

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

No branches or pull requests

2 participants