//! oxygen#162: a subrepo pin moved by work inside the subrepo is a change //! the parent's next commit records; `oxy status` and `oxy commit` say so, //! and say when a subrepo holds uncommitted edits of its own. use std::path::Path; use std::process::Command; fn oxy(dir: &Path, home: &Path, args: &[&str]) -> (i32, 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(); let text = format!( "{}{}", String::from_utf8_lossy(&out.stdout), String::from_utf8_lossy(&out.stderr) ); (out.status.code().unwrap_or(-1), text) } fn ok(dir: &Path, home: &Path, args: &[&str]) -> String { let (code, out) = oxy(dir, home, args); assert_eq!(code, 0, "oxy {args:?}: {out}"); out } #[test] fn moved_pins_and_edits_inside_subrepos_are_named() { let tmp = tempfile::tempdir().unwrap(); let t = tmp.path(); let home = t.join("home"); std::fs::create_dir_all(&home).unwrap(); ok( t, &home, &[ "identity", "create", "--name", "Ada", "--email", "ada@example.org", ], ); // The subrepo's own repository, with one change. let lib = t.join("lib"); ok(t, &home, &["init", lib.to_str().unwrap()]); std::fs::write(lib.join("lib.txt"), "one\n").unwrap(); ok(&lib, &home, &["commit", "-m", "lib one"]); // The parent pins it. let app = t.join("app"); ok(t, &home, &["init", app.to_str().unwrap()]); std::fs::write(app.join("app.txt"), "app\n").unwrap(); ok( &app, &home, &["submodule", "add", lib.to_str().unwrap(), "deps/lib"], ); ok(&app, &home, &["commit", "-m", "app with lib"]); let quiet = ok(&app, &home, &["status"]); assert!(!quiet.contains("Subrepo pins"), "{quiet}"); // Edits inside the subrepo, not committed there: named, not a pin move. let inner = app.join("deps/lib"); std::fs::write(inner.join("lib.txt"), "two\n").unwrap(); let st = ok(&app, &home, &["status"]); assert!( st.contains("Subrepo pins") && st.contains("uncommitted edits inside it"), "{st}" ); assert!(!st.contains("pin moved"), "{st}"); // Committed inside: the pin has moved, and a bare commit says it records it. ok(&inner, &home, &["commit", "-m", "lib two"]); let st = ok(&app, &home, &["status"]); assert!(st.contains("deps/lib") && st.contains("pin moved"), "{st}"); std::fs::write(app.join("app.txt"), "app 2\n").unwrap(); let by_path = ok(&app, &home, &["commit", "-m", "app only", "app.txt"]); assert!( !by_path.contains("recorded subrepo"), "a commit by path leaves the pin out: {by_path}" ); let bare = ok(&app, &home, &["commit", "-m", "everything"]); assert!( bare.contains("recorded subrepo deps/lib's pin moving") && bare.contains("a pin bump"), "{bare}" ); let after = ok(&app, &home, &["status"]); assert!(!after.contains("Subrepo pins"), "recorded: {after}"); }