grit-lib 0.5.16

Core library for the grit Git implementation
Documentation
//! Shallow `deepen` on a single-commit repository (system `git` parity).

use std::path::Path;
use std::process::Command;

use grit_lib::config::environment::RepositoryOptions;
use grit_lib::objects::{ObjectId, ObjectKind};
use grit_lib::repo::{InitOptions, Repository};
use grit_lib::revwalk::rev_list::shallow_grafts_for_upload_pack_deepen;

fn init_single_commit_bare(dir: &Path) -> (Repository, ObjectId) {
    Repository::init(
        dir,
        &InitOptions::new()
            .with_bare(true)
            .with_initial_branch("main".to_owned())
            .with_ref_storage(grit_lib::refs::ref_storage::RefStorageFormat::Files),
    )
    .expect("init");
    let repo = Repository::open(dir, &RepositoryOptions::empty()).expect("open");
    let tree = ObjectId::from_hex("4b825dc642cb6eb9a060e54bf8d69288fbee4904").expect("empty tree");
    let commit_body = format!(
        "tree {}\nauthor T <t@x> 1 +0000\ncommitter T <t@x> 1 +0000\n\nonly\n",
        tree.to_hex()
    );
    let tip = repo
        .odb()
        .write_loose_materialize(ObjectKind::Commit, commit_body.as_bytes())
        .expect("commit");
    grit_lib::refs::write_ref(dir, "refs/heads/main", &tip).expect("ref");
    (repo, tip)
}

fn git_clone_depth(bare: &Path, dest: &Path, depth: u32) -> bool {
    Command::new("git")
        .args([
            "clone",
            "-q",
            "--depth",
            &depth.to_string(),
            &format!("file://{}", bare.display()),
            dest.to_str().expect("utf8 dest"),
        ])
        .env("GIT_CONFIG_GLOBAL", "/dev/null")
        .env("GIT_CONFIG_SYSTEM", "/dev/null")
        .status()
        .map(|s| s.success())
        .unwrap_or(false)
}

fn clone_has_shallow_file(clone_git_dir: &Path) -> bool {
    clone_git_dir.join("shallow").is_file()
}

#[test]
fn deepen_one_on_root_commit_returns_shallow_border() {
    let dir = tempfile::tempdir().expect("tempdir");
    let (repo, tip) = init_single_commit_bare(dir.path());

    let borders = shallow_grafts_for_upload_pack_deepen(&repo, &[tip], &[], 1);
    assert_eq!(
        borders,
        vec![tip],
        "deepen 1 on a single commit must advertise that commit as shallow"
    );
}

#[test]
fn deepen_beyond_history_does_not_advertise_shallow_border() {
    let dir = tempfile::tempdir().expect("tempdir");
    let (repo, tip) = init_single_commit_bare(dir.path());

    let borders = shallow_grafts_for_upload_pack_deepen(&repo, &[tip], &[], 5);
    assert!(
        borders.is_empty(),
        "deepen larger than history must not mark the root shallow (complete history)"
    );
}

#[test]
fn single_commit_shallow_borders_match_git_clone_depth() {
    let dir = tempfile::tempdir().expect("tempdir");
    let (repo, tip) = init_single_commit_bare(dir.path());

    let grit_depth_one = shallow_grafts_for_upload_pack_deepen(&repo, &[tip], &[], 1);
    let grit_depth_five = shallow_grafts_for_upload_pack_deepen(&repo, &[tip], &[], 5);
    assert_eq!(grit_depth_one.len(), 1);
    assert!(grit_depth_five.is_empty());

    let d1 = dir.path().join("git-d1");
    let d5 = dir.path().join("git-d5");
    if !git_clone_depth(dir.path(), &d1, 1) || !git_clone_depth(dir.path(), &d5, 5) {
        eprintln!("SKIP: system git clone unavailable");
        return;
    }
    assert!(
        clone_has_shallow_file(&d1.join(".git")),
        "git clone --depth 1 must write .git/shallow for a one-commit repo"
    );
    assert!(
        !clone_has_shallow_file(&d5.join(".git")),
        "git clone --depth 5 must not write .git/shallow when history is complete"
    );
}