use std::path::Path;
use super::types::RebaseResult;
use crate::cli;
use crate::errors::GitCallError;
pub async fn rebase(
repo: &Path,
file: &Path,
line: usize,
rev_a: &str,
rev_b: &str,
) -> Result<RebaseResult, GitCallError> {
let blame = cli::blame_reverse(repo, file, line, rev_a, rev_b).await?;
let path = if blame.path.as_os_str().is_empty() {
file.to_path_buf()
} else {
blame.path
};
Ok(RebaseResult {
path,
line: blame.line,
rev: blame.rev,
})
}
#[cfg(test)]
mod tests {
use super::rebase;
use std::path::{Path, PathBuf};
fn run(repo: &Path, args: &[&str]) -> String {
let output = std::process::Command::new("git")
.arg("-C")
.arg(repo)
.arg("-c")
.arg("user.email=dev@fluidattacks.com")
.arg("-c")
.arg("user.name=dev")
.args(args)
.output()
.unwrap();
assert!(output.status.success(), "git {args:?} failed");
String::from_utf8(output.stdout).unwrap().trim().to_owned()
}
#[tokio::test]
async fn a_line_that_moved_to_a_renamed_file_is_reported_at_its_new_home() {
let dir = tempfile::tempdir().unwrap();
std::env::set_var("GIT_CONFIG_GLOBAL", dir.path().join("gitconfig"));
let repo = dir.path().join("repo");
std::fs::create_dir_all(&repo).unwrap();
run(&repo, &["init", "-q"]);
std::fs::write(repo.join("old.txt"), b"first\nsecond\nthird\n").unwrap();
run(&repo, &["add", "-A"]);
run(&repo, &["commit", "-q", "-m", "add"]);
let rev_a = run(&repo, &["rev-parse", "HEAD"]);
run(&repo, &["mv", "old.txt", "new.txt"]);
run(&repo, &["commit", "-q", "-m", "rename"]);
let head = run(&repo, &["rev-parse", "HEAD"]);
let result = rebase(&repo, Path::new("old.txt"), 2, &rev_a, "HEAD")
.await
.unwrap();
assert_eq!(result.path, PathBuf::from("new.txt"));
assert_eq!(result.line, 2);
assert_eq!(result.rev, head);
}
}