#![allow(dead_code)]
use std::path::{Path, MAIN_SEPARATOR};
pub enum CrossProjectResumeResult {
NotCrossProject,
SameRepoWorktree { project_path: String },
DifferentRepo { command: String, project_path: String },
}
pub fn check_cross_project_resume(
log_project_path: Option<&str>,
show_all_projects: bool,
worktree_paths: &[String],
session_id: &str,
) -> CrossProjectResumeResult {
let current_cwd = get_original_cwd();
if !show_all_projects
|| log_project_path.is_none()
|| log_project_path.unwrap_or("") == current_cwd.as_str()
{
return CrossProjectResumeResult::NotCrossProject;
}
let project_path = log_project_path.unwrap_or("");
let user_type = std::env::var("USER_TYPE").unwrap_or_default();
if user_type != "ant" {
let command = format!(
"cd '{}' && claude --resume {}",
quote_path(project_path),
session_id
);
return CrossProjectResumeResult::DifferentRepo {
command,
project_path: project_path.to_string(),
};
}
let is_same_repo = worktree_paths.iter().any(|wt| {
project_path == wt.as_str() || project_path.starts_with(&format!("{wt}{MAIN_SEPARATOR}"))
});
if is_same_repo {
return CrossProjectResumeResult::SameRepoWorktree {
project_path: project_path.to_string(),
};
}
let command = format!(
"cd '{}' && claude --resume {}",
quote_path(project_path),
session_id
);
CrossProjectResumeResult::DifferentRepo {
command,
project_path: project_path.to_string(),
}
}
fn get_original_cwd() -> String {
std::env::var("AI_ORIGINAL_CWD")
.or_else(|_| std::env::var("AI_CODE_ORIGINAL_CWD"))
.unwrap_or_else(|_| {
std::env::current_dir()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_default()
})
}
fn quote_path(path: &str) -> String {
format!("'{}'", path.replace('\'', "'\\''"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_not_cross_project_same_path() {
let result = check_cross_project_resume(
Some("/same/path"),
true,
&[],
"session-123",
);
match result {
CrossProjectResumeResult::NotCrossProject => {}
_ => {
}
}
}
#[test]
fn test_not_cross_project_show_all_false() {
let result = check_cross_project_resume(
Some("/some/path"),
false,
&[],
"session-123",
);
assert!(matches!(result, CrossProjectResumeResult::NotCrossProject));
}
#[test]
fn test_different_repo_non_ant() {
let result = check_cross_project_resume(
Some("/different/project"),
true,
&["/other/worktree".to_string()],
"session-456",
);
if let CrossProjectResumeResult::DifferentRepo {
command,
project_path,
} = result
{
assert!(command.contains("/different/project"));
assert_eq!(project_path, "/different/project");
}
}
#[test]
fn test_quote_path() {
assert_eq!(quote_path("/simple/path"), "'/simple/path'");
assert_eq!(
quote_path("/path/with'single/quote"),
"'/path/with'\\''single/quote'"
);
}
}