use super::common; use ansi_term::Color; use std::ffi::OsStr; use std::fs::OpenOptions; use std::io::{self, Error, ErrorKind, Write}; use std::process::{Command, Stdio}; #[test] fn show_nothing_on_empty_dir() -> io::Result<()> { let repo_dir = tempfile::tempdir()?; let output = common::render_module("git_state") .arg("--path") .arg(repo_dir.path()) .output()?; let actual = String::from_utf8(output.stdout).unwrap(); let expected = ""; assert_eq!(expected, actual); repo_dir.close() } #[test] fn shows_rebasing() -> io::Result<()> { let repo_dir = create_repo_with_conflict()?; let path = path_str(&repo_dir)?; run_git_cmd(&["rebase", "other-branch"], Some(path), false)?; let output = common::render_module("git_state") .arg("--path") .arg(&path) .output()?; let actual = String::from_utf8(output.stdout).unwrap(); let mut expected = Color::Yellow.bold().paint("(REBASING 1/1)").to_string(); expected.push(' '); assert_eq!(expected, actual); Ok(()) } #[test] fn shows_merging() -> io::Result<()> { let repo_dir = create_repo_with_conflict()?; let path = path_str(&repo_dir)?; run_git_cmd(&["merge", "other-branch"], Some(path), false)?; let output = common::render_module("git_state") .arg("--path") .arg(&path) .output()?; let actual = String::from_utf8(output.stdout).unwrap(); let mut expected = Color::Yellow.bold().paint("(MERGING)").to_string(); expected.push(' '); assert_eq!(expected, actual); Ok(()) } #[test] fn shows_cherry_picking() -> io::Result<()> { let repo_dir = create_repo_with_conflict()?; let path = path_str(&repo_dir)?; run_git_cmd(&["cherry-pick", "other-branch"], Some(path), false)?; let output = common::render_module("git_state") .arg("--path") .arg(&path) .output()?; let actual = String::from_utf8(output.stdout).unwrap(); let mut expected = Color::Yellow.bold().paint("(CHERRY-PICKING)").to_string(); expected.push(' '); assert_eq!(expected, actual); Ok(()) } #[test] fn shows_bisecting() -> io::Result<()> { let repo_dir = create_repo_with_conflict()?; let path = path_str(&repo_dir)?; run_git_cmd(&["bisect", "start"], Some(path), false)?; let output = common::render_module("git_state") .arg("--path") .arg(&path) .output()?; let actual = String::from_utf8(output.stdout).unwrap(); let mut expected = Color::Yellow.bold().paint("(BISECTING)").to_string(); expected.push(' '); assert_eq!(expected, actual); Ok(()) } #[test] fn shows_reverting() -> io::Result<()> { let repo_dir = create_repo_with_conflict()?; let path = path_str(&repo_dir)?; run_git_cmd(&["revert", "--no-commit", "HEAD~1"], Some(path), false)?; let output = common::render_module("git_state") .arg("--path") .arg(&path) .output()?; let actual = String::from_utf8(output.stdout).unwrap(); let mut expected = Color::Yellow.bold().paint("(REVERTING)").to_string(); expected.push(' '); assert_eq!(expected, actual); Ok(()) } fn run_git_cmd(args: A, dir: Option<&str>, expect_ok: bool) -> io::Result<()> where A: IntoIterator, S: AsRef, { let mut command = Command::new("git"); command .args(args) .stdout(Stdio::null()) .stderr(Stdio::null()) .stdin(Stdio::null()); if let Some(dir) = dir { command.current_dir(dir); } let status = command.status()?; if expect_ok && !status.success() { Err(Error::from(ErrorKind::Other)) } else { Ok(()) } } fn create_repo_with_conflict() -> io::Result { let repo_dir = tempfile::tempdir()?; let path = path_str(&repo_dir)?; let conflicted_file = repo_dir.path().join("the_file"); let write_file = |text: &str| { let mut file = OpenOptions::new() .write(true) .create(true) .truncate(true) .open(&conflicted_file)?; write!(file, "{}", text) }; // Initialize a new git repo run_git_cmd(&["init", "--quiet", path], None, true)?; // Set local author info run_git_cmd( &["config", "--local", "user.email", "starship@example.com"], Some(path), true, )?; run_git_cmd( &["config", "--local", "user.name", "starship"], Some(path), true, )?; // Write a file on master and commit it write_file("Version A")?; run_git_cmd(&["add", "the_file"], Some(path), true)?; run_git_cmd(&["commit", "--message", "Commit A"], Some(path), true)?; // Switch to another branch, and commit a change to the file run_git_cmd(&["checkout", "-b", "other-branch"], Some(path), true)?; write_file("Version B")?; run_git_cmd( &["commit", "--all", "--message", "Commit B"], Some(path), true, )?; // Switch back to master, and commit a third change to the file run_git_cmd(&["checkout", "master"], Some(path), true)?; write_file("Version C")?; run_git_cmd( &["commit", "--all", "--message", "Commit C"], Some(path), true, )?; Ok(repo_dir) } fn path_str(repo_dir: &tempfile::TempDir) -> io::Result<&str> { repo_dir .path() .to_str() .ok_or_else(|| Error::from(ErrorKind::Other)) }