Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

xtask/tests/medium_head.rs

//! `medium::head_of`: a checkout's `HEAD` read off `.git` with no git binary, the way
//! the ISO record names the kernel donor's revision. Detached, a loose ref, a packed
//! ref, and a linked worktree's `gitdir:` file with its `commondir`; anything
//! unreadable is `None`, never a guess.

use std::path::{Path, PathBuf};

use xtask::medium::head_of;

const A: &str = "1111111111111111111111111111111111111111";
const B: &str = "2222222222222222222222222222222222222222";

struct Scratch(PathBuf);

impl Drop for Scratch {
    fn drop(&mut self) {
        let _ = std::fs::remove_dir_all(&self.0);
    }
}

fn put(p: &Path, text: &str) {
    std::fs::create_dir_all(p.parent().unwrap()).unwrap();
    std::fs::write(p, text).unwrap();
}

#[test]
fn head_is_read_detached_loose_packed_and_through_a_worktree() {
    let base = std::env::temp_dir().join(format!("gunnar-head-of-{}", std::process::id()));
    let _ = std::fs::remove_dir_all(&base);
    let _s = Scratch(base.clone());

    let detached = base.join("detached");
    put(&detached.join(".git/HEAD"), &format!("{A}\n"));
    assert_eq!(head_of(&detached).as_deref(), Some(A));

    let loose = base.join("loose");
    put(&loose.join(".git/HEAD"), "ref: refs/heads/main\n");
    put(&loose.join(".git/refs/heads/main"), &format!("{B}\n"));
    assert_eq!(head_of(&loose).as_deref(), Some(B));

    let packed = base.join("packed");
    put(&packed.join(".git/HEAD"), "ref: refs/heads/main\n");
    put(
        &packed.join(".git/packed-refs"),
        &format!("# pack-refs with: peeled\n{A} refs/heads/other\n{B} refs/heads/main\n"),
    );
    assert_eq!(head_of(&packed).as_deref(), Some(B));

    // a linked worktree: `.git` is a file naming its gitdir, whose branch ref lives
    // in the common directory
    let main = base.join("main");
    put(&main.join(".git/refs/heads/topic"), &format!("{A}\n"));
    let wt_git = main.join(".git/worktrees/wt");
    put(&wt_git.join("HEAD"), "ref: refs/heads/topic\n");
    put(&wt_git.join("commondir"), "../..\n");
    let wt = base.join("wt");
    put(&wt.join(".git"), &format!("gitdir: {}\n", wt_git.display()));
    assert_eq!(head_of(&wt).as_deref(), Some(A));

    let dangling = base.join("dangling");
    put(&dangling.join(".git/HEAD"), "ref: refs/heads/gone\n");
    assert_eq!(head_of(&dangling), None, "a ref that exists nowhere");
    let bad_file = base.join("bad-file");
    put(&bad_file.join(".git"), "not a gitdir line\n");
    assert_eq!(head_of(&bad_file), None);
    assert_eq!(head_of(&base.join("nothing-here")), None);
}

/// `cargo xtask build --list` names the declared rows and builds nothing.
#[test]
fn build_list_names_the_declared_rows_without_building() {
    let root = xtask::guard::workspace_root();
    let rows = xtask::build::run(&root, &["--list".to_string()]).expect("the list");
    assert!(rows.iter().any(|r| r == "gunnar-server"), "{rows:?}");
    let declared = gunnar_recipe::emit_recipe::declared();
    assert!(rows.len() <= declared.variants.len());
    assert!(xtask::build::run(&root, &["--no-such-flag".to_string()]).is_err());
}