use std::fs;
use std::path::PathBuf;
use tempfile::tempdir;
use scryer_db::{Project, ScryerDb};
use scryer_engine::{ChangeDetector, EngineService, FileChange};
#[cfg(unix)]
#[tokio::test]
async fn test_unreadable_file_is_not_reported_deleted() -> anyhow::Result<()> {
use std::os::unix::fs::PermissionsExt;
let temp = tempdir()?;
let root = temp.path();
fs::create_dir_all(root.join("src"))?;
fs::write(root.join("src/lib.rs"), "pub fn a() {}\n")?;
fs::write(root.join("src/b.rs"), "pub fn b() {}\n")?;
let db = ScryerDb::new_in_memory().await?;
let project = {
let mut conn = db.lock().await;
Project::create()
.slug("hasher-read-error".to_string())
.root_path(root.to_string_lossy().to_string())
.default_branch("main".to_string())
.is_active(true)
.created_at("2026-10-07T00:00:00Z".to_string())
.updated_at("2026-10-07T00:00:00Z".to_string())
.exec(&mut *conn)
.await?
};
EngineService::new(db.clone())
.index_project(project.id, root)
.await?;
let locked = root.join("src/b.rs");
fs::set_permissions(&locked, fs::Permissions::from_mode(0o000))?;
if fs::read(&locked).is_ok() {
return Ok(());
}
let scanned = vec![PathBuf::from("src/lib.rs"), PathBuf::from("src/b.rs")];
let report = ChangeDetector::detect_changes(&db, project.id, root, &scanned).await?;
fs::set_permissions(&locked, fs::Permissions::from_mode(0o644))?;
assert_eq!(report.deleted_count, 0, "{:?}", report.changes);
assert!(
!report
.changes
.iter()
.any(|c| matches!(c, FileChange::Deleted { .. }))
);
Ok(())
}