use std::fmt;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionCwdIssue {
pub session_file: Option<PathBuf>,
pub session_cwd: PathBuf,
pub fallback_cwd: PathBuf,
}
pub fn get_missing_session_cwd_issue(
session_file: Option<&Path>,
session_cwd: &Path,
fallback_cwd: &Path,
) -> Option<SessionCwdIssue> {
let session_file = session_file?;
if session_cwd.as_os_str().is_empty() {
return None;
}
if session_cwd.exists() {
return None;
}
Some(SessionCwdIssue {
session_file: Some(session_file.to_path_buf()),
session_cwd: session_cwd.to_path_buf(),
fallback_cwd: fallback_cwd.to_path_buf(),
})
}
pub fn format_missing_session_cwd_error(issue: &SessionCwdIssue) -> String {
let session_file = issue
.session_file
.as_ref()
.map(|p| format!("\nSession file: {}", p.display()))
.unwrap_or_default();
format!(
"Stored session working directory does not exist: {}{}\nCurrent working directory: {}",
issue.session_cwd.display(),
session_file,
issue.fallback_cwd.display()
)
}
pub fn format_missing_session_cwd_prompt(issue: &SessionCwdIssue) -> String {
format!(
"cwd from session file does not exist\n{}\n\ncontinue in current cwd\n{}",
issue.session_cwd.display(),
issue.fallback_cwd.display()
)
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MissingSessionCwdError {
pub issue: SessionCwdIssue,
}
impl fmt::Display for MissingSessionCwdError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&format_missing_session_cwd_error(&self.issue))
}
}
impl std::error::Error for MissingSessionCwdError {}
pub fn assert_session_cwd_exists(
session_file: Option<&Path>,
session_cwd: &Path,
fallback_cwd: &Path,
) -> Result<(), MissingSessionCwdError> {
match get_missing_session_cwd_issue(session_file, session_cwd, fallback_cwd) {
Some(issue) => Err(MissingSessionCwdError { issue }),
None => Ok(()),
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn no_session_file_is_ok() {
assert!(
get_missing_session_cwd_issue(None, Path::new("/whatever"), Path::new("/cwd"))
.is_none()
);
}
#[test]
fn existing_dir_is_ok() {
let dir = std::env::temp_dir();
assert!(get_missing_session_cwd_issue(Some(Path::new("/s.jsonl")), &dir, &dir).is_none());
}
#[test]
fn empty_stored_cwd_is_ok() {
assert!(get_missing_session_cwd_issue(
Some(Path::new("/s.jsonl")),
Path::new(""),
Path::new("/cwd")
)
.is_none());
}
#[test]
fn missing_dir_reports_issue() {
let missing = PathBuf::from("/definitely/not/here/xyzzy-1234");
let issue =
get_missing_session_cwd_issue(Some(Path::new("/s.jsonl")), &missing, Path::new("/cwd"))
.expect("issue");
assert_eq!(issue.session_cwd, missing);
assert!(format_missing_session_cwd_error(&issue).contains("does not exist"));
assert!(format_missing_session_cwd_prompt(&issue).contains("continue in current cwd"));
assert!(assert_session_cwd_exists(
Some(Path::new("/s.jsonl")),
&missing,
Path::new("/cwd")
)
.is_err());
}
}