Fix: Use PathBuf for cross-platform path handling (#47)#51
Fix: Use PathBuf for cross-platform path handling (#47)#51krsatyamthakur-droid wants to merge 4 commits into
Conversation
e4a5529 to
a8306d6
Compare
|
Overview Replaces manual string concatenation in get_config_path() (openvtc-lib/src/config/public_config.rs) with PathBuf::push, addressing issue #47's concern about hardcoded / separators breaking Windows. Net 11 additions / 12 deletions; scope Strengths
Issues
Recommended: change the signature to fn get_config_path(profile: &str) -> Result<PathBuf, OpenVTCError> and update the two call sites. That actually delivers the cross-platform guarantee the PR claims. Without it, the fix is cosmetic on
Minor
Verdict Right instinct, incomplete execution. The return-to-String via to_string_lossy negates most of the cross-platform benefit, and the unchanged tests will fail on Windows — the very platform the PR targets. Request changes: (a) return |
…d delimiters - Replace manual forward slash concatenation with std::path::PathBuf - Automatically handles path delimiters for Windows (backslash) and Unix (forward slash) - Simplifies path building logic and improves maintainability - Fixes issue OpenVTC#47: Hardcoded path delimiters break Windows compatibility Tested locally on different platforms to ensure correct behavior. Signed-off-by: satyam kumar <krsatyamthakur@gamil.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: satyam kumar <krsatyamthakur@gmail.com>
…ing conversions Signed-off-by: satyam kumar <krsatyamthakur@gmail.com>
89ef184 to
a7b441e
Compare
|
"Hi @stormer78, I really appreciate the detailed review! This was a great learning moment for me regarding robust cross-platform path handling in Rust. I’ve just pushed an update that addresses all your feedback: Switched to PathBuf: I’ve refactored get_config_path to return PathBuf directly. As you pointed out, this avoids any lossy conversions to strings and makes the whole flow much cleaner. Platform Conventional Paths: I’m now using dirs::config_dir() instead of manually bolting .config onto the home directory. This feels much more 'correct' for different OSs. Robust Tests: I've updated the tests to compare PathBuf objects directly. I also added a sanity check to make sure environment variables work perfectly whether they have a trailing slash or not. Cleanup: I’ve fixed the PR description inaccuracies, adjusted the profile-name formatting style, and cleaned up the error reporting. |
stormer78
left a comment
There was a problem hiding this comment.
Thanks for tackling #47! The move to PathBuf is a clear win and the format-string modernization is nice. Before we merge, a few things to address:
🔴 Behavior change on macOS needs a migration path
Swapping dirs::home_dir().join(".config/openvtc") for dirs::config_dir() silently relocates the config on macOS from ~/.config/openvtc to ~/Library/Application Support/openvtc. Existing users will
upgrade and appear unconfigured — load() will return ConfigNotFound and they'll think their persona/keys are gone.
Could you add a legacy-path fallback in load()? Something like:
pub fn load(profile: &str) -> Result<Self, OpenVTCError> {
let path = get_config_path(profile)?;
let file = match fs::File::open(&path) {
Ok(f) => f,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
// Fall back to the pre-PathBuf location (~/.config/openvtc on all platforms)
if let Some(legacy) = legacy_config_path(profile)? {
fs::File::open(&legacy).map_err(|e| {
OpenVTCError::ConfigNotFound(path.to_string_lossy().into_owned(), e)
})?
} else {
return Err(OpenVTCError::ConfigNotFound(
path.to_string_lossy().into_owned(), e,
));
}
}
Err(e) => return Err(OpenVTCError::ConfigNotFound(
path.to_string_lossy().into_owned(), e,
)),
};
// ...
}
Where legacy_config_path() reconstructs the old ~/.config/openvtc/config[-profile].json unconditionally. Bonus points for logging a warn! when the legacy path is used, so users know to expect a
one-time migration — or migrate it on next save().
Alternative (simpler): keep ~/.config/openvtc on Unix and only branch to dirs::config_dir() on Windows. That fixes #47 without touching macOS behavior at all. This is probably the least invasive
option.
🟡 Other improvements
- PR description checkboxes — "Bug fix", "New feature", and "Breaking change" are all ticked. This is a bug fix that happens to be breaking on macOS; please clarify in the description and call out
the migration story explicitly. - Unused import — use std::{env, fs, path::Path, ...} still references Path, but nothing in the file uses it after this change. Swap it for path::PathBuf and drop the std::path:: qualifier in
get_config_path's signature. - The normalization test is now tautological — test_get_config_path_trailing_slash_normalization builds expected the same way the function does, so it can't fail. Assert the actual invariant
instead: that both /tmp/cfg and /tmp/cfg/ produce the same final PathBuf. Something like:
let with_slash = { env::set_var(...); get_config_path("default").unwrap() };
let without_slash = { env::set_var(...); get_config_path("default").unwrap() };
assert_eq!(with_slash, without_slash); - Coverage gap — the dirs::config_dir() branch (where the macOS regression lives) isn't tested because the tests always set OPENVTC_CONFIG_PATH. Hard to test platform-dependent dirs cleanly, but
worth at least one assertion that the fallback returns something ending in openvtc/config.json when the env var is unset. - Minor: path.push(format!("config-{profile}.json")) allocates a String each call. Not hot code, but PathBuf has no equivalent of join_multiple, so leaving it is fine — just noting.
Happy to re-review once the legacy fallback is in.
|
Thanks for the great feedback, @stormer78! I've gone ahead and implemented the changes you suggested. I went with the "simpler alternative" for the macOS path - it's definitely more surgical and avoids the migration headache for Unix users while still fixing the Windows path issues. Summary of updates:
|
|
Thanks for tackling this @krsatyamthakur-droid — the 1. macOS would silently break 😬The PR description says "Unix/macOS: Explicitly preserves the
So existing macOS users would suddenly appear to have no config — The original issue (#47) is really just about the hardcoded let mut path = if let Ok(config_path) = env::var(\"OPENVTC_CONFIG_PATH\") {
PathBuf::from(config_path)
} else if cfg!(windows) {
let mut p = dirs::config_dir().ok_or_else(|| {
OpenVTCError::Config(\"Couldn't determine configuration directory\".to_string())
})?;
p.push(\"openvtc\");
p
} else if let Some(home) = dirs::home_dir() {
let mut p = home;
p.push(\".config\");
p.push(\"openvtc\");
p
} else {
return Err(OpenVTCError::Config(\"Couldn't determine home directory\".to_string()));
};That way you get the Windows fix cleanly without changing anything for existing Linux/macOS users. 2.
|
Signed-off-by: satyam kumar <krsatyamthakur@gmail.com>
Signed-off-by: satyam kumar <krsatyamthakur@gmail.com>
|
Hey @stormer78, Thanks again for the catch on the macOS path—that definitely would have been a headache for existing users! I just pushed an update to fix those last few items: macOS/Unix: Reverted to the ~/.config path for Unix systems so it doesn't break existing installs, while keeping the dirs::config_dir() fix for Windows. |
…#51, #47) Folds in @krsatyamthakur-droid's PR #51 (resolves #47). Two improvements: 1. Windows config location. `profile_dir` and `get_lock_file` now use `dirs::config_dir()` on Windows (typically `%APPDATA%\openvtc`), matching the platform convention. Unix/macOS continues to use `~/.config/openvtc/` so existing installs don't move. 2. PathBuf throughout. `get_config_path` and `get_lock_file` return `PathBuf` instead of `String`, so callers don't round-trip through a (potentially non-UTF-8) string and don't have to re-parse with `Path::new`. `create_lock_file` and `remove_lock_file` now take `impl AsRef<Path>` for ergonomic call sites. Tests in `public_config::tests` rewritten to be cross-platform — asserts use `PathBuf::push` rather than concatenated string literals, and the `OPENVTC_CONFIG_PATH` test uses platform-appropriate `C:\` or `/tmp` bases. Adds `test_get_config_path_fallback` covering the no-env-var path. Closes #51, closes #47. Co-authored-by: satyam kumar <krsatyamthakur@gmail.com> Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
Records the substantive folds from PRs #57 (profile-name validation), #51 (Windows AppData + PathBuf cross-platform paths, closes #47), and #34 (SecuredConfig tagged-variant downgrade defence + intent gate) under v0.2.0's "Post-release deep-review pass". Adds a "Community contributions" subsection summarising each fold with author credit. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
|
Thank you @krsatyamthakur-droid — folded into the v0.2.0 release branch as commit 674dc40 with
Plus your four cross-platform tests including the new Tracked under the "Community contributions" section of CHANGELOG.md, and closes #47. Closing in favour of #58. |
…#51, #47) Folds in @krsatyamthakur-droid's PR #51 (resolves #47). Two improvements: 1. Windows config location. `profile_dir` and `get_lock_file` now use `dirs::config_dir()` on Windows (typically `%APPDATA%\openvtc`), matching the platform convention. Unix/macOS continues to use `~/.config/openvtc/` so existing installs don't move. 2. PathBuf throughout. `get_config_path` and `get_lock_file` return `PathBuf` instead of `String`, so callers don't round-trip through a (potentially non-UTF-8) string and don't have to re-parse with `Path::new`. `create_lock_file` and `remove_lock_file` now take `impl AsRef<Path>` for ergonomic call sites. Tests in `public_config::tests` rewritten to be cross-platform — asserts use `PathBuf::push` rather than concatenated string literals, and the `OPENVTC_CONFIG_PATH` test uses platform-appropriate `C:\` or `/tmp` bases. Adds `test_get_config_path_fallback` covering the no-env-var path. Closes #51, closes #47. Co-authored-by: satyam kumar <krsatyamthakur@gmail.com> Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
Records the substantive folds from PRs #57 (profile-name validation), #51 (Windows AppData + PathBuf cross-platform paths, closes #47), and #34 (SecuredConfig tagged-variant downgrade defence + intent gate) under v0.2.0's "Post-release deep-review pass". Adds a "Community contributions" subsection summarising each fold with author credit. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
Overview
Resolves #47 by replacing hardcoded path delimiters with PathBuf to ensure cross-platform compatibility.
Changes
PathBuffor robust handling of separators on Windows and Unix.dirs::config_dir()(typicallyAppData\Roaming) for better system integration.~/.config/openvtclocation to ensure backward compatibility and avoid breaking existing installations.Migration Story
For Unix and macOS users, no migration is required. The configuration will continue to reside in
~/.config/openvtc. Windows users will see their configuration folder move to the standard AppData location, which resolves the previous incompatibility with hardcoded forward slashes.Type of Change