quinjet 0.0.76

A fast, live, keyboard-first Git source-control interface for the terminal
use super::*;

#[test]
fn a_selected_commit_diff_excludes_earlier_and_later_changes() {
    let source = initialized_repository();
    let base = source.git(&["rev-parse", "HEAD"]);
    source.git(&["switch", "-c", "feature/rocket"]);
    fs::write(source.0.join("earlier.txt"), "earlier\n").unwrap();
    source.git(&["add", "."]);
    source.git(&["commit", "--message=earlier"]);
    fs::write(source.0.join("selected.txt"), "selected\n").unwrap();
    source.git(&["add", "."]);
    source.git(&["commit", "--message=selected"]);
    let selected = source.git(&["rev-parse", "HEAD"]);
    fs::write(source.0.join("later.txt"), "later\n").unwrap();
    source.git(&["add", "."]);
    source.git(&["commit", "--message=later"]);
    let head = source.git(&["rev-parse", "HEAD"]);
    let before = source.git(&["show-ref"]);
    let repository = Repository {
        root: source.0.clone(),
        github_cli: None,
        diff_highlighting: true,
    };
    let request = PullRequest {
        base_oid: base,
        head_oid: head,
        ..PullRequest::default()
    };
    let prepared = repository
        .prepare_pull_request_commit_diff(&request, &selected, |_| {})
        .unwrap();
    assert_eq!(prepared.index.files.len(), 1);
    assert_eq!(prepared.index.files[0].path, Path::new("selected.txt"));
    assert_eq!(prepared.index.files[0].counts.unwrap().additions, 1);
    let document = prepared.diff_file(Path::new("selected.txt")).unwrap();
    assert!(
        document
            .lines
            .iter()
            .any(|line| line.text().contains("selected"))
    );
    assert_eq!(source.git(&["show-ref"]), before);
    assert_eq!(source.git(&["status", "--porcelain"]), "");
}

#[test]
fn merge_commit_diff_uses_its_first_parent() {
    let source = initialized_repository();
    let base = source.git(&["rev-parse", "HEAD"]);
    source.git(&["switch", "-c", "side"]);
    fs::write(source.0.join("side.txt"), "side\n").unwrap();
    source.git(&["add", "."]);
    source.git(&["commit", "--message=side"]);
    source.git(&["switch", "main"]);
    fs::write(source.0.join("main.txt"), "main\n").unwrap();
    source.git(&["add", "."]);
    source.git(&["commit", "--message=main"]);
    let parent = source.git(&["rev-parse", "HEAD"]);
    source.git(&["merge", "--no-ff", "side", "--message=merge"]);
    let selected = source.git(&["rev-parse", "HEAD"]);
    let repository = Repository {
        root: source.0.clone(),
        github_cli: None,
        diff_highlighting: true,
    };
    let request = PullRequest {
        base_oid: base,
        head_oid: selected.clone(),
        ..PullRequest::default()
    };
    let prepared = repository
        .prepare_pull_request_commit_diff(&request, &selected, |_| {})
        .unwrap();
    assert_eq!(prepared.merge_base, parent);
    assert_eq!(prepared.index.files.len(), 1);
    assert_eq!(prepared.index.files[0].path, Path::new("side.txt"));
}

