use crate::core::registry::{IndexHandle, IndexId};
use crate::service::walker::{walk_source_files_with_options, WalkOptions};
use dashmap::DashMap;
use std::path::PathBuf;
use std::sync::atomic::AtomicU32;
use std::sync::Arc;
use std::time::Instant;
use super::progress::ReindexProgress;
use super::quarantine::ReindexQuarantine;
use super::semaphore::BACKGROUND_QUEUE_DEPTH;
pub fn spawn_reindex(handle: Arc<IndexHandle>, progress: Arc<ReindexProgress>, force: bool) {
spawn_reindex_with_cleanup(handle, progress, force, None, None, None, true, None);
}
pub(super) fn collect_files_to_index(handle: &IndexHandle) -> crate::service::walker::WalkResult {
let include_paths: Vec<PathBuf> = if handle.include_paths.is_empty() {
vec![handle.root_path.clone()]
} else {
handle.include_paths.clone()
};
let mut walked_files: Vec<PathBuf> = Vec::new();
let mut total_skipped_dirs: usize = 0;
let walk_opts = WalkOptions {
include_docs: handle.include_docs,
respect_gitignore: handle.respect_gitignore,
extra_skip_dirs: handle.extra_skip_dirs.clone(),
data_file_max_bytes: handle.data_file_max_bytes,
};
for subtree in &include_paths {
let w = walk_source_files_with_options(subtree, &walk_opts);
walked_files.extend(w.files);
total_skipped_dirs = total_skipped_dirs.saturating_add(w.skipped_dirs);
}
if !handle.exclude_globs.is_empty() {
let excludes = handle.exclude_globs.clone();
walked_files.retain(|p| !crate::core::repo_config::path_matches_any_glob(p, &excludes));
}
if !handle.extensions.is_empty() {
let allowed = handle.extensions.clone();
walked_files.retain(|p| {
p.extension()
.and_then(|e| e.to_str())
.map(|e| allowed.iter().any(|x| x.eq_ignore_ascii_case(e)))
.unwrap_or(false)
});
}
if !handle.path_filter.is_empty() {
let patterns = handle.path_filter.clone();
let root =
std::fs::canonicalize(&handle.root_path).unwrap_or_else(|_| handle.root_path.clone());
walked_files.retain(|p| crate::core::registry::path_matches_filter(p, &root, &patterns));
}
walked_files.sort();
walked_files.dedup();
crate::service::walker::WalkResult {
files: walked_files,
skipped_dirs: total_skipped_dirs,
}
}
#[allow(clippy::too_many_arguments)]
pub fn spawn_reindex_with_cleanup(
handle: Arc<IndexHandle>,
progress: Arc<ReindexProgress>,
force: bool,
cleanup_map: Option<Arc<DashMap<IndexId, Arc<ReindexProgress>>>>,
aborted_map: Option<Arc<DashMap<IndexId, Instant>>>,
embedderd_pid_slot: Option<Arc<AtomicU32>>,
priority: bool,
quarantine: Option<ReindexQuarantine>,
) {
use std::sync::atomic::Ordering as AtomicOrd;
if !priority {
BACKGROUND_QUEUE_DEPTH.fetch_add(1, AtomicOrd::Relaxed);
}
tokio::spawn(super::runner::run_reindex(
handle,
progress,
force,
cleanup_map,
aborted_map,
embedderd_pid_slot,
priority,
quarantine,
));
}