//! `oxy git colocate` (oxygenhub#355, part two): a `.git` beside `.oxy`, //! kept up to date after every oxy command, so Git tools read an Oxygen //! checkout; oxy never takes `.git` as content. use std::path::Path; use std::process::Command; fn oxy(dir: &Path, home: &Path, args: &[&str]) -> (bool, String) { let out = Command::new(env!("CARGO_BIN_EXE_oxy")) .arg("--plain") .args(args) .current_dir(dir) .env("OXY_HOME", home) .env("NO_COLOR", "1") .output() .unwrap(); ( out.status.success(), format!( "{}{}", String::from_utf8_lossy(&out.stdout), String::from_utf8_lossy(&out.stderr) ), ) } fn git(dir: &Path, args: &[&str]) -> String { let out = Command::new("git") .args(args) .current_dir(dir) .env("GIT_CONFIG_NOSYSTEM", "1") .env("HOME", dir) .output() .unwrap(); assert!( out.status.success(), "git {args:?}: {}", String::from_utf8_lossy(&out.stderr) ); String::from_utf8_lossy(&out.stdout).trim().to_string() } #[test] fn a_colocated_git_follows_the_bookmark() { if Command::new("git").arg("--version").output().is_err() { eprintln!("git not installed; skipping"); return; } let tmp = tempfile::tempdir().unwrap(); let home = tmp.path().join("home"); std::fs::create_dir_all(&home).unwrap(); let r = tmp.path().join("r"); assert!(oxy(tmp.path(), &home, &["init", r.to_str().unwrap()]).0); assert!( oxy( &r, &home, &[ "identity", "create", "--name", "Ada", "--email", "ada@example.org" ] ) .0 ); std::fs::write(r.join("a.txt"), "one\n").unwrap(); assert!(oxy(&r, &home, &["commit", "-m", "first"]).0); let (ok, out) = oxy(&r, &home, &["git", "colocate"]); assert!(ok, "{out}"); assert!(r.join(".git/HEAD").exists()); assert_eq!(git(&r, &["log", "--format=%s"]), "first"); assert_eq!(git(&r, &["symbolic-ref", "HEAD"]), "refs/heads/main"); assert_eq!( git(&r, &["status", "--porcelain"]), "", "Git sees no difference, and not .oxy either" ); let (_, status) = oxy(&r, &home, &["status"]); assert!( !status.contains(".git"), "oxy never takes .git as content: {status}" ); // An oxy commit shows in Git without asking. std::fs::write(r.join("a.txt"), "one\ntwo\n").unwrap(); assert_eq!( git(&r, &["status", "--porcelain"]), "M a.txt", "uncommitted work shows as modified" ); assert!(oxy(&r, &home, &["commit", "-m", "second"]).0); assert_eq!(git(&r, &["log", "--format=%s"]), "second\nfirst"); assert_eq!(git(&r, &["status", "--porcelain"]), ""); assert_eq!(git(&r, &["show", "HEAD:a.txt"]), "one\ntwo"); // Off: no more updates, the .git stays. assert!(oxy(&r, &home, &["git", "colocate", "--off"]).0); std::fs::write(r.join("b.txt"), "b\n").unwrap(); assert!(oxy(&r, &home, &["commit", "-m", "third"]).0); assert_eq!( git(&r, &["log", "--format=%s"]), "second\nfirst", "no longer followed" ); assert!(r.join(".git/HEAD").exists()); }