use std::fs; use std::io::Write; use std::os::unix::fs::PermissionsExt; mod common; use common::Environment; fn create_environment() -> anyhow::Result<(Environment, String)> { let (e, root) = Environment::scooby_gang_bootstrap()?; // Create a bare repository at our scratch location. let scratch = e.scratch_state().display().to_string(); e.git(&["init", "--bare", &scratch])?; // Set us as update hook. let update_hook = e.scratch_state().join("hooks").join("update"); let mut update = fs::File::create(&update_hook)?; writeln!(update, "#!/bin/sh")?; writeln!(update)?; writeln!(update, "{} update-hook --trust-root={} \"$@\"", Environment::sq_git_path()?.display(), root)?; // Make file executable. let metadata = update.metadata()?; let mut permissions = metadata.permissions(); permissions.set_mode(0o755); update.set_permissions(permissions)?; // Add as origin. e.git(&["remote", "add", "origin", &scratch])?; Ok((e, root)) } #[test] fn update_hook() -> anyhow::Result<()> { let (e, _root) = create_environment()?; let p = e.git_state(); // Bookmark. e.git(&["checkout", "-b", "test-base"])?; // Willow's code-signing key can change the source code, as she // has the sign-commit right. e.git(&["checkout", "-b", "test-willow"])?; fs::write(p.join("a"), "Aller Anfang ist schwer.")?; e.git(&["add", "a"])?; e.git(&[ "commit", "-m", "First change.", &format!("-S{}", e.willow.fingerprint), ])?; e.git(&["push", "origin", "test-willow"])?; // Reset. e.git(&["checkout", "test-base"])?; e.git(&["clean", "-fdx"])?; // Her release key also has that right, because she needs it in // order to give it to new users. e.git(&["checkout", "-b", "test-willow-release"])?; fs::write(p.join("a"), "Aller Anfang ist schwer. -- Schiller")?; e.git(&["add", "a"])?; e.git(&[ "commit", "-m", "Someone is not quite correct on the internet.", &format!("-S{}", e.willow_release.fingerprint), ])?; e.git(&["push", "origin", "test-willow-release"])?; // Reset. e.git(&["checkout", "test-base"])?; e.git(&["clean", "-fdx"])?; // Buffy's cert was not yet added, so she may not sign commits. e.git(&["checkout", "-b", "test-buffy"])?; fs::write(p.join("a"), "Aller Anfang ist schwer, unless you are super strong!1")?; e.git(&["add", "a"])?; e.git(&[ "commit", "-m", "Well, actually...", &format!("-S{}", e.buffy.fingerprint), ])?; if let Ok((_, stderr)) = e.git(&["push", "origin", "test-buffy"]) { eprintln!("stderr: {}", String::from_utf8_lossy(&stderr)); } assert!(e.git(&["push", "origin", "test-buffy"]).is_err()); Ok(()) } #[test] fn rebase() -> anyhow::Result<()> { let (e, _root) = create_environment()?; let p = e.git_state(); // Bookmark. e.git(&["checkout", "-b", "test-base"])?; // There are two threads of development. Let's start the first // one. e.git(&["checkout", "-b", "feature-one"])?; fs::write(p.join("a"), "Aller Anfang ist schwer.")?; e.git(&["add", "a"])?; e.git(&[ "commit", "-m", "First change of the first feature.", &format!("-S{}", e.willow.fingerprint), ])?; e.git(&["push", "origin", "feature-one"])?; // Reset. e.git(&["checkout", "test-base"])?; e.git(&["clean", "-fdx"])?; // There are two threads of development. Let's start the second // one. e.git(&["checkout", "-b", "feature-two"])?; fs::write(p.join("b"), "And now for something completely different.")?; e.git(&["add", "b"])?; e.git(&[ "commit", "-m", "First change of the second feature.", &format!("-S{}", e.willow.fingerprint), ])?; e.git(&["push", "origin", "feature-two"])?; // Now we rebase feature-two on top of feature-one and push it to // update the remote feature-two branch. e.git(&[ "rebase", "feature-one", &format!("-S{}", e.willow.fingerprint), ])?; e.git(&["push", "origin", "--force", "feature-two"])?; Ok(()) }