migrate-guard 0.1.0

Detect and auto-renumber colliding sqlx migration version numbers across git branches.
Documentation
use migrate_guard::git::{branch_migration_files, local_branches, topic_new_files, GitCmd};
use std::path::Path;
use std::process::Command;

fn git(repo: &Path, args: &[&str]) {
    let ok = Command::new("git")
        .args(args)
        .current_dir(repo)
        .status()
        .unwrap()
        .success();
    assert!(ok, "git {args:?} failed");
}

fn write(repo: &Path, rel: &str, body: &str) {
    let p = repo.join(rel);
    std::fs::create_dir_all(p.parent().unwrap()).unwrap();
    std::fs::write(p, body).unwrap();
}

#[test]
fn detects_new_files_and_branch_versions() {
    let tmp = tempfile::tempdir().unwrap();
    let repo = tmp.path();
    git(repo, &["init", "-q", "-b", "main"]);
    git(repo, &["config", "user.email", "t@t.test"]);
    git(repo, &["config", "user.name", "t"]);

    write(repo, "migrations/0001_a.sql", "");
    git(repo, &["add", "-A"]);
    git(repo, &["commit", "-qm", "base"]);

    git(repo, &["checkout", "-qb", "feat"]);
    write(repo, "migrations/0002_b.sql", "");
    git(repo, &["add", "-A"]);
    git(repo, &["commit", "-qm", "feat"]);

    let gc = GitCmd::new(repo);
    let branches = local_branches(&gc).unwrap();
    assert!(branches.contains(&"main".to_string()) && branches.contains(&"feat".to_string()));

    let main_files = branch_migration_files(&gc, "main", Path::new("migrations")).unwrap();
    assert_eq!(
        main_files.iter().map(|f| f.version).collect::<Vec<_>>(),
        vec![1]
    );

    let new = topic_new_files(&gc, "main", Path::new("migrations")).unwrap();
    assert_eq!(new.iter().map(|f| f.version).collect::<Vec<_>>(), vec![2]);
}

#[test]
fn bad_base_ref_is_an_error_not_empty() {
    let tmp = tempfile::tempdir().unwrap();
    let repo = tmp.path();
    git(repo, &["init", "-q", "-b", "main"]);
    git(repo, &["config", "user.email", "t@t.test"]);
    git(repo, &["config", "user.name", "t"]);
    write(repo, "migrations/0001_a.sql", "");
    git(repo, &["add", "-A"]);
    git(repo, &["commit", "-qm", "base"]);

    let gc = GitCmd::new(repo);
    // A valid ref works.
    assert!(branch_migration_files(&gc, "main", std::path::Path::new("migrations")).is_ok());
    // A bogus ref must error, not return empty.
    assert!(
        branch_migration_files(&gc, "does-not-exist", std::path::Path::new("migrations")).is_err()
    );
}