@@ -4147,6 +4147,8 @@ dependencies = [
"async-trait",
"collections",
"dap",
+ "dotenvy",
+ "fs",
"futures 0.3.31",
"gpui",
"json_dotpath",
@@ -4675,12 +4677,6 @@ dependencies = [
"syn 2.0.101",
]
-[[package]]
-name = "dotenv"
-version = "0.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
-
[[package]]
name = "dotenvy"
version = "0.15.7"
@@ -5114,7 +5110,7 @@ dependencies = [
"collections",
"debug_adapter_extension",
"dirs 4.0.0",
- "dotenv",
+ "dotenvy",
"env_logger 0.11.8",
"extension",
"fs",
@@ -7,13 +7,22 @@ use dap::{
latest_github_release,
},
};
-
+use fs::Fs;
use gpui::{AsyncApp, SharedString};
use language::LanguageName;
-use std::{env::consts, ffi::OsStr, path::PathBuf, sync::OnceLock};
+use log::warn;
+use serde_json::{Map, Value};
use task::TcpArgumentsTemplate;
use util;
+use std::{
+ env::consts,
+ ffi::OsStr,
+ path::{Path, PathBuf},
+ str::FromStr,
+ sync::OnceLock,
+};
+
use crate::*;
#[derive(Default, Debug)]
@@ -437,22 +446,34 @@ impl DebugAdapter for GoDebugAdapter {
adapter_path.join("dlv").to_string_lossy().to_string()
};
- let cwd = task_definition
- .config
- .get("cwd")
- .and_then(|s| s.as_str())
- .map(PathBuf::from)
- .unwrap_or_else(|| delegate.worktree_root_path().to_path_buf());
+ let cwd = Some(
+ task_definition
+ .config
+ .get("cwd")
+ .and_then(|s| s.as_str())
+ .map(PathBuf::from)
+ .unwrap_or_else(|| delegate.worktree_root_path().to_path_buf()),
+ );
let arguments;
let command;
let connection;
let mut configuration = task_definition.config.clone();
+ let mut envs = HashMap::default();
+
if let Some(configuration) = configuration.as_object_mut() {
configuration
.entry("cwd")
.or_insert_with(|| delegate.worktree_root_path().to_string_lossy().into());
+
+ handle_envs(
+ configuration,
+ &mut envs,
+ cwd.as_deref(),
+ delegate.fs().clone(),
+ )
+ .await;
}
if let Some(connection_options) = &task_definition.tcp_connection {
@@ -494,8 +515,8 @@ impl DebugAdapter for GoDebugAdapter {
Ok(DebugAdapterBinary {
command,
arguments,
- cwd: Some(cwd),
- envs: HashMap::default(),
+ cwd,
+ envs,
connection,
request_args: StartDebuggingRequestArguments {
configuration,
@@ -504,3 +525,44 @@ impl DebugAdapter for GoDebugAdapter {
})
}
}
+
+// delve doesn't do anything with the envFile setting, so we intercept it
+async fn handle_envs(
+ config: &mut Map<String, Value>,
+ envs: &mut HashMap<String, String>,
+ cwd: Option<&Path>,
+ fs: Arc<dyn Fs>,
+) -> Option<()> {
+ let env_files = match config.get("envFile")? {
+ Value::Array(arr) => arr.iter().map(|v| v.as_str()).collect::<Vec<_>>(),
+ Value::String(s) => vec![Some(s.as_str())],
+ _ => return None,
+ };
+
+ let rebase_path = |path: PathBuf| {
+ if path.is_absolute() {
+ Some(path)
+ } else {
+ cwd.map(|p| p.join(path))
+ }
+ };
+
+ for path in env_files {
+ let Some(path) = path
+ .and_then(|s| PathBuf::from_str(s).ok())
+ .and_then(rebase_path)
+ else {
+ continue;
+ };
+
+ if let Ok(file) = fs.open_sync(&path).await {
+ envs.extend(dotenvy::from_read_iter(file).filter_map(Result::ok))
+ } else {
+ warn!("While starting Go debug session: failed to read env file {path:?}");
+ };
+ }
+
+ // remove envFile now that it's been handled
+ config.remove("entry");
+ Some(())
+}