From 518cfdbd5613dcfa46e92f6cd4d5f5f7a0a4d036 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 5 Apr 2024 19:24:46 -0700 Subject: [PATCH] Adjust env parsing to account for multiline env values (#10216) fixes https://github.com/zed-industries/zed/issues/6012 Release Notes: - N/A --- crates/project/src/project.rs | 13 +++++-------- crates/util/src/util.rs | 26 ++++++++++++++++++++++++++ crates/zed/src/main.rs | 12 ++++-------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index d8db31f76f0f9817d91163d6fbfe5c8edf0c8048..3cd32cb0d0dc954e03690062e80e6bcb4e46d62b 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -99,7 +99,7 @@ use text::{Anchor, BufferId, RopeFingerprint}; use util::{ debug_panic, defer, http::{HttpClient, Url}, - maybe, merge_json_value_into, + maybe, merge_json_value_into, parse_env_output, paths::{ LOCAL_SETTINGS_RELATIVE_PATH, LOCAL_TASKS_RELATIVE_PATH, LOCAL_VSCODE_TASKS_RELATIVE_PATH, }, @@ -10569,13 +10569,10 @@ async fn load_shell_environment(dir: &Path) -> Result> { let mut parsed_env = HashMap::default(); let env_output = &stdout[env_output_start + marker.len()..]; - for line in env_output.split_terminator('\n') { - if let Some(separator_index) = line.find('=') { - let key = line[..separator_index].to_string(); - let value = line[separator_index + 1..].to_string(); - parsed_env.insert(key, value); - } - } + + parse_env_output(env_output, |key, value| { + parsed_env.insert(key, value); + }); Ok(parsed_env) } diff --git a/crates/util/src/util.rs b/crates/util/src/util.rs index a8755ef2b97ba683bd0c17ff46c2f3389d1e658b..80e4a1b316d767fb26d7fb248a6d23fca868c82a 100644 --- a/crates/util/src/util.rs +++ b/crates/util/src/util.rs @@ -130,6 +130,32 @@ where } } +/// Parse the result of calling `usr/bin/env` with no arguments +pub fn parse_env_output(env: &str, mut f: impl FnMut(String, String)) { + let mut current_key: Option = None; + let mut current_value: Option = None; + + for line in env.split_terminator('\n') { + if let Some(separator_index) = line.find('=') { + if &line[..separator_index] != "" { + if let Some((key, value)) = Option::zip(current_key.take(), current_value.take()) { + f(key, value) + } + current_key = Some(line[..separator_index].to_string()); + current_value = Some(line[separator_index + 1..].to_string()); + continue; + }; + } + if let Some(value) = current_value.as_mut() { + value.push('\n'); + value.push_str(line); + } + } + if let Some((key, value)) = Option::zip(current_key.take(), current_value.take()) { + f(key, value) + } +} + pub fn merge_json_value_into(source: serde_json::Value, target: &mut serde_json::Value) { use serde_json::Value; diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index b2405903cf40859332494733be646a88e2c323e8..642d3f7aa77fc24e427fdcfd4d311db87b983e61 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -54,7 +54,7 @@ use std::{ use theme::{ActiveTheme, SystemAppearance, ThemeRegistry, ThemeSettings}; use util::{ http::{HttpClient, HttpClientWithUrl}, - maybe, + maybe, parse_env_output, paths::{self, CRASHES_DIR, CRASHES_RETIRED_DIR}, ResultExt, TryFutureExt, }; @@ -923,13 +923,9 @@ async fn load_login_shell_environment() -> Result<()> { if let Some(env_output_start) = stdout.find(marker) { let env_output = &stdout[env_output_start + marker.len()..]; - for line in env_output.split_terminator('\n') { - if let Some(separator_index) = line.find('=') { - let key = &line[..separator_index]; - let value = &line[separator_index + 1..]; - env::set_var(key, value); - } - } + + parse_env_output(env_output, |key, value| env::set_var(key, value)); + log::info!( "set environment variables from shell:{}, path:{}", shell,