use std::path::{Path, PathBuf};
use crate::ledger::location::Repo;
use crate::ledger::store::{self, LedgerStore, RefreshOutcome};
use crate::ledger::{fetch_keeping_local_reporting, push_reporting};
pub const CLOUD_SESSION_VAR: &str = "CLAUDE_CODE_REMOTE_SESSION_ID";
pub const MARKER_FILE: &str = "tsk-thread-id";
pub struct Session {
pub repo: Repo,
pub cloud_session: Option<String>,
pub git_dir: PathBuf,
pub store: Box<dyn LedgerStore>,
}
impl Session {
pub fn discover() -> Result<Session, String> {
let cwd = std::env::current_dir()
.map_err(|e| format!("error: could not read the current directory: {}", e))?;
let repo = Repo::discover(&cwd)?;
let git_dir = PathBuf::from(repo.git.run_line([
"rev-parse",
"--path-format=absolute",
"--git-dir",
])?);
let cloud_session = std::env::var(CLOUD_SESSION_VAR)
.ok()
.filter(|v| !v.is_empty());
let store = store::open(&cwd)?;
Ok(Session {
repo,
cloud_session,
git_dir,
store,
})
}
pub fn refresh(&self) -> Result<RefreshOutcome, String> {
fetch_keeping_local_reporting(self.store.as_ref())
}
pub fn push(&self, message: &str) -> Result<(), String> {
push_reporting(self.store.as_ref(), message).map(|_| ())
}
pub fn marker_path(&self) -> PathBuf {
self.git_dir.join(MARKER_FILE)
}
pub fn actor_urn(&self) -> String {
actor_urn(self.cloud_session.as_deref(), &self.git_dir)
}
}
pub fn actor_urn(cloud_session: Option<&str>, git_dir: &Path) -> String {
match cloud_session {
Some(id) => format!("urn:tsk:cloudsession:{}", id),
None => format!(
"urn:tsk:worktree:{}",
git_dir
.file_name()
.map(|n| n.to_string_lossy().into_owned())
.unwrap_or_default()
),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cloud_session_urn_names_the_session() {
assert_eq!(
actor_urn(Some("cse_01abc"), Path::new("/r/.git")),
"urn:tsk:cloudsession:cse_01abc"
);
}
#[test]
fn main_worktree_urn_is_dot_git() {
assert_eq!(
actor_urn(None, Path::new("/r/.git")),
"urn:tsk:worktree:.git"
);
}
#[test]
fn linked_worktree_urn_is_the_worktree_name() {
assert_eq!(
actor_urn(None, Path::new("/r/.git/worktrees/feature-x")),
"urn:tsk:worktree:feature-x"
);
}
}