#[cfg(unix)]
#[test]
fn remote_commit_older_than_the_initial_fetch_window_is_fetched_exactly() {
    use std::os::unix::fs::PermissionsExt;

    let source = initialized_repository();
    let base = source.git(&["rev-parse", "HEAD"]);
    let remote = test_directory("commit-remote.git");
    source.git(&[
        "init",
        "--bare",
        "--initial-branch=main",
        remote.0.to_str().unwrap(),
    ]);
    source.git(&["remote", "add", "test-origin", remote.0.to_str().unwrap()]);
    source.git(&["push", "test-origin", "main:main"]);
    source.git(&["switch", "-c", "feature/rocket"]);
    fs::write(source.0.join("selected.txt"), "selected\n").unwrap();
    source.git(&["add", "."]);
    source.git(&["commit", "--message=selected"]);
    let selected = source.git(&["rev-parse", "HEAD"]);
    for index in 0..70 {
        fs::write(source.0.join("later.txt"), format!("later {index}\n")).unwrap();
        source.git(&["add", "."]);
        source.git(&["commit", "--message=later"]);
    }
    let head = source.git(&["rev-parse", "HEAD"]);
    source.git(&["push", "test-origin", "HEAD:refs/pull/7/head"]);
    let opened = test_directory("commit-opened");
    source.git(&[
        "clone",
        "--depth=1",
        &format!("file://{}", remote.0.display()),
        opened.0.to_str().unwrap(),
    ]);
    let fake_gh = opened.0.join("fake-gh");
    fs::write(&fake_gh, format!("#!/bin/sh\nprintf '%s\\n' '{base}'\n")).unwrap();
    fs::set_permissions(&fake_gh, fs::Permissions::from_mode(0o755)).unwrap();
    let repository = Repository {
        root: opened.0.clone(),
        github_cli: Some(fake_gh),
        diff_highlighting: true,
    };
    assert!(!repository.has_commit(&selected));
    let before = opened.git(&["show-ref"]);
    let mut request = pull_request(
        super::repository(
            "acme/widget",
            &format!("file://{}", remote.0.display()),
            &[],
        ),
        7,
    );
    request.base_oid = base;
    request.head_oid = head.clone();
    let prepared = repository
        .prepare_pull_request_commit_diff(&request, &selected, |_| {})
        .unwrap();
    assert_eq!(prepared.head, selected);
    assert_eq!(prepared.index.files.len(), 1);
    assert_eq!(prepared.index.files[0].path, Path::new("selected.txt"));
    assert_eq!(opened.git(&["show-ref"]), before);

    source.git(&["push", "test-origin", "HEAD:refs/heads/feature/rocket"]);
    let shallow = test_directory("commit-shallow-head");
    source.git(&[
        "clone",
        "--depth=1",
        "--branch=feature/rocket",
        &format!("file://{}", remote.0.display()),
        shallow.0.to_str().unwrap(),
    ]);
    let repository = Repository {
        root: shallow.0.clone(),
        github_cli: None,
        diff_highlighting: true,
    };
    assert!(repository.has_commit(&head));
    let prepared = repository
        .prepare_pull_request_commit_diff(&request, &head, |_| {})
        .unwrap();
    assert_eq!(prepared.head, head);
    assert_eq!(prepared.index.files.len(), 1);
    assert_eq!(prepared.index.files[0].path, Path::new("later.txt"));
}

#[test]
fn an_initial_commit_in_a_shallow_repository_uses_local_objects_without_mutation() {
    let source = initialized_repository();
    let root = source.git(&["rev-parse", "HEAD"]);
    let shallow_path = source.0.join(".git/shallow");
    fs::write(&shallow_path, format!("{root}\n")).unwrap();
    let repository = Repository {
        root: source.0.clone(),
        github_cli: Some(source.0.join("unavailable-gh")),
        diff_highlighting: true,
    };
    let request = PullRequest {
        base_oid: root.clone(),
        head_oid: root.clone(),
        ..PullRequest::default()
    };
    let before = source.git(&["show-ref"]);
    let prepared = repository
        .prepare_pull_request_commit_diff(&request, &root, |_| {})
        .unwrap();
    assert_eq!(prepared.index.files[0].path, Path::new("README.md"));
    assert_eq!(prepared.index.files[0].counts.unwrap().additions, 1);
    let document = prepared.diff_file(Path::new("README.md")).unwrap();
    assert!(
        document
            .lines
            .iter()
            .any(|line| line.text().contains("base"))
    );
    assert_eq!(source.git(&["show-ref"]), before);
    assert_eq!(
        fs::read_to_string(shallow_path).unwrap(),
        format!("{root}\n")
    );
}