Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/pr_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ jobs:
load: true
push: false
tags: local/cnf-ci-zypper:latest
-
name: Build openSUSE Tumbleweed image with dnf4
uses: docker/build-push-action@v4
with:
cache-from: type=gha
cache-to: type=gha,mode=max
context: test/
file: test/dnf.dockerfile
load: true
push: false
tags: local/cnf-ci-dnf:latest
-
name: Build openSUSE Tumbleweed image with dnf5
uses: docker/build-push-action@v4
Expand Down
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
| **`fish` integration** | Included with fish 1.23.1 | Included with fish 1.23.1 |
| **Disable integration** | Uninstall package | Magic variable |
| **Localization** | Yes (UTF-8 only) | Yes |
| **Package Managers Queried** | Dnf5, Zypper | Zypper |
| **Package Managers Queried** | Dnf5, Dnf4, Zypper | Zypper |

## **Build**

Expand Down Expand Up @@ -77,10 +77,10 @@ cmake

## **Integration tests**

Integration tests runs inside docker images tagged `local/cnf-ci-zypper` and `local/cnf-ci-dnf5`. these are built as a part of Github Action and can be built locally with:
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:

```.sh
for pm in zypper dnf5; do
for pm in zypper dnf dnf5; do
docker build -t local/cnf-ci-$pm:latest -f test/$pm.dockerfile test
done
```
Expand All @@ -91,7 +91,6 @@ The testing itself is wrapped in [bats](https://github.com/bats-core/bats-core)
./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
Expand All @@ -104,6 +103,18 @@ The testing itself is wrapped in [bats](https://github.com/bats-core/bats-core)
> ✓ zypper nonroot: zsh handler: not installed cmake
> ✓ zypper nonroot: fish handler: not installed cmake
> ✓ zypper issue26: do not list not installable files
> ✓ dnf root: installed /usr/bin/rpm
> ✓ dnf root: installed /usr/sbin/sysctl
> ✓ dnf root: not installed xnake
> ✓ dnf root: not installed make
> ✓ dnf root: not installed cmake
> ✓ dnf nonroot: not installed cmake
> ✓ dnf nonroot: bash without handler: not installed cmake
> ✓ dnf nonroot: bash handler: not installed cmake
> ✓ dnf nonroot: zsh without handler: not installed cmake
> ✓ dnf nonroot: zsh handler: not installed cmake
> ✓ dnf nonroot: fish handler: not installed cmake
> ✓ dnf issue26: do not list not installable files
> ✓ dnf5 root: installed /usr/bin/rpm
> ✓ dnf5 root: installed /usr/sbin/sysctl
> ✓ dnf5 root: not installed xnake
Expand All @@ -117,7 +128,7 @@ The testing itself is wrapped in [bats](https://github.com/bats-core/bats-core)
> ✓ dnf5 nonroot: fish handler: not installed cmake
> ✓ dnf5 issue26: do not list not installable files
>
> 24 tests, 0 failures
> 36 tests, 0 failures
```

Every test can be executed on a command line. The `root.sh` wrapper mounts the
Expand Down
4 changes: 2 additions & 2 deletions cnf.1
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ cnf \- A command not found handler for openSUSE
libsolv(3) under the hood. The source of truth of information about
repositories, packages and their content.
.PP
This works with enabled dnf5 or zypper repostiores: the first one found in /usr/bin will be used.
Use dnf5 \-\-refresh makecache or zypper \-\-force refresh to update the metadata used.
This works with enabled dnf5, dnf, or zypper repostiores: the first one found in /usr/bin will be used.
Use dnf5 \-\-refresh makecache, dnf \-\-refresh makecache, or zypper \-\-force refresh to update the metadata used.
.PP
It is typically called through command-not-found mechanism of bash(1) or zsh(1)
or fish(1). This is enabled via installing the cnf-bash or cnf-zsh
Expand Down
29 changes: 24 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ 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] = [
"/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",
Expand All @@ -27,6 +33,7 @@ const DNF5_REPOS_GLOBS: [&str; 4] = [
#[derive(Clone, Copy)]
pub enum PackageManager {
Zypper,
Dnf4,
Dnf5,
}
pub struct SolvInput {
Expand Down Expand Up @@ -70,12 +77,16 @@ fn main() {
}

let pm = if Path::exists(Path::new("/usr/bin/dnf5")) {
// Use DNF5 if it's installed (this should probably be set via a config file, in case you have both installed but prefer zypper)
// 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
// (in case a dnf5 user symlinks /usr/bin/dnf to /usr/bin/dnf5, this goes after the dnf5 check)
PackageManager::Dnf4
} else if Path::exists(Path::new("/usr/bin/zypper")) {
PackageManager::Zypper
} else {
println!("Neither /usr/bin/dnf5 nor /usr/bin/zypper could be found.");
println!("Neither /usr/bin/dnf5, /usr/bin/dnf, norr /usr/bin/zypper could be found.");
exit(127);
};

Expand Down Expand Up @@ -142,6 +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::Dnf5 => println!(" sudo dnf5 install {}\n", suggested_package),
}
Ok(())
Expand All @@ -151,6 +163,7 @@ fn load_repos<'a>(pm: PackageManager) -> Result<Vec<SolvInput>, ErrorKind<'a>> {
let mut repos: Vec<SolvInput> = Vec::new();
let globs = match pm {
PackageManager::Zypper => &[ZYPPER_REPO_GLOB] as &[&str],
PackageManager::Dnf4 => &DNF4_REPOS_GLOBS as &[&str],
PackageManager::Dnf5 => &DNF5_REPOS_GLOBS as &[&str],
};
for glob in globs {
Expand All @@ -165,10 +178,16 @@ fn load_repos<'a>(pm: PackageManager) -> Result<Vec<SolvInput>, ErrorKind<'a>> {
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-<username>-<random suffix>)
// I'm choosing the system one as dnf is more likely to be run with sudo
PackageManager::Dnf4 => format!(
"/var/cache/dnf/{}.solv",
info.name.replace('/', "_")
),

// This uses the default system_cachedir configuration open for dnf5
// None superusers however use cachedir option (which defaults to ~/.cache/libdnf5)
// I'm choosing the system one as dnf5 is more likely to be run with sudo?
// As with dnf4, this uses the default system_cachedir value
// (The default non-superuser cachedir is ~/.cache/libdnf5)
PackageManager::Dnf5 => format!(
"/var/cache/libdnf5/{}-*/solv/*.solv",
info.name.replace('/', "_")
Expand Down
21 changes: 21 additions & 0 deletions test/dnf.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Tumbleweed based CI image for cnf integration testing with dnf4
FROM registry.opensuse.org/opensuse/tumbleweed

# This is the same as dnf5.dockerfile
ADD passwd /etc/passwd
ADD group /etc/group
ADD --chown=65532:65532 nonroot /home/nonroot/whoami

# The following is exactly the same as for dnf5, except it uses 'dnf' instead of 'dnf5'
RUN zypper refresh
# As with dnf5, dnf4 fails to work without the libcurl4 package
RUN zypper --non-interactive install --no-recommends dnf libcurl4 rpm-repos-openSUSE-Tumbleweed
RUN dnf --assumeyes remove zypper libzypp
RUN rm -rf /etc/zypp /var/cache/zypp/ /var/lib/zypp

RUN echo excludepkgs=busybox dbus diffutils pam-config perl-base systemd groff man >> /etc/dnf/dnf.conf
RUN dnf --setopt install_weak_deps=False --assumeyes install zsh fish libsolv1
RUN curl -O https://download.opensuse.org/repositories/GNOME:/Next/openSUSE_Factory/GNOME:Next.repo --output-dir /etc/dnf/repos.d/
RUN dnf makecache

WORKDIR /src
2 changes: 1 addition & 1 deletion test/test.bats
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function make_test {
bats_test_function --description "$1" -- "$name"
}

for PM in zypper dnf5; do
for PM in zypper dnf dnf5; do

make_test "$PM root: installed /usr/bin/rpm" <<EOF
run root.sh $PM '/usr/bin/cnf' 'rpm'
Expand Down