diff --git a/crates/turborepo-dirs/src/lib.rs b/crates/turborepo-dirs/src/lib.rs
index 678adcffb9705..3181bd15c4087 100644
--- a/crates/turborepo-dirs/src/lib.rs
+++ b/crates/turborepo-dirs/src/lib.rs
@@ -13,7 +13,23 @@ use turbopath::{AbsoluteSystemPathBuf, PathError};
/// is set, it will return that path instead of `dirs_next::config_dir`.
pub fn config_dir() -> Result, PathError> {
if let Ok(dir) = std::env::var("TURBO_CONFIG_DIR_PATH") {
- return AbsoluteSystemPathBuf::new(dir).map(Some);
+ // Reject empty strings per Unix convention
+ if dir.is_empty() {
+ return Err(PathError::InvalidUnicode(dir));
+ }
+
+ let raw = std::path::PathBuf::from(&dir);
+
+ // Resolve to absolute path if necessary
+ let abs = if raw.is_absolute() {
+ raw
+ } else {
+ std::env::current_dir()?.join(raw)
+ };
+
+ let abs_str = abs.to_str().ok_or(PathError::InvalidUnicode(dir))?;
+
+ return AbsoluteSystemPathBuf::new(abs_str).map(Some);
}
dirs_config_dir()
@@ -28,6 +44,11 @@ pub fn config_dir() -> Result , PathError> {
/// is set, it will return that path instead of `dirs_next::config_dir`.
pub fn vercel_config_dir() -> Result , PathError> {
if let Ok(dir) = std::env::var("VERCEL_CONFIG_DIR_PATH") {
+ // Reject empty strings per Unix convention.
+ if dir.is_empty() {
+ return Err(PathError::InvalidUnicode(dir));
+ }
+
return AbsoluteSystemPathBuf::new(dir).map(Some);
}
@@ -73,14 +94,18 @@ mod tests {
}
#[test]
- fn test_config_dir_with_invalid_env_var() {
- // Set TURBO_CONFIG_DIR_PATH to a relative path (invalid)
+ fn test_config_dir_with_relative_path() {
+ // Set TURBO_CONFIG_DIR_PATH to a relative path (should be resolved to absolute)
unsafe {
env::set_var("TURBO_CONFIG_DIR_PATH", "relative/path");
}
let result = config_dir();
- assert!(result.is_err());
+ assert!(result.is_ok());
+ let path = result.unwrap();
+ assert!(path.is_some());
+ // Verify it was resolved to an absolute path
+ assert!(path.unwrap().as_path().is_absolute());
unsafe {
env::remove_var("TURBO_CONFIG_DIR_PATH");