1#compdef rpm rpmbuild rpmkeys rpmsign rpmspec rpmquery rpmverify 2 3# This uses `_arguments' in a state-machine kind of way. These states 4# have names and before executing the default action for such a state 5# we try to call a function with the name `_rpm_<state>'. If such a 6# function exists, we return with its return status immediately. This 7# allows users to override the default completions by simply defining 8# these functions. 9# The states (and possible values for the `<state>' above) are: 10# 11# common 12# complete for basic options like --querytags and --showrc 13# query 14# complete for `rpm -q' query 15# verify 16# complete for `rpm --verify' 17# install 18# complete for `rpm -i' or `rpm --install' 19# upgrade 20# complete for `rpm -U' or `rpm --upgrade' 21# uninstall 22# complete for `rpm -e' or `rpm --erase' 23# build_b 24# complete for `rpmbuild -bx' (the stage `x' is already completed) 25# build_r 26# complete for `rpmbuild -rx' (the stage `x' is already completed) 27# build_t 28# complete for `rpmbuild -tx' (the stage `x' is already completed) 29# checksig 30# complete for `rpm --checksig' 31# package 32# complete a RPM package name 33# package_file 34# complete a RPM package file name 35# file_or_package 36# an absolute path to any file (not a package file) or a package 37# tags 38# complete a tag name 39# capability 40# complete a capability 41# relocate 42# complete a `old=new' pair of paths 43# setattrs 44# complete for --setperms, --setugids, --setcaps and --restore 45# public_keys 46# complete for `rpmkeys --import' 47# query_specs 48# complete for `rpmspec --query' 49 50_rpm () { 51 local curcontext="$curcontext" state lstate line nm="$compstate[nmatches]" 52 typeset -A opt_args 53 local ret 54 local -a tmp expl opts commonopts selectopts fileopts pathopts buildopts queryopts 55 56 commonopts=( 57 '(-v --verbose)--quiet[print as little as possible]' 58 '(--quiet)*'{-v,--verbose}'[verbose output]' 59 '--rcfile=:configuration file:_sequence -s \: _files' 60 '--httpproxy=:http proxy server:_hosts' 61 '--httpport=:http port number' 62 '--pipe=[pipes the output of rpm to the specified command]:pipe command:_cmdstring' 63 \*{-D,--define=}'[define a macro]:macro value' 64 '*--undefine=[undefine a macro]:macro:->macros' 65 '--target=[specify target platform]:arch-vendor-os' 66 '--macros=[read macros from specified files instead of the defaults]:file:_sequence -s \: _files' 67 '--load=[load a single macro file]:file:_files' 68 "--noplugins[don't enable any plugins]" 69 "--nodigest[don't verify package digest(s)]" 70 "--nosignature[don't verify package signature(s)]" 71 ) 72 73 # package selection options of which only one can be used 74 selectopts=( 75 {-a,--all}'[query all packages]' 76 {-f,--file}'[query packages that own specified files]' 77 {-p,--package}'[query uninstalled packages]' 78 {-g,--group}'[query packages in one of specified groups]' 79 --pkgid --hdrid --tid --querybynumber 80 '--triggeredby' 81 '--whatconflicts' 82 '--whatrequires' 83 '--whatobsoletes' 84 '--whatprovides' 85 '--whatrecommends' 86 '--whatsuggests' 87 '--whatsupplements' 88 '--whatenhances' 89 '--nomanifest' 90 ) 91 sopts=${selectopts%\[*}\ --specfile 92 selectopts=( 93 "(* $sopts)"${selectopts[1,2]} 94 "($sopts)"${selectopts[3,-1]} 95 '(-a --all)*: :->package-select' 96 ) 97 98 fileopts=( 99 '(-c --configfiles)'{-c,--configfiles}'[configuration files only]' 100 '(-d --docfiles)'{-d,--docfiles}'[documentation files only]' 101 '(-L --licensefiles)'{-L,--licensefiles}'[license files only]' 102 '(-A --artifactfiles)'{-A,--artifactfiles}'[artifact files only]' 103 '--noghost[exclude ghost files]' 104 '--noconfig[exclude config files]' 105 '--noartifact[exclude artifact files]' 106 ) 107 108 pathopts=( 109 {-r,--root=}'[specify rpm root directory]:directory:_directories' 110 '--dbpath=[specify rpm database path]:path:_directories' 111 ) 112 113 buildopts=( 114 '--rpmfcdebug[debug dependencies generation]' 115 '--buildroot=[override the build root]:build root directory:_directories' 116 '--build-in-place[run build in current directory]' 117 '--clean[remove the build tree after the packages are made]' 118 "--nobuild[don't execute any stages of the build]" 119 '--nodeps[do not verify build dependencies]' 120 '--nodirtokens[generate package header(s) compatible with (legacy) rpm v3 packaging]' 121 "--noclean[don't execute %clean stage of the build]" 122 "--noprep[don't execute %prep stage of the build]" 123 "--nocheck[don't execute %check stage of the build]" 124 '--rmsource[remove sources when done]' 125 '--rmspec[remove the spec file when done]' 126 '--short-circuit[skip straight to specified stage (only for c,i)]' 127 '*--with=[enable configure option for build]:option' 128 '*--without=[disable configure option for build]:option' 129 '--scm=[select the SCM to use with %autosetup]:scm [patch]:(patch gendiff git quilt)' 130 '*--buildpolicy=[set buildroot policy]:policy:->brp_policies' 131 '!--sign' 132 "--nodebuginfo[don't generate debuginfo for this package]" 133 ) 134 135 queryopts=( 136 '--conflicts' 137 '--obsoletes[list packages obsoleted by package]' 138 '--provides[list capabilities provided by package]' 139 '(-R)--requires[list capabilities on which packages depend]' 140 ) 141 142 case $service in 143 rpm|rpmkeys) 144 opts+=( 145 '--import[import an armored public key]:*: :->public_keys' 146 {-K,--checksig}'[signature check mode]:*:sigcheck:->checksig' 147 ) 148 ;| 149 rpm|rpmdb) 150 opts+=( --{init,rebuild}'db:*: :->common' ) 151 ;| 152 rpm|rpmsign) 153 opts+=( 154 --{add,re}sign'[sign package(s)]:*: :->sign' 155 '--delsign[delete package signatures]:*: :->sign' 156 ) 157 ;| 158 rpm) 159 opts+=( 160 {-q+,--query}'[query mode]:*:query:->query' 161 {-V+,-y+,--verify}'[verify mode]:*:verify:->verify' 162 {-i+,--install}'[install mode]:*:install:->install' 163 {-U+,--upgrade}'[upgrade mode]:*:upgrade:->upgrade' 164 {-F+,--freshen}'[freshen mode]:*:upgrade:->upgrade' 165 {-e+,--erase}'[uninstall mode]:*:uninstall:->uninstall' 166 '--reinstall[reinstall mode]:*:install:->install' 167 '--setperms[set file permissions]:*:package:->setattrs' 168 '--setugids[set file owner/group]:*:package:->setattrs' 169 '--setcaps[set capabilities of files in the given package]:*:package:->setattrs' 170 '--restore[restore owner, group, permissions and capabilities of files in the given package]:*:package:->setattrs' 171 ) 172 ;; 173 rpmbuild) 174 [[ -prefix -r ]] && pathopts[1]= 175 opts+=( $buildopts 176 '(-r -t)-b+[build mode (spec file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages s\:build\ source\ package\ only r\:build\ source\ package\ only\ -\ calculate\ build\ requires)):*:build:->build_b' 177 '(-b -t)-r+[build mode (source package)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages s\:build\ source\ package\ only r\:build\ source\ package\ only\ -\ calculate\ build\ requires)):*:build:->build_b' 178 '(-b -r)-t+[build mode (tar file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages s\:build\ source\ package\ only r\:build\ source\ package\ only\ -\ calculate\ build\ requires)):*:build:->build_t' 179 --{rebuild,recompile}':*:source rpm file:->build_r' 180 ) 181 ;; 182 rpmspec) 183 opts+=( 184 {-P,--parse}'[parse spec files]:*: :->spec_files' 185 {-q,--query}'[query spec files]:*: :->query_specs' 186 ) 187 ;; 188 rpmquery) state=query ;; 189 rpmverify) state=verify ;; 190 esac 191 192 [[ -z $state ]] && _arguments -C -s $pathopts $opts $commonopts \ 193 '(-)'{-\?,--help}'[print help information]' \ 194 '(-)--usage[print brief usage message]' \ 195 '(-)--version[print version number]' \ 196 \*{-E,--eval=}'[print macro expansion of given expression]:expression:->tags' \ 197 --{querytags,showrc}':*: :->common' 198 199 # As long as we have a state name... 200 201 while [[ -n "$state" ]]; do 202 203 # First try to call a user-defined function. 204 205 _call_function ret _rpm_$state && return ret 206 207 # Copy the state and reset `state', to simplify the test above. 208 209 lstate="$state" 210 state='' 211 tmp=() 212 213 # Dispatch... 214 215 case "$lstate" in 216 common) 217 _arguments -s -C $commonopts 218 ;; 219 query) 220 # --dump requires one of -{l,c,d} 221 # --triggers requires --script 222 _arguments -s -C \ 223 \!{-q,--query} $commonopts $selectopts $fileopts $pathopts $queryopts \ 224 '--dump[dump basic file information]' \ 225 \*--{qf,queryformat}'[specify format for package information]:rpm query format:->tags' \ 226 "($sopts)--specfile[query specified spec file as if it were a package]" \ 227 '(-i --info)'{-i,--info}'[display package information]' \ 228 '--changelog' '--changes' '--dupes' \ 229 '--last[order packages by install time]' \ 230 '--xml' \ 231 '--recommends[list capabilities recommended by packages]' \ 232 '(--requires)-R[list capabilities on which packages depend]' \ 233 '--suggests[list capabilities suggested by packages]' \ 234 '--supplements[list capabilities supplemented by packages]' \ 235 '(-s --state -l --list --filesbypkg)'{-l,--list}'[list files in package]' \ 236 '(-s --state -l --list)'{-s,--state}'[show file states]' \ 237 '--fileclass' '--filecolor' '--fileprovide' '--filerequire' \ 238 '--filecaps' '--filesbypkg[list files with package names]' \ 239 '--filetriggers[list filetrigger scriptlets]' \ 240 '--scripts[show (un)install scripts]' \ 241 {--triggers,--triggerscripts}'[show trigger scripts]' 242 ;; 243 query_specs) 244 _arguments -s -C \ 245 \!{-q,--query} $commonopts $pathopts $queryopts \ 246 --buildconflicts --buildrequires --trace \ 247 '*:spec file:->spec_files' 248 ;; 249 setattrs) 250 _arguments -s -C '!--set{perm,ugids,caps}' '!--restore' $selectopts 251 ;; 252 verify) 253 _arguments -s -C \ 254 \!{-V,--verify} $commonopts $selectopts $fileopts $pathopts \ 255 --no{deps,digest,files,scripts,signature,linkto,filedigest,size,user,group,mtime,mode,rdev,caps} 256 ;; 257 upgrade) 258 tmp=( '(--force)--oldpackage' ) 259 ;& 260 install) 261 _arguments -s -C \!{-i,--install,-U,--upgrade,-F,--freshen} $tmp \ 262 $commonopts $pathopts \ 263 '--excludepath=:file to exclude:_files -/' \ 264 '--relocate:relocate:->relocate' \ 265 '--prefix=[relocate the package]:package prefix directory:_files -/' \ 266 '(-h --hash)'{-h,--hash}'[print hash marks as package installs]' \ 267 '(--replacepkgs --replacefiles --oldpackage)--force' \ 268 '(--force)--'{replacefiles,replacepkgs} \ 269 --{aid,allfiles,badreloc,excludedocs,ignorearch,ignoreos,ignoresize,includedocs,justdb,percent,test} \ 270 --no{deps,filedigest,contexts,caps,order,suggest,pre,post,preun,postun,trigger{s,in,un,postun}} \ 271 '(--nopre --nopost --nopreun --nopostun)--noscripts' \ 272 '*:pkg file:->package_file' 273 ;; 274 uninstall) 275 _arguments -s -C \!{-e,--erase} \ 276 "${commonopts[@]}" "${pathopts[@]}" \ 277 --{allmatches,justdb,repackage,test} \ 278 --no{deps,scripts,preun,postun,trigger{s,un,postun}} \ 279 '*:package:->package' 280 ;; 281 build_b) tmp=( '*:spec file:_files -g "*.spec(-.)"' ) ;| 282 build_r) tmp=( '*:source package:_files -g "*.(#i)src.rpm(-.)"' ) ;| 283 build_t) tmp=( '*:tar file:_files -g "*.(#i)tar(.*|)(-.)"' ) ;| 284 build_?) 285 _arguments -s -C $buildopts $commonopts $pathopts \ 286 ;; 287 checksig) 288 _arguments -s -C \!-K \ 289 "${commonopts[@]}" \ 290 --no{gpg,pgp,md5,digest} \ 291 '*:package file:->package_file' 292 ;; 293 sign) 294 _arguments -s -C $commonopts $pathopts \ 295 '--signfiles[sign package(s) files]' \ 296 '--fskpath=[use file signing key]:key:_files' \ 297 '--fskpass[prompt for file signing key password]' \ 298 '--key-id=[specify key id/name to sign with]:key id' \ 299 '--digest-algo=[override default digest algorithm]:algorithm:(sha1 sha256 sha384 sha512)' \ 300 '*:package file:_files -g "*.(#i)rpm(-.)"' 301 ;; 302 package-select) 303 case "${opt_args[(i)${sopts// /|}]}" in 304 -f|--file) _files ;; 305 -p|--package) state=package_file ;; 306 -g|--group) state=groups ;; 307 --fileid|--pkgid) _message -e md5 md5 ;; 308 --hdrid) _message -e sha1 sha1 ;; 309 --querybynumber) _message -e value number ;; 310 --tid) _message -e ids 'transaction id' ;; 311 --what*) state=capabilities ;; 312 --specfile) state=spec_files ;; 313 *) state=package ;; 314 esac 315 ;; 316 macros) 317 local -a macros 318 macros=( ${${${(M)${(f)"$(_call_program macros rpm --showrc)"}:#(-|)[0-9]##[:=] ##*}#* }%%[[:blank:](]*} ) 319 _description macros expl macro 320 if zstyle -t ":completion:${curcontext}:macros" prefix-hidden; then 321 compadd "$expl[@]" -p '%' -a - macros 322 else 323 macros=( %${^macros} ) 324 compadd "$expl[@]" -a - macros 325 fi 326 ;; 327 target) 328 _wanted targets expl 'target platform' compadd \ 329 ${${(M)${(f)"$(_call_programs targets rpm --showrc)"}:#compatible archs*}##*: } 330 ;; 331 groups) 332 if ( (( ! $+_rpm_groups )) || _cache_invalid rpm-groups ) && 333 ! _retrieve_cache rpm-groups 334 then 335 typeset -gaU _rpm_groups 336 _rpm_groups=( 337 ${(f)"$(_call_program groups rpm -qa --queryformat '%\{group}\\n' 2>/dev/null)"} 338 ) 339 _store_cache RPM-groups _rpm_groups 340 fi 341 _wanted groups expl 'group' _multi_parts / _rpm_groups 342 ;; 343 file_or_package) 344 if [[ $PREFIX = /* ]]; then 345 _wanted files expl 'file' _files 346 else 347 state=package 348 fi 349 ;; 350 package) 351 if ( [[ ${+_rpms} -eq 0 ]] || _cache_invalid RPMs ) && 352 ! _retrieve_cache RPMs; 353 then 354 _rpms=( $(_call_program packages rpm -qa) ) 355 _store_cache RPMs _rpms 356 fi 357 _wanted packages expl 'package' \ 358 compadd -M 'r:|-=* r:|=*' - "$_rpms[@]" 359 ;; 360 spec_files) 361 _wanted specfiles expl 'spec file' \ 362 _files -g '*.spec(-.)' 363 ;; 364 package_file) 365 _wanted files expl 'package file' \ 366 _files -g '*.(#i)rpm(-.)' 367 if [[ -prefix 1 (f|ht)tp:// ]]; then 368 _wanted urls expl 'URL of rpm package file' \ 369 _urls -f -g '*.(#i)rpm(-.)' "${expl[@]}" 370 else 371 _wanted urls expl 'URL of rpm package file' \ 372 compadd -S '' "${expl[@]}" ftp:// http:// 373 fi 374 ;; 375 package_src) 376 _wanted files expl 'source package' _files -g '(#i)*.src.rpm(-.)' 377 ;; 378 tags) 379 local -a suf 380 if compset -P "*%*${${QIPREFIX:+{}:-\{}"; then 381 compset -S '(|\\)}*' || suf=( -S ${${QIPREFIX:+\}}:-\\\}} -r ": \}\t\n\-" ) 382 if compset -P '*:'; then 383 _wanted formats expl format compadd $suf - \ 384 armor arraysize base64 date day depflags deptype expand \ 385 fflags fstate fstatus hex octal humaniec humansi perms \ 386 pgpsig shescape triggertype vflags xml 387 else 388 _wanted tags expl 'rpm tag' compadd -M 'm:{a-z}={A-Z}' "$suf[@]" - \ 389 "${(L@)${(@f)$(_call_program tags rpm --querytags)}#RPMTAG_}" 390 fi 391 else 392 _message -e formats 'rpm query format' 393 fi 394 ;; 395 capabilities) 396 local match mbegin mend 397 if [[ "${opt_args[(i)${sopts// /|}]}" = --what(#b)(*) ]]; then 398 if [[ $match[1] = provides && -prefix / ]]; then 399 _wanted files expl file _files 400 else 401 _description capabilities expl capability 402 compadd ${${(f)"$(_call_program capabilities rpm -qa --queryformat '%\{$match[1]}\\n')"}:#\(none\)} 403 fi 404 fi 405 ;; 406 relocate) 407 if compset -P 1 '*='; then 408 _description directories expl 'new path' 409 else 410 _description directories expl 'old path' 411 fi 412 413 _files "$expl[@]" -/ 414 ;; 415 public_keys) 416 _arguments -s -C \!--import $commonopts \ 417 '*:public key:_files' 418 ;; 419 brp_policies) 420 local rpmconfigdir=$(_call_program policies rpm -E '%\{_rpmconfigdir\}') 421 _wanted policies expl policy compadd $rpmconfigdir/brp-*(N:t:s/brp-//) 422 ;; 423 esac 424 425 [[ $nm -ne $compstate[nmatches] ]] && return 0 426 done 427 428 return ret 429} 430 431# set a sensible default caching policy 432local update_policy 433zstyle -s ":completion:*:*:rpm:*" cache-policy update_policy 434if [[ -z "$update_policy" ]]; then 435 zstyle ":completion:*:*:rpm:*" cache-policy _rpms_caching_policy 436fi 437 438_rpms_caching_policy () { 439 # rebuild if cache is more than a week old 440 local -a oldp 441 oldp=( "$1"(mw+1) ) 442 (( $#oldp )) && return 0 443 444 pkg_indices=( /var/lib/rpm/{packages.rpm,Packages}(N) ) 445 for pkg_index in $pkg_indices; do 446 [[ "$pkg_index" -nt "$1" ]] && return 0 447 done 448} 449 450_rpm "$@" 451