use std::{
io,
path::{Path, PathBuf},
};
use tracing::warn;
#[derive(Debug, thiserror::Error)]
pub enum ScannerError {
#[error("IO operation failed: {0}")]
IoOps(#[from] std::io::Error),
#[error("IO error accessing path {path}: {source}")]
Io {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Filesystem walk configuration/build error: {0}")]
WalkBuildError(#[from] ignore::Error),
#[error("Failed to get metadata for path {path}: {source}")]
MetadataError {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Failed to read symlink target for path {path}: {source}")]
SymlinkReadError {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Failed to canonicalize root path {path}: {source}")]
CanonicalizeError {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Root path not found or is not a directory: {0}")]
InvalidRoot(PathBuf),
#[error("Failed to strip prefix '{prefix}' from path '{path}'")]
StripPrefixError { prefix: PathBuf, path: PathBuf },
#[error("Error occurred during parallel processing phase: {0}")]
ParallelProcessingError(String),
#[error("Error during final tree construction: {0}")]
TreeConstructionError(String),
#[error("Scan was cancelled")]
Cancelled,
#[error("Failed to send path from walker to processor channel (receiver disconnected)")]
ChannelSendError,
#[error("Failed to build Rayon thread pool: {0}")]
ThreadPoolBuildError(#[from] rayon::ThreadPoolBuildError),
#[error("Walker thread panicked")]
WalkerThreadPanic,
#[error("Format: {0}")]
FmtScanError(#[from] crate::fs::FsFmtError),
}
pub fn map_meta_err(path: &Path, err: io::Error) -> ScannerError {
warn!(path=%path.display(), error=%err, "Metadata error occurred");
ScannerError::MetadataError {
path: path.to_path_buf(),
source: err,
}
}
pub fn map_symlink_err(path: &Path, err: io::Error) -> ScannerError {
warn!(path=%path.display(), error=%err, "Symlink Read Error occurred");
ScannerError::SymlinkReadError {
path: path.to_path_buf(),
source: err,
}
}