Skip to main content

sandogasa_depfilter/
lib.rs

1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3//! RPM dependency filtering for cross-branch analysis.
4//!
5//! Provides functions to classify RPM dependency strings as
6//! auto-generated or otherwise ignorable when comparing packages
7//! across Fedora/EPEL branches.
8
9/// Return `true` if `dep` is a solib-style dependency (contains `.so.`).
10///
11/// This is a broad check that matches both soname deps like
12/// `libbpf.so.1()(64bit)` and symbol version deps like
13/// `libc.so.6(GLIBC_2.38)(64bit)`.
14pub fn is_solib_dep(dep: &str) -> bool {
15    dep.contains(".so.")
16}
17
18/// Return `true` if `dep` is a solib symbol version dependency.
19///
20/// These have non-empty content in the first parentheses, e.g.
21/// `libc.so.6(GLIBC_2.38)(64bit)`.  They are auto-generated at
22/// RPM build time and regenerated when the package is rebuilt on
23/// the target branch, so they are not meaningful for cross-branch
24/// installability checks.
25///
26/// Soname deps like `libbpf.so.1()(64bit)` return `false` — they
27/// are also auto-generated but match the soversion, so changes
28/// reflect real ABI bumps that matter for installability.
29pub fn is_solib_symbol_dep(dep: &str) -> bool {
30    let Some(so_pos) = dep.find(".so.") else {
31        return false;
32    };
33    let after_so = &dep[so_pos..];
34    let Some(open) = after_so.find('(') else {
35        return false;
36    };
37    let inside = &after_so[open + 1..];
38    let Some(close) = inside.find(')') else {
39        return false;
40    };
41    close > 0
42}
43
44/// Return `true` if `dep` is an RPM-internal or auto-generated
45/// dependency that is not meaningful for installability checks.
46///
47/// This covers:
48/// - `rpmlib(...)` — RPM feature gates
49/// - `auto(...)` — auto-generated deps
50/// - `config(...)` — config file deps
51pub fn is_rpm_internal_dep(dep: &str) -> bool {
52    dep.starts_with("rpmlib(") || dep.starts_with("auto(") || dep.starts_with("config(")
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn solib_positive() {
61        assert!(is_solib_dep("libc.so.6()(64bit)"));
62        assert!(is_solib_dep("libc.so.6(GLIBC_2.38)(64bit)"));
63        assert!(is_solib_dep("libm.so.6(GLIBC_2.29)(64bit)"));
64        assert!(is_solib_dep("libbpf.so.1()(64bit)"));
65    }
66
67    #[test]
68    fn solib_negative() {
69        assert!(!is_solib_dep("glibc"));
70        assert!(!is_solib_dep("glibc-devel"));
71        assert!(!is_solib_dep("libfoo"));
72        assert!(!is_solib_dep("pkgconfig(dracut)"));
73        assert!(!is_solib_dep("rpmlib(CompressedFileNames)"));
74    }
75
76    #[test]
77    fn solib_symbol_positive() {
78        assert!(is_solib_symbol_dep("libc.so.6(GLIBC_2.38)(64bit)"));
79        assert!(is_solib_symbol_dep("libm.so.6(GLIBC_2.29)(64bit)"));
80        assert!(is_solib_symbol_dep("libpthread.so.0(GLIBC_2.12)(64bit)"));
81    }
82
83    #[test]
84    fn solib_symbol_negative_soname() {
85        // Soname deps have empty first parens — also auto-generated
86        // but match the soversion, so changes are meaningful.
87        assert!(!is_solib_symbol_dep("libbpf.so.1()(64bit)"));
88        assert!(!is_solib_symbol_dep("libc.so.6()(64bit)"));
89    }
90
91    #[test]
92    fn solib_symbol_negative_non_solib() {
93        assert!(!is_solib_symbol_dep("glibc"));
94        assert!(!is_solib_symbol_dep("pkgconfig(dracut)"));
95        assert!(!is_solib_symbol_dep("rpmlib(CompressedFileNames)"));
96    }
97
98    #[test]
99    fn rpm_internal_positive() {
100        assert!(is_rpm_internal_dep("rpmlib(CompressedFileNames)"));
101        assert!(is_rpm_internal_dep("rpmlib(PayloadIsZstd)"));
102        assert!(is_rpm_internal_dep("auto(gcc)"));
103        assert!(is_rpm_internal_dep("config(glibc)"));
104    }
105
106    #[test]
107    fn rpm_internal_negative() {
108        assert!(!is_rpm_internal_dep("glibc"));
109        assert!(!is_rpm_internal_dep("libc.so.6()(64bit)"));
110        assert!(!is_rpm_internal_dep("pkgconfig(dracut)"));
111    }
112}