#![cfg_attr(coverage_nightly, coverage(off))]
pub(crate) const PMAT_OWNED_STATE_PREFIXES: &[&str] = &[".pmat/", ".pmat-work/", ".pmat-metrics/"];
pub(crate) fn is_pmat_owned_state(porcelain_line: &str) -> bool {
let Some(after_status) = porcelain_line.get(3..) else {
return false;
};
let path = after_status
.rsplit(" -> ")
.next()
.unwrap_or(after_status)
.trim();
PMAT_OWNED_STATE_PREFIXES
.iter()
.any(|p| path.starts_with(p))
}
#[cfg(test)]
mod tests {
use super::is_pmat_owned_state;
#[test]
fn matches_owned_dirs() {
assert!(is_pmat_owned_state(" M .pmat/context.db"));
assert!(is_pmat_owned_state(" M .pmat/context.idx/manifest.json"));
assert!(is_pmat_owned_state(" M .pmat/project.toml"));
assert!(is_pmat_owned_state("M .pmat-work/ledger.jsonl"));
assert!(is_pmat_owned_state("?? .pmat-work/PMAT-154/evidence.json"));
assert!(is_pmat_owned_state(
"A .pmat-metrics/commit-abc123-meta.json"
));
}
#[test]
fn skips_user_files() {
assert!(!is_pmat_owned_state(" M src/lib.rs"));
assert!(!is_pmat_owned_state("M docs/roadmaps/roadmap.yaml"));
assert!(!is_pmat_owned_state(" M Cargo.toml"));
assert!(!is_pmat_owned_state(" M .pmat-baseline.json"));
assert!(!is_pmat_owned_state(" M pmat/context.db"));
}
#[test]
fn rename_destination() {
assert!(is_pmat_owned_state(
"R src/old.rs -> .pmat-work/archived.rs"
));
assert!(!is_pmat_owned_state("R .pmat-work/old.rs -> src/new.rs"));
}
#[test]
fn short_line_defense() {
assert!(!is_pmat_owned_state(""));
assert!(!is_pmat_owned_state("XY"));
assert!(!is_pmat_owned_state("XY "));
}
#[test]
fn full_github_sync_scenario() {
let status = concat!(
"## master...origin/master\n",
"M .pmat-work/ledger.jsonl\n",
" M .pmat/context.db\n",
" M .pmat/context.idx/manifest.json\n",
"A .pmat-metrics/commit-abc123-meta.json\n",
" M src/lib.rs\n",
"?? untracked.txt"
);
let dirty_count = status
.lines()
.skip(1)
.filter(|l| !l.is_empty() && !l.starts_with("??"))
.filter(|l| !is_pmat_owned_state(l))
.count();
assert_eq!(
dirty_count, 1,
"Only user-owned src/lib.rs should count; pmat state excluded"
);
}
}