tlc: Sprint 3 C4 — Panel::set_path resolves relative paths

Previously, Panel::set_path() would pass the input path straight to
read_directory(). A relative path like 'sub' would fail because
read_directory tries to stat it relative to wherever, not relative
to the user's current working directory.

Implementation:
  Panel::set_path() now checks if p.is_relative() and, if so,
  joins it onto std::env::current_dir() before reading. Absolute
  paths pass through unchanged. Falls back to the raw path if
  current_dir() fails (process has no cwd).

Tests (1 new in panel::tests):
  - set_path_resolves_relative_against_cwd

Total: 1272 passing (was 1271; +1 new).
This commit is contained in:
kellito
2026-07-05 17:53:05 +03:00
parent 8ca31beee3
commit b058c05338
@@ -694,14 +694,23 @@ impl Panel {
Ok(p)
}
/// Set the panel's path to `p` and re-read the directory.
/// Used by Find/Tree/Hotlist dialogs to navigate the active
/// panel to a chosen location.
/// Set the panel's path to `p` and re-read the directory. Used
/// by Find/Tree/Hotlist dialogs to navigate the active panel to
/// a chosen location. Relative paths are resolved against the
/// current working directory before navigation.
pub fn set_path(&mut self, p: &Path) -> Result<()> {
if p == self.path {
let resolved = if p.is_relative() {
match std::env::current_dir() {
Ok(cwd) => cwd.join(p),
Err(_) => p.to_path_buf(),
}
} else {
p.to_path_buf()
};
if resolved == self.path {
return Ok(());
}
self.read_directory(p)
self.read_directory(&resolved)
}
/// Re-read the current directory.
@@ -1103,6 +1112,23 @@ mod tests {
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn set_path_resolves_relative_against_cwd() {
let dir = std::env::temp_dir().join("tlc-panel-relative-test");
let sub = dir.join("sub");
let _ = fs::create_dir_all(&sub);
fs::write(sub.join("x.txt"), b"x").unwrap();
let mut p = Panel::new(&dir, &empty_cfg()).unwrap();
// Simulate cwd = dir by chdir; restore on drop.
let prev_cwd = std::env::current_dir().unwrap();
std::env::set_current_dir(&dir).unwrap();
let relative = std::path::PathBuf::from("sub");
p.set_path(&relative).unwrap();
assert_eq!(p.path(), sub.canonicalize().unwrap_or(sub));
std::env::set_current_dir(&prev_cwd).unwrap();
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn cursor_movement() {
let dir = std::env::temp_dir().join("tlc-panel-cursor-test");