Fix accidentally dropping shell environment variable (#10105)

Thorsten Ball created

Previously this code would run the changed commend, take its output,
remove the `marker` from the front and then split on `0` byte.

Problem was that `echo` adds a newline, which we did *NOT* skip. So
whatever `env` printed as the first environment variable would have a
`\n` in front of it.

Instead of setting, say, `HOME`, Zed would set `\nHOME`.

This change fixes the issue by switching to `printf '%s' marker`, which
is more portable than using `echo -n`.

This is related to https://github.com/zed-industries/zed/issues/9786 but
I'm not sure yet whether that fixes it.

Release Notes:

- Fixed Zed sometimes missing environment variables from shell in case
they were the first environment variable listed by `/usr/bin/env`.

Change summary

crates/project/src/project.rs | 2 +-
crates/zed/src/main.rs        | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

Detailed changes

crates/project/src/project.rs 🔗

@@ -10017,7 +10017,7 @@ async fn load_shell_environment(dir: &Path) -> Result<HashMap<String, String>> {
         });
 
     let command = format!(
-        "cd '{}';{} echo {marker}; /usr/bin/env -0; exit 0;",
+        "cd '{}';{} printf '%s' {marker}; /usr/bin/env -0; exit 0;",
         dir.display(),
         additional_command.unwrap_or("")
     );

crates/zed/src/main.rs 🔗

@@ -906,7 +906,7 @@ async fn load_login_shell_environment() -> Result<()> {
     // We still don't know why `$SHELL -l -i -c '/usr/bin/env -0'`  would
     // do that, but it does, and `exit 0` helps.
     let shell_cmd = format!(
-        "{}echo {marker}; /usr/bin/env -0; exit 0;",
+        "{}printf '%s' {marker}; /usr/bin/env -0; exit 0;",
         shell_cmd_prefix.as_deref().unwrap_or("")
     );