From 6221f107a2cd02d17af1c35dc4fe9a9affcb3db4 Mon Sep 17 00:00:00 2001 From: Isaac Oscar Gariano Date: Sun, 31 Aug 2025 02:35:32 +1000 Subject: [PATCH 1/3] Fixed some grammar errors in README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8675925..fd831ef 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ cmake ## **Integration tests** -Integration tests runs inside docker images tagged `local/cnf-ci-zypper`, `local/cnf-ci-dnf`, and `local/cnf-ci-dnf5`. these are built as a part of Github Action and can be built locally with: +Integration tests run inside docker images tagged `local/cnf-ci-zypper`, `local/cnf-ci-dnf`, and `local/cnf-ci-dnf5`; these are built as a part of a Github Action and can be built locally with: ```.sh for pm in zypper dnf dnf5; do @@ -85,12 +85,13 @@ for pm in zypper dnf dnf5; do done ``` -The testing itself is wrapped in [bats](https://github.com/bats-core/bats-core) and in order to make it run, one needs to initialize the git submodules (`git submodule update --init`). Then tests can be executed using a following command +The testing itself is wrapped in [bats](https://github.com/bats-core/bats-core) and in order to make it run, one needs to initialize the git submodules (`git submodule update --init`). Then tests can be executed using following command ```.sh ./test/bats/bin/bats ./test/ ``` > ```.log +> test.bats > ✓ zypper root: installed /usr/bin/rpm > ✓ zypper root: installed /usr/sbin/sysctl > ✓ zypper root: not installed xnake From 6ad9b6fccd6453d04f2916935ef06451a1acfa97 Mon Sep 17 00:00:00 2001 From: Isaac Oscar Gariano Date: Sun, 31 Aug 2025 02:37:31 +1000 Subject: [PATCH 2/3] Change rust code to say 'dnf' instead of 'dnf4' This is for consistency with the name of the command that is executed, and the CI tests. --- src/main.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 95a633d..025f863 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ mod pool; const ZYPPER_REPO_GLOB: &str = "/etc/zypp/repos.d/*.repo"; // Default value of the reposdir configuration directory -const DNF4_REPOS_GLOBS: [&str; 3] = [ +const DNF_REPOS_GLOBS: [&str; 3] = [ "/etc/dnf/repos.d/*.repo", "/etc/yum.repos.d/*.repo", "/etc/distro.repos.d/*.repo" @@ -33,7 +33,7 @@ const DNF5_REPOS_GLOBS: [&str; 4] = [ #[derive(Clone, Copy)] pub enum PackageManager { Zypper, - Dnf4, + Dnf, Dnf5, } pub struct SolvInput { @@ -77,16 +77,16 @@ fn main() { } let pm = if Path::exists(Path::new("/usr/bin/dnf5")) { - // Use DNF5 if it's installed from the openSUSE repo (since zypper is the default, someone is only likely to have dnf5 installed if they want to use it) + // Use dnf5 if it's installed from the openSUSE repo (since zypper is the default, someone is only likely to have dnf5 installed if they want to use it) PackageManager::Dnf5 } else if Path::exists(Path::new("/usr/bin/dnf")) { - // Use DNF4 if it's installed, but dnf5 isn't + // Use an old dnf if it's installed, but dnf5 isn't // (in case a dnf5 user symlinks /usr/bin/dnf to /usr/bin/dnf5, this goes after the dnf5 check) - PackageManager::Dnf4 + PackageManager::Dnf } else if Path::exists(Path::new("/usr/bin/zypper")) { PackageManager::Zypper } else { - println!("Neither /usr/bin/dnf5, /usr/bin/dnf, norr /usr/bin/zypper could be found."); + println!("Neither /usr/bin/dnf5, /usr/bin/dnf, nor /usr/bin/zypper could be found."); exit(127); }; @@ -153,7 +153,7 @@ fn search_in_repos<'a>( ); match pm { PackageManager::Zypper => println!(" sudo zypper install {}\n", suggested_package), - PackageManager::Dnf4 => println!(" sudo dnf install {}\n", suggested_package), + PackageManager::Dnf => println!(" sudo dnf install {}\n", suggested_package), PackageManager::Dnf5 => println!(" sudo dnf5 install {}\n", suggested_package), } Ok(()) @@ -163,7 +163,7 @@ fn load_repos<'a>(pm: PackageManager) -> Result, ErrorKind<'a>> { let mut repos: Vec = Vec::new(); let globs = match pm { PackageManager::Zypper => &[ZYPPER_REPO_GLOB] as &[&str], - PackageManager::Dnf4 => &DNF4_REPOS_GLOBS as &[&str], + PackageManager::Dnf => &DNF_REPOS_GLOBS as &[&str], PackageManager::Dnf5 => &DNF5_REPOS_GLOBS as &[&str], }; for glob in globs { @@ -181,12 +181,12 @@ fn load_repos<'a>(pm: PackageManager) -> Result, ErrorKind<'a>> { // This uses the default system_cachedir configuration option for dnf // Non superusers however use cachedir option (which defaults to /var/tmp/dnf--) // I'm choosing the system one as dnf is more likely to be run with sudo - PackageManager::Dnf4 => format!( + PackageManager::Dnf => format!( "/var/cache/dnf/{}.solv", info.name.replace('/', "_") ), - // As with dnf4, this uses the default system_cachedir value + // As with the old dnf, this uses the default system_cachedir value // (The default non-superuser cachedir is ~/.cache/libdnf5) PackageManager::Dnf5 => format!( "/var/cache/libdnf5/{}-*/solv/*.solv", From ff65a11f903a5bf7cd0b478a6b0be132c8902ea3 Mon Sep 17 00:00:00 2001 From: Isaac Oscar Gariano Date: Sun, 31 Aug 2025 02:49:09 +1000 Subject: [PATCH 3/3] Documented what configuration variables are relied on. --- cnf.1 | 6 ++++++ src/main.rs | 42 +++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/cnf.1 b/cnf.1 index a47f1eb..d20df79 100644 --- a/cnf.1 +++ b/cnf.1 @@ -29,6 +29,12 @@ Try installing with: bash(1), zsh(1), fish(1), libsolv(3) .SH BUGS No support for localization other than UTF-8. +.PP +It is assumed that the following configuration variables have not been changed from their openSUSE defaults: + for zypper (usually set in /etc/zypp/zypp.conf): reposdir, cachedir, and solvfilesdir + for dnf/dnf5 (usually set in /etc/dnf/dnf.conf): reposdir and system_cachedir + + .SH "AUTHOR" .PP \fBMichal Vyskocil\fR <\&mvyskocil@opensuse\&.org\&> diff --git a/src/main.rs b/src/main.rs index 025f863..3d168b7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,22 +14,6 @@ use std::vec::Vec; mod ini; mod pool; -const ZYPPER_REPO_GLOB: &str = "/etc/zypp/repos.d/*.repo"; -// Default value of the reposdir configuration directory -const DNF_REPOS_GLOBS: [&str; 3] = [ - "/etc/dnf/repos.d/*.repo", - "/etc/yum.repos.d/*.repo", - "/etc/distro.repos.d/*.repo" -]; -// Default value of the reposdir configuration directory -// (Note that /etc/dnf/repos.d is patched in by the openSUSE dnf5 package) -const DNF5_REPOS_GLOBS: [&str; 4] = [ - "/etc/dnf/repos.d/*.repo", - "/etc/yum.repos.d/*.repo", - "/etc/distro.repos.d/*.repo", - "/usr/share/dnf5/repos.d/*.repo", -]; - #[derive(Clone, Copy)] pub enum PackageManager { Zypper, @@ -161,10 +145,21 @@ fn search_in_repos<'a>( fn load_repos<'a>(pm: PackageManager) -> Result, ErrorKind<'a>> { let mut repos: Vec = Vec::new(); + // These use the default values of the reposdir configuration options for the various package managers let globs = match pm { - PackageManager::Zypper => &[ZYPPER_REPO_GLOB] as &[&str], - PackageManager::Dnf => &DNF_REPOS_GLOBS as &[&str], - PackageManager::Dnf5 => &DNF5_REPOS_GLOBS as &[&str], + PackageManager::Zypper => &["/etc/zypp/repos.d/*.repo"] as &[&str], + PackageManager::Dnf => &[ + "/etc/dnf/repos.d/*.repo", + "/etc/yum.repos.d/*.repo", + "/etc/distro.repos.d/*.repo", + ] as &[&str], + PackageManager::Dnf5 => &[ + // This first one is patched in by the openSUSE dnf5 package, and is not mentioned in the documentation + "/etc/dnf/repos.d/*.repo", + "/etc/yum.repos.d/*.repo", + "/etc/distro.repos.d/*.repo", + "/usr/share/dnf5/repos.d/*.repo", + ] as &[&str], }; for glob in globs { for repo in glob::glob(glob)? { @@ -175,16 +170,17 @@ fn load_repos<'a>(pm: PackageManager) -> Result, ErrorKind<'a>> { let info = ini::repo_enabled(reader)?; if info.enabled { let solv_glob = match pm { + // This uses the default solvfilesdir configuration option for libzypp, + // (solvfilesdir defaults to $cachedir/solv, and cachedir defaults to /var/cache/zypp) PackageManager::Zypper => { format!("/var/cache/zypp/solv/{}/solv", info.name.replace('/', "_")) } // This uses the default system_cachedir configuration option for dnf // Non superusers however use cachedir option (which defaults to /var/tmp/dnf--) // I'm choosing the system one as dnf is more likely to be run with sudo - PackageManager::Dnf => format!( - "/var/cache/dnf/{}.solv", - info.name.replace('/', "_") - ), + PackageManager::Dnf => { + format!("/var/cache/dnf/{}.solv", info.name.replace('/', "_")) + } // As with the old dnf, this uses the default system_cachedir value // (The default non-superuser cachedir is ~/.cache/libdnf5)