use std::fs;
use std::process::Command;
use tempfile::TempDir;
fn bin() -> Command {
let mut c = Command::new(env!("CARGO_BIN_EXE_sqlite-graphrag"));
c.env_remove("OPENROUTER_API_KEY");
c.env_remove("SQLITE_GRAPHRAG_API_KEY");
c
}
fn write_pair(root: &std::path::Path) {
let a = root.join("a");
let b = root.join("b");
fs::create_dir_all(&a).unwrap();
fs::create_dir_all(&b).unwrap();
fs::write(a.join("shared-topic.md"), "# one\n\nbody-alpha\n").unwrap();
fs::write(b.join("shared-topic.md"), "# two\n\nbody-beta-updated\n").unwrap();
}
#[test]
fn same_derived_name_without_force_merge_does_not_overwrite() {
let tmp = TempDir::new().unwrap();
let db = tmp.path().join("t.sqlite");
write_pair(tmp.path());
let init = bin()
.args(["init", "--db"])
.arg(&db)
.arg("-q")
.status()
.expect("init");
assert!(init.success(), "init must succeed");
let out1 = bin()
.args(["ingest", "--db"])
.arg(&db)
.arg(tmp.path().join("a"))
.args([
"--pattern",
"*.md",
"-q",
"--no-input",
"--llm-backend",
"none",
])
.output()
.expect("ingest a");
assert!(
out1.status.success(),
"first ingest: {}",
String::from_utf8_lossy(&out1.stderr)
);
let out2 = bin()
.args(["ingest", "--db"])
.arg(&db)
.arg(tmp.path().join("b"))
.args([
"--pattern",
"*.md",
"-q",
"--no-input",
"--llm-backend",
"none",
])
.output()
.expect("ingest b");
let body = bin()
.args(["read", "--db"])
.arg(&db)
.args(["--name", "shared-topic", "--format", "raw", "-q"])
.output()
.expect("read");
assert!(
body.status.success(),
"read: {}",
String::from_utf8_lossy(&body.stderr)
);
let text = String::from_utf8_lossy(&body.stdout);
assert!(
text.contains("body-alpha"),
"without --force-merge the first body must survive; got: {text:?}; stderr2={}",
String::from_utf8_lossy(&out2.stderr)
);
assert!(
!text.contains("body-beta-updated"),
"without --force-merge must not silently overwrite with second file"
);
}
#[test]
fn same_derived_name_with_force_merge_updates_body() {
let tmp = TempDir::new().unwrap();
let db = tmp.path().join("t.sqlite");
write_pair(tmp.path());
assert!(bin()
.args(["init", "--db"])
.arg(&db)
.arg("-q")
.status()
.unwrap()
.success());
assert!(bin()
.args(["ingest", "--db"])
.arg(&db)
.arg(tmp.path().join("a"))
.args([
"--pattern",
"*.md",
"-q",
"--no-input",
"--llm-backend",
"none"
])
.status()
.unwrap()
.success());
let out2 = bin()
.args(["ingest", "--db"])
.arg(&db)
.arg(tmp.path().join("b"))
.args([
"--pattern",
"*.md",
"--force-merge",
"-q",
"--no-input",
"--llm-backend",
"none",
])
.output()
.expect("ingest force-merge");
assert!(
out2.status.success(),
"force-merge ingest: {}",
String::from_utf8_lossy(&out2.stderr)
);
let body = bin()
.args(["read", "--db"])
.arg(&db)
.args(["--name", "shared-topic", "--format", "raw", "-q"])
.output()
.expect("read");
assert!(body.status.success());
let text = String::from_utf8_lossy(&body.stdout);
assert!(
text.contains("body-beta-updated"),
"with --force-merge the body must update; got: {text:?}"
);
}