use std::path::Path;
#[derive(Debug, Clone)]
pub struct SessionCwdIssue {
pub session_file: Option<String>,
pub session_cwd: String,
pub fallback_cwd: String,
}
pub trait SessionCwdSource {
fn get_cwd(&self) -> Option<String>;
fn get_session_file(&self) -> Option<String>;
}
pub fn get_missing_session_cwd_issue(
source: &dyn SessionCwdSource,
fallback_cwd: &str,
) -> Option<SessionCwdIssue> {
let session_file = source.get_session_file()?;
let session_cwd = source.get_cwd()?;
if Path::new(&session_cwd).is_dir() {
return None;
}
Some(SessionCwdIssue {
session_file: Some(session_file),
session_cwd,
fallback_cwd: fallback_cwd.to_string(),
})
}
pub fn format_missing_session_cwd_error(issue: &SessionCwdIssue) -> String {
let session_file_line = issue
.session_file
.as_ref()
.map(|f| format!("\nSession file: {}", f))
.unwrap_or_default();
format!(
"Stored session working directory does not exist: {}{}\\nCurrent working directory: {}",
issue.session_cwd, session_file_line, issue.fallback_cwd
)
}
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, issue.fallback_cwd
)
}
#[derive(Debug)]
pub struct MissingSessionCwdError {
pub issue: SessionCwdIssue,
}
impl std::fmt::Display for MissingSessionCwdError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", format_missing_session_cwd_error(&self.issue))
}
}
impl std::error::Error for MissingSessionCwdError {}
pub fn assert_session_cwd_exists(
source: &dyn SessionCwdSource,
fallback_cwd: &str,
) -> Result<(), MissingSessionCwdError> {
if let Some(issue) = get_missing_session_cwd_issue(source, fallback_cwd) {
return Err(MissingSessionCwdError { issue });
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
struct MockSource {
cwd: Option<String>,
file: Option<String>,
}
impl SessionCwdSource for MockSource {
fn get_cwd(&self) -> Option<String> {
self.cwd.clone()
}
fn get_session_file(&self) -> Option<String> {
self.file.clone()
}
}
#[test]
fn no_issue_when_no_session_file() {
let src = MockSource {
cwd: Some("/nonexistent".into()),
file: None,
};
assert!(get_missing_session_cwd_issue(&src, "/tmp").is_none());
}
#[test]
fn no_issue_when_cwd_exists() {
let src = MockSource {
cwd: Some("/tmp".into()),
file: Some("/tmp/session.json".into()),
};
assert!(get_missing_session_cwd_issue(&src, "/tmp").is_none());
}
#[test]
fn error_format() {
let issue = SessionCwdIssue {
session_file: Some("/tmp/s.json".into()),
session_cwd: "/gone".into(),
fallback_cwd: "/tmp".into(),
};
let msg = format_missing_session_cwd_error(&issue);
assert!(msg.contains("/gone"));
assert!(msg.contains("/tmp/s.json"));
}
#[test]
fn prompt_format() {
let issue = SessionCwdIssue {
session_file: None,
session_cwd: "/gone".into(),
fallback_cwd: "/here".into(),
};
let prompt = format_missing_session_cwd_prompt(&issue);
assert!(prompt.contains("/gone"));
assert!(prompt.contains("/here"));
}
}