Skip to content

io::process::Command: add fine-grained env builder #15353

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

Merged
merged 1 commit into from
Jul 10, 2014

Conversation

aturon
Copy link
Member

@aturon aturon commented Jul 2, 2014

This commit adds env_insert and env_remove methods to the Command
builder, easing updates to the environment variables for the child
process. The existing method, env, is still available for overriding
the entire environment in one shot (after which the env_insert and
env_remove methods can be used to make further adjustments).

To support these new methods, the internal env representation for
Command has been changed to an optional HashMap holding owned
CStrings (to support non-utf8 data). The HashMap is only
materialized if the environment is updated. The implementation does not
try hard to avoid allocation, since the cost of launching a process will
dwarf any allocation cost.

This patch also adds PartialOrd, Eq, and Hash implementations for
CString.

@alexcrichton
Copy link
Member

If I were to design the API from the ground up at this moment, I would tend to say the the shorter-named env function would be used for building up the environment rather than overriding it. Overriding is a pretty dangerous thing to do as you have to ensure you keep all the important variables.

Cargo has a similar builder for the environment (predates Command), which has this signature:

pub fn env(mut self, key: &str, val: Option<&str>) -> ProcessBuilder;

For us &str would be T, but it made it such that we didn't need to have two functions, one for insertion, and one for removal. That being said, I find env("foo", "bar") quite convenient!

Hm, putting on the bikeshedding hat, what do you think of:

fn env<T: ToCStr>(self, k: T, v: T) -> Self;
fn env_remove<T: ToCStr>(self, k: T) -> Self;
fn env_override<T: ToCStr>(self, k: &[(T, T)]) -> Self;

Other than the naming (which may also be just fine), the rest of the patch looks good to me!

@aturon
Copy link
Member Author

aturon commented Jul 4, 2014

@alexcrichton Updated, using env_set_all rather than env_override.

I also updated some of the code using Command to use env rather than env_set_all, and made the signature for env a bit more flexible by allowing the key and value types to differ.

Let me know if you have any other suggestions!

This commit changes the `io::process::Command` API to provide
fine-grained control over the environment:

* The `env` method now inserts/updates a key/value pair.
* The `env_remove` method removes a key from the environment.
* The old `env` method, which sets the entire environment in one shot,
  is renamed to `env_set_all`. It can be used in conjunction with the
  finer-grained methods. This renaming is a breaking change.

To support these new methods, the internal `env` representation for
`Command` has been changed to an optional `HashMap` holding owned
`CString`s (to support non-utf8 data). The `HashMap` is only
materialized if the environment is updated. The implementation does not
try hard to avoid allocation, since the cost of launching a process will
dwarf any allocation cost.

This patch also adds `PartialOrd`, `Eq`, and `Hash` implementations for
`CString`.

[breaking-change]
@aturon
Copy link
Member Author

aturon commented Jul 10, 2014

@alexcrichton This is now passing on try. Take a quick look at the changes and send it to bors?

@@ -574,7 +574,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
cmd.arg("./src/etc/lldb_batchmode.py")
.arg(test_executable)
.arg(debugger_script)
.env([("PYTHONPATH", config.lldb_python_dir.clone().unwrap().as_slice())]);
.env_set_all([("PYTHONPATH", config.lldb_python_dir.clone().unwrap().as_slice())]);
Copy link
Member

Choose a reason for hiding this comment

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

This seems like another candidate for env over env_set_all

Copy link
Member Author

Choose a reason for hiding this comment

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

Note that the existing code zaps the entire environment to contain just $PYTHONPATH. Not sure if that was intended, but the new version keeps that behavior

Copy link
Member

Choose a reason for hiding this comment

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

While I doubt that it was intended behavior, let's see what happens!

In general, it should probably continue to work, but it's also probably best to not nuke things like HOME and USER.

Copy link
Member

Choose a reason for hiding this comment

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

But not critical at all, of course.

@alexcrichton
Copy link
Member

I left two comments about where env may be more appropriate, but it's ok to fix later, so I'm going to r+ (neither is critical)

bors added a commit that referenced this pull request Jul 10, 2014
This commit adds `env_insert` and `env_remove` methods to the `Command`
builder, easing updates to the environment variables for the child
process. The existing method, `env`, is still available for overriding
the entire environment in one shot (after which the `env_insert` and
`env_remove` methods can be used to make further adjustments).

To support these new methods, the internal `env` representation for
`Command` has been changed to an optional `HashMap` holding owned
`CString`s (to support non-utf8 data). The `HashMap` is only
materialized if the environment is updated. The implementation does not
try hard to avoid allocation, since the cost of launching a process will
dwarf any allocation cost.

This patch also adds `PartialOrd`, `Eq`, and `Hash` implementations for
`CString`.
@bors bors closed this Jul 10, 2014
@bors bors merged commit bfa853f into rust-lang:master Jul 10, 2014
bors added a commit to rust-lang/cargo that referenced this pull request Jul 11, 2014
alexcrichton pushed a commit to alexcrichton/cargo that referenced this pull request Sep 2, 2014
bors added a commit to alexcrichton/cargo that referenced this pull request Sep 2, 2014
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 7, 2023
Add manual implementation of clone for tuples in mir interpreter

And some other minor changes.

Clone for tuple is not implemented in the std and it is magically implemented by the compiler, so we need this.
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

Successfully merging this pull request may close these issues.

3 participants