diff options
| author | JJ Liebig <jonathan.liebig@gmail.com> | 2026-09-04 01:05:35 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-04 01:05:35 +0200 |
| commit | 3150bd92d6162ba248bc28fd4d40bd0d6238e1af (patch) | |
| tree | beab751f2fc61d49a9f771091b9132cd1357b070 /src/integration | |
| parent | 73825652244edaf11d3fddc89b5b00266edcae0d (diff) | |
fix(integration): resolve Devin config on Windows (#3595)
refs #2724
Diffstat (limited to 'src/integration')
| -rw-r--r-- | src/integration/env.rs | 33 | ||||
| -rw-r--r-- | src/integration/tests.rs | 32 |
2 files changed, 63 insertions, 2 deletions
diff --git a/src/integration/env.rs b/src/integration/env.rs index 8f3a9e65..c4ee1c34 100644 --- a/src/integration/env.rs +++ b/src/integration/env.rs @@ -76,6 +76,11 @@ pub(crate) fn devin_dir() -> io::Result<PathBuf> { return expand_tilde_path(PathBuf::from(value)).map(|path| path.join("devin")); } + #[cfg(windows)] + if let Some(value) = std::env::var_os("APPDATA").filter(|value| !value.is_empty()) { + return Ok(PathBuf::from(value).join("devin")); + } + Ok(home_dir()?.join(".config").join("devin")) } @@ -215,7 +220,31 @@ pub(crate) fn home_dir() -> io::Result<PathBuf> { } #[cfg(test)] -pub(crate) fn integration_env_lock() -> MutexGuard<'static, ()> { +pub(crate) struct IntegrationEnvLock { + _guard: MutexGuard<'static, ()>, + #[cfg(windows)] + appdata: Option<std::ffi::OsString>, +} + +#[cfg(test)] +impl Drop for IntegrationEnvLock { + fn drop(&mut self) { + #[cfg(windows)] + if let Some(appdata) = self.appdata.take() { + std::env::set_var("APPDATA", appdata); + } else { + std::env::remove_var("APPDATA"); + } + } +} + +#[cfg(test)] +pub(crate) fn integration_env_lock() -> IntegrationEnvLock { static LOCK: OnceLock<Mutex<()>> = OnceLock::new(); - LOCK.get_or_init(|| Mutex::new(())).lock().unwrap() + let guard = LOCK.get_or_init(|| Mutex::new(())).lock().unwrap(); + IntegrationEnvLock { + _guard: guard, + #[cfg(windows)] + appdata: std::env::var_os("APPDATA"), + } } diff --git a/src/integration/tests.rs b/src/integration/tests.rs index c2d94a6e..a02a549e 100644 --- a/src/integration/tests.rs +++ b/src/integration/tests.rs @@ -134,6 +134,8 @@ fn clear_integration_path_env() { std::env::remove_var(COPILOT_HOME_ENV_VAR); std::env::remove_var(KIMI_CODE_HOME_ENV_VAR); std::env::remove_var("XDG_CONFIG_HOME"); + #[cfg(windows)] + std::env::remove_var("APPDATA"); std::env::remove_var(QODERCLI_CONFIG_DIR_ENV_VAR); std::env::remove_var(QWEN_HOME_ENV_VAR); std::env::remove_var(CURSOR_CONFIG_DIR_ENV_VAR); @@ -211,6 +213,36 @@ fn home_dir_uses_userprofile_when_home_is_missing() { #[cfg(windows)] #[test] +fn windows_devin_dir_uses_appdata_without_xdg_override() { + let previous_appdata; + { + let _lock = integration_env_lock(); + previous_appdata = std::env::var_os("APPDATA"); + let previous_xdg = std::env::var_os("XDG_CONFIG_HOME"); + let base = unique_base(); + let appdata = base.join("appdata"); + let xdg = base.join("xdg"); + std::env::set_var("APPDATA", &appdata); + + assert_eq!(devin_dir().unwrap(), appdata.join("devin")); + + std::env::set_var("XDG_CONFIG_HOME", &xdg); + assert_eq!(devin_dir().unwrap(), xdg.join("devin")); + + if let Some(value) = previous_xdg { + std::env::set_var("XDG_CONFIG_HOME", value); + } else { + std::env::remove_var("XDG_CONFIG_HOME"); + } + } + { + let _lock = integration_env_lock(); + assert_eq!(std::env::var_os("APPDATA"), previous_appdata); + } +} + +#[cfg(windows)] +#[test] fn windows_supports_portable_integrations() { use crate::api::schema::IntegrationTarget; |
