use std::fs;
use lantern::ingest::{IngestOptions, ingest_path, ingest_path_with};
use lantern::store::Store;
use tempfile::tempdir;
fn uri_list(report: &lantern::ingest::IngestReport) -> Vec<String> {
let mut v: Vec<String> = report.ingested.iter().map(|s| s.uri.clone()).collect();
v.sort();
v
}
#[test]
fn honours_patterns_from_lantern_ignore() {
let root = tempdir().unwrap();
let store_dir = root.path().join("store");
let mut store = Store::initialize(&store_dir).unwrap();
let data = root.path().join("data");
fs::create_dir_all(data.join("logs")).unwrap();
fs::create_dir_all(data.join("docs")).unwrap();
fs::write(data.join("docs/keep.md"), "# keep me").unwrap();
fs::write(data.join("logs/trace.md"), "# noisy").unwrap();
fs::write(data.join("scratch.md"), "# scratch").unwrap();
fs::write(
data.join(".lantern-ignore"),
"# skip the log directory and top-level scratch\nlogs/\nscratch.md\n",
)
.unwrap();
let report = ingest_path(&mut store, &data).unwrap();
let paths: Vec<String> = report
.ingested
.iter()
.map(|s| s.uri.clone())
.collect::<Vec<_>>();
assert_eq!(report.ingested.len(), 1, "unexpected ingest: {paths:?}");
assert!(report.ingested[0].uri.ends_with("docs/keep.md"));
assert!(
report.ignored >= 2,
"expected at least 2 ignored entries, got {} (uris: {:?})",
report.ignored,
paths
);
}
#[test]
fn negation_pattern_unignores_file() {
let root = tempdir().unwrap();
let mut store = Store::initialize(&root.path().join("store")).unwrap();
let data = root.path().join("data");
fs::create_dir_all(&data).unwrap();
fs::write(data.join("a.md"), "a").unwrap();
fs::write(data.join("b.md"), "b").unwrap();
fs::write(data.join("c.md"), "c").unwrap();
fs::write(data.join(".lantern-ignore"), "*.md\n!b.md\n").unwrap();
let report = ingest_path(&mut store, &data).unwrap();
let uris = uri_list(&report);
assert_eq!(uris.len(), 1, "unexpected ingest: {uris:?}");
assert!(uris[0].ends_with("b.md"));
}
#[test]
fn defaults_apply_without_lantern_ignore() {
let root = tempdir().unwrap();
let mut store = Store::initialize(&root.path().join("store")).unwrap();
let data = root.path().join("project");
fs::create_dir_all(data.join("src")).unwrap();
fs::create_dir_all(data.join("target/debug")).unwrap();
fs::create_dir_all(data.join("node_modules/left-pad")).unwrap();
fs::create_dir_all(data.join(".git")).unwrap();
fs::write(data.join("src/main.rs"), "fn main() {}").unwrap();
fs::write(data.join("target/debug/build.log"), "should be ignored").unwrap();
fs::write(data.join("target/debug/build.rs"), "compiled code").unwrap();
fs::write(
data.join("node_modules/left-pad/index.js"),
"module.exports = 1;",
)
.unwrap();
fs::write(data.join(".git/HEAD"), "ref: refs/heads/main").unwrap();
let report = ingest_path(&mut store, &data).unwrap();
let uris = uri_list(&report);
assert_eq!(
uris.len(),
1,
"only src/main.rs should be ingested, got: {uris:?}"
);
assert!(uris[0].ends_with("src/main.rs"));
assert!(report.ignored > 0);
}
#[test]
fn no_ignore_flag_bypasses_rules() {
let root = tempdir().unwrap();
let mut store = Store::initialize(&root.path().join("store")).unwrap();
let data = root.path().join("project");
fs::create_dir_all(data.join("target")).unwrap();
fs::create_dir_all(data.join("src")).unwrap();
fs::write(data.join("src/main.rs"), "fn main() {}").unwrap();
fs::write(data.join("target/build.rs"), "compiled").unwrap();
fs::write(data.join(".lantern-ignore"), "src/\n").unwrap();
let report = ingest_path_with(&mut store, &data, &IngestOptions { no_ignore: true }).unwrap();
let uris = uri_list(&report);
assert_eq!(
uris.len(),
2,
"both files should be ingested, got: {uris:?}"
);
assert_eq!(report.ignored, 0);
assert!(uris.iter().any(|u| u.ends_with("src/main.rs")));
assert!(uris.iter().any(|u| u.ends_with("target/build.rs")));
}
#[test]
fn single_file_target_is_checked_against_rules() {
let root = tempdir().unwrap();
let mut store = Store::initialize(&root.path().join("store")).unwrap();
let data = root.path().join("project");
fs::create_dir_all(&data).unwrap();
let secret = data.join("secret.md");
fs::write(&secret, "hush").unwrap();
fs::write(data.join(".lantern-ignore"), "secret.md\n").unwrap();
let report = ingest_path(&mut store, &secret).unwrap();
assert!(report.ingested.is_empty());
assert_eq!(report.ignored, 1);
let bypass = ingest_path_with(&mut store, &secret, &IngestOptions { no_ignore: true }).unwrap();
assert_eq!(bypass.ingested.len(), 1);
}