fix: use ~/.config/gws on all platforms for consistent config path (#134)

Previously used dirs::config_dir() which resolves to different paths per
OS (~/Library/Application Support/gws on macOS, %APPDATA%\gws on Windows),
contradicting the documented ~/.config/gws/ path and causing users to place
config files in the wrong location (ref #119).

Now uses ~/.config/gws/ everywhere with a fallback to the legacy OS-specific
path for existing installs. Also consolidates duplicated dirs::config_dir()
calls in auth.rs and discovery.rs to use the central config_dir() helper.
This commit is contained in:
Frank
2026-03-05 16:30:19 +08:00
committed by GitHub
parent 6ed836c81c
commit d3e90e4931
4 changed files with 64 additions and 9 deletions
@@ -0,0 +1,10 @@
---
"@googleworkspace/cli": patch
---
fix: use ~/.config/gws on all platforms for consistent config path
Previously used `dirs::config_dir()` which resolves to different paths per OS
(e.g. ~/Library/Application Support/gws on macOS, %APPDATA%\gws on Windows),
contradicting the documented ~/.config/gws/ path. Now uses ~/.config/gws/
everywhere with a fallback to the legacy OS-specific path for existing installs.
+1 -3
View File
@@ -51,9 +51,7 @@ pub async fn get_token(scopes: &[&str], account: Option<&str>) -> anyhow::Result
let creds_file = std::env::var("GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE").ok();
let impersonated_user = std::env::var("GOOGLE_WORKSPACE_CLI_IMPERSONATED_USER").ok();
let config_dir = dirs::config_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("gws");
let config_dir = crate::auth_commands::config_dir();
// If env var credentials are specified, skip account resolution entirely
if creds_file.is_some() {
+52 -2
View File
@@ -96,9 +96,25 @@ pub fn config_dir() -> PathBuf {
return PathBuf::from(dir);
}
dirs::config_dir()
// Use ~/.config/gws on all platforms for a consistent, user-friendly path.
let primary = dirs::home_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("gws")
.join(".config")
.join("gws");
if primary.exists() {
return primary;
}
// Backward compat: fall back to OS-specific config dir for existing installs
// (e.g. ~/Library/Application Support/gws on macOS, %APPDATA%\gws on Windows).
let legacy = dirs::config_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("gws");
if legacy.exists() {
return legacy;
}
primary
}
fn plain_credentials_path() -> PathBuf {
@@ -1455,6 +1471,40 @@ mod tests {
assert!(path.ends_with("gws"));
}
#[test]
fn config_dir_primary_uses_dot_config() {
// The primary (non-test) path should be ~/.config/gws.
// We can't easily test the real function without env override,
// but we verify the building blocks: home_dir + .config + gws.
let primary = dirs::home_dir()
.unwrap()
.join(".config")
.join("gws");
assert!(primary.ends_with(".config/gws") || primary.ends_with(r".config\gws"));
}
#[test]
#[serial_test::serial]
fn config_dir_fallback_to_legacy() {
// When GOOGLE_WORKSPACE_CLI_CONFIG_DIR points to a legacy-style dir,
// config_dir() should return it (simulating the test env override).
let dir = tempfile::tempdir().unwrap();
let legacy = dir.path().join("legacy_gws");
std::fs::create_dir_all(&legacy).unwrap();
unsafe {
std::env::set_var(
"GOOGLE_WORKSPACE_CLI_CONFIG_DIR",
legacy.to_str().unwrap(),
);
}
let path = config_dir();
assert_eq!(path, legacy);
unsafe {
std::env::remove_var("GOOGLE_WORKSPACE_CLI_CONFIG_DIR");
}
}
#[test]
#[serial_test::serial]
fn plain_credentials_path_defaults_to_config_dir() {
+1 -4
View File
@@ -195,10 +195,7 @@ pub async fn fetch_discovery_document(
let version =
crate::validate::validate_api_identifier(version).map_err(|e| anyhow::anyhow!("{e}"))?;
let cache_dir = dirs::config_dir()
.unwrap_or_else(|| std::path::PathBuf::from("."))
.join("gws")
.join("cache");
let cache_dir = crate::auth_commands::config_dir().join("cache");
std::fs::create_dir_all(&cache_dir)?;
let cache_file = cache_dir.join(format!("{service}_{version}.json"));