#compdef dnf5 # based on dnf-5.2.6.2 # utility functions _dnf5_helper() { _call_program specs $service "${(q-)@}" "${(q-)PREFIX}\*" \ -qC --assumeno --nogpgcheck 2>/dev/null </dev/null } _dnf5_repositories() { # required option: -T (all|disabled|enabled) local selected expl zparseopts -D -E - T:=selected selected=$selected[2] _wanted $selected-repositories expl "$selected repository" \ compadd "$@" - "${(@)${(f)$(_dnf5_helper repo list --$selected)}[2,-1]%% *}" } _dnf5_packages() { # required option: -T (all|available|installed|upgradable) local selected opt expl zparseopts -D -E - T:=selected selected=$selected[2] case $selected in all) opt='' ;; # option --all does not exist upgradable) opt='--upgrades' ;; *) opt="--$selected" ;; esac _wanted $selected-packages expl "$selected package" \ compadd "$@" - $(_dnf5_helper repoquery $opt --qf='%{name} ') } _dnf5_rpm_files() { local expl _wanted rpm-files expl 'rpm file' _files -g '(#i)*.rpm(-.)' } _dnf5_packages_or_rpms() { if [[ "$words[CURRENT]" = (*/*|\~*) ]]; then # if looks like a path name _dnf_rpm_files else _dnf5_packages "$@" fi } _dnf5_groups() { # optional option: -T (available|installed) local update_policy selected line pat groups zparseopts -D -E - T:=selected selected=$selected[2] if [[ -z $selected ]]; then selected=all opt= # option --all does not exist else opt=--$selected fi # XXX hidden groups are not included for line in ${${(f)"$(_dnf5_helper group list $opt)"}[2,-1]}; do line=( ${(z)line} ) groups+=( "$line[1]:$line[2,-2]" ) done _describe -t $selected-groups "$selected group" groups } _dnf5_environments() { local line envs for line in ${${(f)"$(_dnf5_helper environment list)"}[2,-1]}; do line=( ${(z)line} ) envs+=( "$line[1]:$line[2,-2]" ) done _describe -t environments 'environment' envs } # completers for (several) dnf commands _dnf5-advisory () { _arguments : \ $advisory_opts \ '--contains-pkgs=[only show advisories containing specified packages]: : _sequence _dnf5_packages -T installed' \ + '(with)' \ '--with-cve[show only advisories referencing CVE ticket]' \ '--with-bz[show only advisories referencing Bugzilla ticket]' \ + '(type)' \ '--all[show all advisories]' \ '--available[show advisories containing newer versions of installed packages (default)]' \ '--installed[show advisories containing equal and older version of installed packages]' \ '--updates[show advisories containing upgradable packages]' \ + args \ ':subcommand:(list info summary)' '*:advisory spec:' } _dnf5-group() { local -a tmp if (( CURRENT == 2 )); then tmp=( 'list:list all matching groups' 'info:print detailed information about groups' 'install:install packages from specified groups' 'remove:remove removable packages in specified groups' 'upgrade:upgrade specified groups and packages in them' ) _describe -t subcommands 'subcommand' tmp else case $words[2] in list|info) tmp=( '(--installed)--available[show only available groups]' '(--available)--installed[show only installed groups]' '--hidden[show also hidden groups]' '--contains-pkgs=[show only groups containing specified packages]: : _sequence _dnf5_packages -T all' '*: : _dnf5_groups' ) ;; install) tmp=( $common_opts '--with-optional[include optional packages from the groups]' '*: : _dnf5_groups -T available' ) ;| upgrade) tmp=( ${common_opts:#--skip-broken*} '*: : _dnf5_groups -T installed' ) ;| remove) tmp=( $offline_opts '*: : _dnf5_groups -T installed' ) ;| install|remove) tmp+=( '--no-packages[operate on groups only, not manipulate any packages]' ) ;| install|upgrade) tmp+=( $downgrade_opts ) ;; esac _arguments : $tmp fi } _dnf5-history() { local -a tmp if (( CURRENT == 2 )); then tmp=( 'list:list info about recorded transactions' 'info:print detailed about specific transactions' 'undo:revert all actions from the specified transaction' 'redo:repeat the specified transaction' 'rollback:undo all transactions performed after the specified transaction' 'store:store the transaction into a directory' ) _describe -t subcommands 'subcommand' tmp else case $words[2] in list|info) tmp=( '--reverse[reverse the order of transactions in output]' ) ;; undo|rollback|redo) tmp=( '--skip-unavailable[allow skipping impossible actions]' ) ;| undo|rollback) tmp+=( $replay_opts ) ;; store) tmp=( {-o,--output=}'[directory for storing the transaction (default ./transaction)]: : _directories') esac _arguments : $tmp '2:transaction:( )' fi } _dnf5-mark() { local -a tmp if (( CURRENT == 2 )); then tmp=( 'user:mark the package as user-installed' 'dependency:mark the package as a dependency' 'weak:mark the package as a weak dependency' 'group:mark the package as installed by the specified group' ) _describe -t subcommands 'subcommand' tmp else tmp=( '--skip-unavailable[skip packages not installed on the system]' '--store=[store the transaction in specified directory]: : _directories' ) if [[ $words[2] = group ]]; then tmp+=( '2:group-id: _dnf5_groups -T installed' ) fi _arguments : $tmp '*: : _dnf5_packages -T installed' fi } _dnf5-module() { local -a tmp if (( CURRENT == 2 )); then tmp=( 'list:list module streams' 'info:print details about module streams' 'enable:enable module streams' 'disable:disable modules including all their streams' "reset:reset module state so it's no longer enabled or disabled" ) _describe -t subcommands 'subcommand' tmp elif (( CURRENT == 3 )) && [[ $cur = -* ]]; then case $words[2] in list|info) tmp=( --enabled --disabled ) ;; enable) tmp=( --skip-broken --skip-unavailable ) ;; *) tmp=( --skip-unavailable ) ;; esac _wanted options expl 'option' compadd -a tmp else _message 'module spec' fi } _dnf5-offline() { # also used by the 'system-upgrade' command local -a tmp if (( CURRENT == 2 )); then tmp=( 'clean:remove any stored offline transactions and cached packages' 'log:list boots during which offline transaction was attempted' 'reboot:prepare the system for offline transaction and reboot' ) if [[ $cmd = offline ]]; then tmp+=( 'status:show status of the current offline transaction' ) else tmp+=( 'download:download all packages needed for upgrade' ) fi _describe -t subcommands 'subcommand' tmp && ret=0 else case $words[2] in download) _arguments : \ '--releasever=[the version to upgrade to]:version number:' \ '--no-downgrade:do not install packages older than currently installed' '*: :' && ret=0 ;; log) _arguments : \ '--number=[show log of transaction specified by number]:transaction number:' '*: :' && ret=0 ;; reboot) _wanted options expl 'option' compadd -- --poweroff && ret=0 ;; esac fi } _dnf5-repoquery() { local v local -a opts=( $advisory_opts '--arch=[limit results to specified architectures]:list of archs: ' '--available[limit results to available packages]' '--disable-modular-filtering[include packages of inactive module streams]' '--duplicates[limit to installed duplicate packages]' '--exactdeps[limit to packages that require capability specified by ==what{requires,depends}]' '--extras[limit to installed packages that are not present in any available repository]' '--file=[limit results to packages which own specified file]:list of files: _sequence _files' '--installed[query installed packages]' '--installonly[limit to installed installonly packages]' '--latest-limit=[limit to latest packages of specified number]:number:' '--leaves[limit to groups of installed packages not required by other installed packages]' '--providers-of=[select packages that provide specified attribute]:attribute:(conflicts depends enhances obsoletes provides recommends requires requires_pre suggests supplement)' '--recent[limit to only recently changed packages]' '--recursive[make --whatrequires/--providers-of work recursively]' '--security[limit to packages in security advisories]' '--srpm[use the corresponding source RPM]' '--unneeded[limit to unneeded installed packages]' '--upgrades[limit to available packages that provide upgrade for installed packages]' '--userinstalled[limit to packages that are not installed as dependencies]' '--whatdepends=[limit to packages that require, enhance, recommend, suggest of supplement specified capability]:list of capability:' '--whatconflicts=[limit to packages that conflicts with specified capabilities]:list of capability: ' ) for v in enhance obsolete provide recommend require suggest supplement; do opts+=( "--what${v}s=[limit to packages that $v specified capabilities]:list of capability: ") done # mutually exclusive formating options opts+=( + '(format)' '--conflicts[display capabilities that the package conflicts with]' '--depends[display capabilities that the package depends on, enables, recommends, suggests or supplements]' '--files[show files in the package]' '--requires-pre[display capabilities required to run pre/post scripts of the package]' '--sourcerpm[display source RPM of the package]' '--location[display location of the package]' '--info[show detailed information about the package]' '--changelogs[print the package changelogs]' '(- *)--querytags[list tags recognized by --queryformat]' '--queryformat=[specify output format]:format:' ) for v in enhance obsolete provide recommend require suggest supplement; do opts+=( "--${v}s[display capabilities ${v}ed by the package]" ) done _arguments : '*: : _dnf5_packages -T all' $opts } # dnf commands _dnf5_commands() { local -a dnf_cmds=( 'advisory:manage advisories' 'autoremove:remove unneeded packages' 'check:check for problems in package database' 'check-upgrade:check for available package upgrades' 'clean:remove or invalidate cached data' 'distro-sync:up/downgrade installed packages to the latest available' 'downgrade:downgrade packages' 'download:download packages' 'environment:manage comps environments' 'group:manage comps groups' 'history:manage transaction history' 'info:provide detailed information about packages' 'install:install packages' 'leaves:list groups of leaf packages' 'list:list installed or available packages' 'makecache:generate the metadata cache' 'mark:change the reason of an installed package' 'module:manage modules' 'offline:manage offline transactions' 'provides:find what package provides the given value' 'reinstall:reinstall packages' 'remove:remove packages' 'replay:replay stored transactions' 'repo:manage repositories' 'repoquery:search for packages in repositories' 'search:search for packages using keywords' 'swap:remove software and install another in the single transaction' 'system-upgrade:upgrade the system to a new major release' 'upgrade:upgrade packages' 'versionlock:protect packages from updates to newer versions' ) _describe -t dnf-commands 'dnf command' dnf_cmds } # subcommands and options _dnf5_subcmds_opts() { local cur=$words[CURRENT] cmd=$words[1] expl ret=1 local -a tmp # common options local -a offline_opts=( '(--store)--offline[store the transaction to be performed offline]' '(--offline)--store=[store the transaction in specified directory]: : _directories' ) local -a common_opts=( $offline_opts '--allowerasing[allow erasing of installed packages]' '--skip-broken[resolve dependency problems by skipping problematic packages]' "--skip-unavailable[skip packages that can't be synchronized]" '--downloadonly[download packages without executing transaction]' ) local -a advisory_opts=( '--advisories=[consider only specified advisories]:list of advisories:' '--advisory-severities=[limit to advisories with specified severity]:severity:_sequence compadd - critical important moderate low none' '--bzs=[limit to advisories that fix specified Bugzilla ID]:list of Bugzilla ID:' '--cves=[limit to advisories that fix specified CVE ID]:list of CVD ID]:' '--security[limit to security advisories]' '--bugfix[limit to bugfix advisories]' '--enhancement[limit to enhancement advisories]' '--newpackage[limit to newpackage advisories]' ) local -a downgrade_opts=( '(--no-allow-downgrade)--allow-downgrade[enable downgrade of dependencies]' '(--allow-downgrade)--no-allow-downgrade[disable downgrade of dependencies]' ) local -a replay_opts=( '--ignore-extras[not consider extra packages]' '--ignore-installed[mismatches between installed and stored transaction are not errors]' ) # Deal with some aliases (not comprehensive) case $cmd in check-updgrade) cmd=check-update;; dg) cmd=downgrade;; dsync) cmd=distro-sync;; grp) cmd=group;; if) cmd=info;; in) cmd=install;; ls) cmd=list;; mc) cmd=makecache;; rei) cmd=reinstall;; rm) cmd=remove ;; rq) cmd=repoquery;; se) cmd=search;; update|up) cmd=upgrade;; esac local curcontext="${curcontext%:*:*}:dnf-${cmd}:" case $cmd in advisory|group|history|mark|module|offline|repoquery) _dnf5-$cmd && ret=0 ;; system-upgrade) _dnf5-offline && ret=0 ;; autoremove) _arguments : $offline_opts && ret=0 ;; check) _arguments : \ '--dependencies[show missing dependencies and conflicts]' \ '--duplicates[show duplicated packages]' \ '--obsoleted[show obsoleted packages]' && ret=0 ;; check-upgrade) _arguments : \ $advisory_opts \ '--changelogs[print package changelogs]' \ '--minimal[reports the lowest versions of packages that fix advisories]' \ '*: : _dnf5_packages -T installed' && ret=0 ;; clean) tmp=( 'dbcache:remove cache files generated from the repository metadata' 'expire-cache:mark the repository metadata expired' 'metadata:remove the repository metadata' 'packages:remove any cached packages' 'all:clean all' ) _describe -t cache-types 'cache type' tmp && ret=0 ;; distro-sync) _arguments : $common_opts '*: : _dnf5_packages -T installed' && ret=0 ;; downgrade) _arguments : \ $common_opts $downgrade_opts \ '*: : _dnf5_packages -T installed' && ret=0 ;; download) _arguments : \ '--arch=[limit to packages of specified architecture]:list of architectures:' \ '--resolve[resolve and download needed dependencies]' \ '--alldeps[with --resolve, also download already installed dependencies]' \ '--destdir=[download to the specified directory]: : _directories' \ '--srpm[download the source rpm]' \ '--url[print the list of URLs where the rpms can be downloaded]' \ '*--urlprotocol=[with --url, limit to specified protocols]:protocol:_sequence compadd - http https ftp file' \ '*: : _dnf5_packages -T all' && ret=0 ;; environment) _arguments : \ '--available[show only available environments]' \ '--installed[show only installed environments]' \ ':subcommand:(list info)' \ '*: : _dnf5_environments' && ret=0 ;; info|list) _arguments : \ '--showduplicates[show all versions of the packages]' \ '*: : _dnf5_packages -T all' \ + '(type)' \ '--installed[list only installed packages]:*: : _dnf5_packages -T installed' \ '--available[list only available packages]:*: : _dnf5_packages -T available' \ '--extras[list only extras]' \ '--obsoletes[list only installed but obsoleted packages]:*: : _dnf5_packages -T installed' \ '--recent[list only recently added packages]' \ '--upgrades[list only available upgrades of installed packages]:*: : _dnf5_packages -T upgradable' \ '--autoremove[list only packages that will be autoremoved]:*: : _dnf5_packages -T installed' &&ret=0 ;; install) _arguments : \ $common_opts $downgrade_opts $advisory_opts \ '*: : _dnf5_packages_or_rpms -T available' && ret=0 ;; leaves|makecache) # nothing to complete ;; provides) _files && ret=0 ;; reinstall) _arguments : \ $common_opts $downgrade_opts \ '*: : _dnf5_packages_or_rpms -T installed' && ret=0 ;; remove) _arguments : \ $offline_opts \ '--no-autoremove[not remove dependencies that are no longer used]' \ '*: : _dnf5_packages -T installed' && ret=0 ;; replay) _arguments : \ $replay_opts \ ':transaction path:_directories' && ret=0 ;; repo) _arguments : \ '--all[show info about all repositories]' \ '--enabled[show info only about enabled repositories]' \ '--disabled[show info only about disabled repositories]' \ ':subcommand:(list info)' && ret=0 ;; search) _arguments : \ '--all[search patterns also inside description and URL fields]' \ '--showduplicates[show all versions of packages, not only the latest ones]' \ '*:search pattern:' && ret=0 ;; swap) _arguments : \ $offline_opts \ '--allowerasing[allow erasing of installed packages]' \ ': : _dnf5_packages -T installed' \ ': : _dnf5_packages -T available' && ret=0 ;; upgrade) _arguments : \ ${common_opts:#--skip-broken*} $downgrade_opts $advisory_opts \ '--minimal[upgrade only to the lowest available versions that fix advisories]' \ '--destdir=[specify directory into which downloading packages]: : _directories' \ '*: : _dnf5_packages_or_rpms -T upgradable' && ret=0 ;; versionlock) _arguments : \ ':subcommand:(add exclude clear delete list)' \ '*: : _dnf5_packages -T all' && ret=0 ;; esac return ret } # main completer _dnf5() { local curcontext="$curcontext" state state_descr line ret=1 typeset -A opt_args local -a opts=( '(-y --assumeyes)--assumeno[answer no for all questions]' '--best[try the best available package version]' '(-C --cacheonly)'{-C,--cacheonly}"[run entirely from system cache, don't update cache]" '--comment=[add comment to transaction history]:comment:' '(-c --config)'{-c+,--config=}'[specify configuration file]:config file:_files' '--debugsolver[dump detailed solving results in file ./debugdata]' '*--disable-plugin=[disable specified plugins]:list of plugin names:' '(--repo)*--disable-repo=[disable specified repos]: : _sequence _dnf5_repositories -T enabled' '--dump-main-config[print main configuration values to stdout]' '*--dump-repo-config=[print repository configuration values to stdout]:repi id' '--dump-variables[print variable values to stdout]' '*--enable-plugin=[enable specified plugins]:list of plugin names:' '*--enable-repo=[enable additional repos]: : _sequence _dnf5_repositories -T disabled' '--forcearch=[force the use of the specified arch]:arch:' '(-)'{-h,--help}'[show the help message]' '--installroot=[set install root]: : _directories' '--no-best[do not limit transactions to best candidates]' '--no-docs[do not install documentation]' '--no-gpgcheck[skip checking GPG signatures on packages]' '--no-plugins[disable all plugins]' '(-q --quiet)'{-q,--quiet}'[show just the relevant content]' '--refresh[force refreshing metadata before running the command]' '--releasever=[override distribution release in config files]:release ver:' '(--disablerepo)*--repo=[enable just the specified repo]: : _sequence _dnf5_repositories -T all' '*--repofrompath=[specify additional repos]:repository_label,path_or_url: ' '*--setopt=[override option in config file]:repoid.option=value:' '*--setvar=[override DNF5 variable value]' '--show-new-leaves[show newly installed leaf packages]' '--use-host-config[use config files and variables from host system]' '(- *)--version[show dnf version]' '(-y --assumeyes --assumeno)'{-y,--assumeyes}'[answer yes for all questions]' '*'{-x+,--exclude=}'[exclude specified packages from transaction]: : _sequence _dnf5_packages -T all' ) _arguments -C -s : $opts ': :->command' '*:: :->cmd_args' && ret=0 case $state in command) _dnf5_commands && ret=0 ;; cmd_args) _dnf5_subcmds_opts && ret=0 ;; esac return ret } _dnf5 "$@"