knott 0.1.17

Fast Rust package manager helper for Arch Linux repos and the AUR
Documentation
use crate::version::vercmp;
use std::cmp::Ordering;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VersionOp {
    Eq,
    Ge,
    Le,
    Gt,
    Lt,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Dependency {
    pub raw: String,
    pub name: String,
    pub op: Option<VersionOp>,
    pub version: Option<String>,
}

pub fn parse_dependency(raw: &str) -> Dependency {
    let trimmed = raw.trim();

    for (token, op) in [
        (">=", VersionOp::Ge),
        ("<=", VersionOp::Le),
        ("=", VersionOp::Eq),
        (">", VersionOp::Gt),
        ("<", VersionOp::Lt),
    ] {
        if let Some((name, version)) = trimmed.split_once(token) {
            return Dependency {
                raw: trimmed.to_string(),
                name: name.trim().to_string(),
                op: Some(op),
                version: Some(version.trim().to_string()),
            };
        }
    }

    Dependency {
        raw: trimmed.to_string(),
        name: trimmed.to_string(),
        op: None,
        version: None,
    }
}

pub fn dependency_satisfied(local_version: &str, dep: &Dependency) -> bool {
    let Some(op) = dep.op else {
        return true;
    };
    let Some(required) = dep.version.as_deref() else {
        return true;
    };

    matches!(
        (op, vercmp(local_version, required)),
        (VersionOp::Eq, Ordering::Equal)
            | (VersionOp::Ge, Ordering::Equal | Ordering::Greater)
            | (VersionOp::Le, Ordering::Equal | Ordering::Less)
            | (VersionOp::Gt, Ordering::Greater)
            | (VersionOp::Lt, Ordering::Less)
    )
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parses_versioned_dependency() {
        let dep = parse_dependency("openssl>=3.0");
        assert_eq!(dep.name, "openssl");
        assert_eq!(dep.op, Some(VersionOp::Ge));
        assert_eq!(dep.version.as_deref(), Some("3.0"));
    }

    #[test]
    fn checks_dependency_versions() {
        let dep = parse_dependency("foo>=1.2-1");
        assert!(dependency_satisfied("1.2-2", &dep));
        assert!(!dependency_satisfied("1.1-9", &dep));
    }
}