guix-scheme 0.1.0

Read, edit, and generate Guix Scheme files (channels.scm, system config.scm) from Rust
Documentation
use guix_scheme::validate;

#[test]
fn url_accepts_known_schemes() {
    for u in [
        "https://example.org/foo.git",
        "http://example.org/foo.git",
        "git://example.org/foo.git",
        "ssh://git@example.org/foo.git",
        "file:///srv/repos/foo.git",
    ] {
        assert!(validate::url(u).is_ok(), "{u}");
    }
}

#[test]
fn url_rejects_unknown_scheme_control_deceptive() {
    assert!(validate::url("javascript:alert(1)").is_err());
    assert!(validate::url("https://example.org/foo\nbar").is_err());
    assert!(validate::url("https://example.org/\u{202E}tig.git").is_err());
    assert!(validate::url(&format!("https://e.org/{}", "a".repeat(2048))).is_err());
}

#[test]
fn branch_charset_and_length() {
    assert!(validate::branch("feature/foo-1.2+x_y").is_ok());
    assert!(validate::branch("").is_err());
    assert!(validate::branch(&"a".repeat(201)).is_err());
    assert!(validate::branch("no spaces").is_err());
}

#[test]
fn commit_and_fingerprint_rules() {
    assert!(validate::introduction_commit("9edb3f66fd807b096b48283debdcddccfea34bad").is_ok());
    assert!(validate::introduction_commit("abc").is_err()); // < 7
    assert!(validate::introduction_commit("xyz4567").is_err()); // non-hex
    assert!(validate::introduction_fingerprint(
        "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA"
    )
    .is_ok());
    assert!(validate::introduction_fingerprint("short").is_err());
}

#[test]
fn channel_name_accepts_scheme_safe() {
    assert!(validate::channel_name("good-name_1.2").is_ok());
    assert!(validate::channel_name("guix").is_ok());
    assert!(validate::channel_name("non+guix").is_ok());
}

#[test]
fn channel_name_rejects_pathological() {
    assert!(validate::channel_name("").is_err());
    assert!(validate::channel_name("bad name").is_err());
    assert!(validate::channel_name("nope;(drop)").is_err());
    assert!(validate::channel_name("with/slash").is_err());
}