#![allow(clippy::unwrap_used)]
use std::fs;
use std::process::Command;
use std::sync::Arc;
use mkit_cli::remote_dispatch::{pull_all, push_all};
use mkit_transport_memory::MemoryTransport;
fn mkit_bin() -> &'static str {
env!("CARGO_BIN_EXE_mkit")
}
fn run_in(cwd: &std::path::Path, args: &[&str]) -> std::process::Output {
let xdg = tempfile::tempdir().expect("xdg tempdir");
let out = Command::new(mkit_bin())
.args(args)
.current_dir(cwd)
.env("XDG_CONFIG_HOME", xdg.path())
.output()
.expect("spawn mkit");
drop(xdg);
out
}
#[test]
fn remote_add_memory_url_roundtrips_through_config() {
let td = tempfile::tempdir().unwrap();
assert!(run_in(td.path(), &["init"]).status.success());
let out = run_in(td.path(), &["remote", "add", "mkit+memory://example"]);
assert!(out.status.success(), "remote add failed: {out:?}");
let names = run_in(td.path(), &["remote"]);
assert!(names.status.success());
assert!(String::from_utf8(names.stdout).unwrap().contains("default"));
let out = run_in(td.path(), &["remote", "-v"]);
assert!(out.status.success());
let stdout = String::from_utf8(out.stdout).unwrap();
assert!(stdout.contains("mkit+memory://example"));
assert!(stdout.contains("(fetch)"));
assert!(stdout.contains("(push)"));
}
#[test]
fn remote_add_rejects_non_mkit_urls() {
let td = tempfile::tempdir().unwrap();
assert!(run_in(td.path(), &["init"]).status.success());
let out = run_in(td.path(), &["remote", "add", "https://example.com/repo"]);
assert!(!out.status.success(), "bare https:// must be rejected");
let stderr = String::from_utf8(out.stderr).unwrap();
assert!(
stderr.contains("mkit+<scheme>://"),
"error message should mention required URL prefix, got: {stderr}"
);
}
#[test]
fn push_then_pull_roundtrips_refs_via_memory_transport() {
let alice = tempfile::tempdir().unwrap();
let bob = tempfile::tempdir().unwrap();
assert!(run_in(alice.path(), &["init"]).status.success());
assert!(run_in(alice.path(), &["keygen"]).status.success());
assert!(run_in(bob.path(), &["init"]).status.success());
assert!(run_in(bob.path(), &["keygen"]).status.success());
fs::write(alice.path().join("a.txt"), b"hello from alice\n").unwrap();
assert!(run_in(alice.path(), &["add", "a.txt"]).status.success());
let out = run_in(alice.path(), &["commit", "-m", "alice-1"]);
assert!(out.status.success(), "alice commit failed: {out:?}");
let tx: Arc<MemoryTransport> = Arc::new(MemoryTransport::new());
let pushed = push_all(alice.path(), tx.as_ref()).expect("push");
assert!(pushed >= 1, "expected at least one ref pushed");
let pulled = pull_all(bob.path(), tx.as_ref(), "default", None).expect("pull");
assert_eq!(pulled, pushed, "push/pull ref count mismatch");
let alice_main = fs::read_to_string(alice.path().join(".mkit/refs/heads/main")).unwrap();
let bob_main = fs::read_to_string(bob.path().join(".mkit/refs/heads/main")).unwrap();
assert_eq!(
alice_main.trim(),
bob_main.trim(),
"bob's main should point at alice's HEAD commit"
);
}