Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3af1cda8a6 | |||
| 31bcc61bcc |
@@ -270,6 +270,8 @@ pub unsafe extern "C" fn fff_create_instance2(
|
||||
watch,
|
||||
mode,
|
||||
cache_budget,
|
||||
allowlist: Vec::new(),
|
||||
denylist: Vec::new(),
|
||||
},
|
||||
) {
|
||||
return FffResult::err(&format!("Failed to init file picker: {}", e));
|
||||
@@ -924,6 +926,8 @@ pub unsafe extern "C" fn fff_restart_index(
|
||||
watch,
|
||||
mode,
|
||||
cache_budget: None,
|
||||
allowlist: Vec::new(),
|
||||
denylist: Vec::new(),
|
||||
},
|
||||
) {
|
||||
Ok(()) => FffResult::ok_empty(),
|
||||
|
||||
@@ -444,6 +444,10 @@ pub struct FilePickerOptions {
|
||||
pub cache_budget: Option<ContentCacheBudget>,
|
||||
/// When `false`, `new_with_shared_state` skips the background file watcher.
|
||||
pub watch: bool,
|
||||
/// Glob patterns to include during indexing. Empty = include all.
|
||||
pub allowlist: Vec<String>,
|
||||
/// Glob patterns to exclude during indexing. Applied after allowlist.
|
||||
pub denylist: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for FilePickerOptions {
|
||||
@@ -455,6 +459,8 @@ impl Default for FilePickerOptions {
|
||||
mode: FFFMode::default(),
|
||||
cache_budget: None,
|
||||
watch: true,
|
||||
allowlist: Vec::new(),
|
||||
denylist: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -471,6 +477,8 @@ pub struct FilePicker {
|
||||
enable_mmap_cache: bool,
|
||||
enable_content_indexing: bool,
|
||||
watch: bool,
|
||||
allowlist: Vec<String>,
|
||||
denylist: Vec<String>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for FilePicker {
|
||||
@@ -528,6 +536,14 @@ impl FilePicker {
|
||||
self.mode
|
||||
}
|
||||
|
||||
pub fn allowlist(&self) -> &[String] {
|
||||
&self.allowlist
|
||||
}
|
||||
|
||||
pub fn denylist(&self) -> &[String] {
|
||||
&self.denylist
|
||||
}
|
||||
|
||||
pub fn cache_budget(&self) -> &ContentCacheBudget {
|
||||
&self.cache_budget
|
||||
}
|
||||
@@ -717,6 +733,8 @@ impl FilePicker {
|
||||
enable_mmap_cache: options.enable_mmap_cache,
|
||||
enable_content_indexing: options.enable_content_indexing,
|
||||
watch: options.watch,
|
||||
allowlist: options.allowlist,
|
||||
denylist: options.denylist,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -745,6 +763,8 @@ impl FilePicker {
|
||||
let signals = picker.scan_signals();
|
||||
let scanned_files_counter = picker.scanned_files_counter();
|
||||
let path = picker.base_path.clone();
|
||||
let allowlist = picker.allowlist.clone();
|
||||
let denylist = picker.denylist.clone();
|
||||
|
||||
{
|
||||
let mut guard = shared_picker.write()?;
|
||||
@@ -768,6 +788,8 @@ impl FilePicker {
|
||||
auto_cache_budget: true,
|
||||
install_watcher: true,
|
||||
},
|
||||
allowlist,
|
||||
denylist,
|
||||
)
|
||||
.spawn();
|
||||
|
||||
@@ -796,6 +818,8 @@ impl FilePicker {
|
||||
&self.scanned_files_count,
|
||||
&empty_frecency,
|
||||
self.mode,
|
||||
&self.allowlist,
|
||||
&self.denylist,
|
||||
)?;
|
||||
|
||||
self.sync_data = sync;
|
||||
@@ -1711,12 +1735,40 @@ impl FileSync {
|
||||
synced_files_count: &Arc<AtomicUsize>,
|
||||
shared_frecency: &SharedFrecency,
|
||||
mode: FFFMode,
|
||||
allowlist: &[String],
|
||||
denylist: &[String],
|
||||
) -> Result<FileSync, Error> {
|
||||
use globset::{Glob, GlobSetBuilder};
|
||||
use ignore::WalkBuilder;
|
||||
|
||||
let scan_start = std::time::Instant::now();
|
||||
info!("SCAN: Starting filesystem walk and git status (async)");
|
||||
|
||||
// Build globsets for filtering
|
||||
let allowlist_set = if !allowlist.is_empty() {
|
||||
let mut builder = GlobSetBuilder::new();
|
||||
for pattern in allowlist {
|
||||
if let Ok(glob) = Glob::new(pattern) {
|
||||
builder.add(glob);
|
||||
}
|
||||
}
|
||||
builder.build().ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let denylist_set = if !denylist.is_empty() {
|
||||
let mut builder = GlobSetBuilder::new();
|
||||
for pattern in denylist {
|
||||
if let Ok(glob) = Glob::new(pattern) {
|
||||
builder.add(glob);
|
||||
}
|
||||
}
|
||||
builder.build().ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Walk files (the fast part, typically 2-3s even on huge repos).
|
||||
let is_git_repo = git_workdir.is_some();
|
||||
let bg_threads = BACKGROUND_THREAD_POOL.current_num_threads();
|
||||
@@ -1749,6 +1801,8 @@ impl FileSync {
|
||||
let pairs = &pairs;
|
||||
let counter = Arc::clone(synced_files_count);
|
||||
let base_path = base_path.to_path_buf();
|
||||
let allowlist_set = allowlist_set.clone();
|
||||
let denylist_set = denylist_set.clone();
|
||||
|
||||
Box::new(move |result| {
|
||||
let Ok(entry) = result else {
|
||||
@@ -1768,6 +1822,20 @@ impl FileSync {
|
||||
return ignore::WalkState::Continue;
|
||||
}
|
||||
|
||||
// Apply allowlist/denylist filtering
|
||||
if let Ok(rel_path) = path.strip_prefix(&base_path) {
|
||||
if let Some(ref allow_set) = allowlist_set {
|
||||
if !allow_set.is_match(rel_path) {
|
||||
return ignore::WalkState::Continue;
|
||||
}
|
||||
}
|
||||
if let Some(ref deny_set) = denylist_set {
|
||||
if deny_set.is_match(rel_path) {
|
||||
return ignore::WalkState::Continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let metadata = entry.metadata().ok();
|
||||
let (file_item, rel_path) =
|
||||
FileItem::new_from_walk(path, &base_path, None, metadata.as_ref());
|
||||
|
||||
@@ -57,6 +57,8 @@ pub(crate) struct ScanJob {
|
||||
/// side. Reset to 0 at scan start, incremented per-file by the
|
||||
/// walker. Shared `Arc` so the UI polls the same atomic.
|
||||
scanned_files_counter: Arc<AtomicUsize>,
|
||||
allowlist: Vec<String>,
|
||||
denylist: Vec<String>,
|
||||
}
|
||||
|
||||
impl ScanJob {
|
||||
@@ -80,6 +82,8 @@ impl ScanJob {
|
||||
let signals = picker.scan_signals();
|
||||
let scanned_files_counter = picker.scanned_files_counter();
|
||||
let base_path = picker.base_path().to_path_buf();
|
||||
let allowlist = picker.allowlist().to_vec();
|
||||
let denylist = picker.denylist().to_vec();
|
||||
|
||||
let new_scan_config = ScanConfig {
|
||||
warmup: picker.has_mmap_cache(),
|
||||
@@ -99,6 +103,8 @@ impl ScanJob {
|
||||
config: new_scan_config,
|
||||
shared_picker: shared_picker.clone(),
|
||||
shared_frecency: shared_frecency.clone(),
|
||||
allowlist,
|
||||
denylist,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -110,6 +116,8 @@ impl ScanJob {
|
||||
signals: ScanSignals,
|
||||
scanned_files_counter: Arc<AtomicUsize>,
|
||||
config: ScanConfig,
|
||||
allowlist: Vec<String>,
|
||||
denylist: Vec<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
shared_picker,
|
||||
@@ -119,6 +127,8 @@ impl ScanJob {
|
||||
signals,
|
||||
scanned_files_counter,
|
||||
config,
|
||||
allowlist,
|
||||
denylist,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +150,8 @@ impl ScanJob {
|
||||
signals,
|
||||
scanned_files_counter,
|
||||
config,
|
||||
allowlist,
|
||||
denylist,
|
||||
} = self;
|
||||
|
||||
let _scanning = ScanningGuard::new(&signals, config.install_watcher);
|
||||
@@ -157,6 +169,8 @@ impl ScanJob {
|
||||
&scanned_files_counter,
|
||||
&shared_frecency,
|
||||
mode,
|
||||
&allowlist,
|
||||
&denylist,
|
||||
) {
|
||||
Ok(sync) => sync,
|
||||
Err(e) => {
|
||||
|
||||
@@ -269,6 +269,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
cache_budget: args
|
||||
.max_cached_files
|
||||
.map(fff::ContentCacheBudget::new_for_repo),
|
||||
allowlist: Vec::new(),
|
||||
denylist: Vec::new(),
|
||||
},
|
||||
)
|
||||
.map_err(|e| format!("Failed to init file picker: {}", e))?;
|
||||
|
||||
Reference in New Issue
Block a user