# bash completion for rpm

have rpm && {
# helper functions

_rpm_installed_packages()
{
    local nodig="$1" nosig="$2"

    if [ -r /var/log/rpmpkgs -a \
        /var/log/rpmpkgs -nt /var/lib/rpm/Packages ]; then
        # using RHL 7.2 or later - this is quicker than querying the DB
        COMPREPLY=( $( sed -ne \
            's|^\('$cur'[^[:space:]]*\)-[^[:space:]-]\+-[^[:space:]-]\+\.rpm$|\1|p' \
            /var/log/rpmpkgs ) )
    else
        _rpm_nodigsig
        COMPREPLY=( $( rpm -qa $nodig $nosig --qf='%{NAME} ' "$cur*" ) )
    fi
}

_rpm_groups()
{
    # TODO: shown completions are wrong but real ones work nevertheless
    # http://lists.alioth.debian.org/pipermail/bash-completion-devel/2009-May/001486.html
    local IFS=$'\n'
    COMPREPLY=( $( compgen -W "$( rpm -qa $nodig $nosig --queryformat \
        '%{group}\n' )" -- "$cur" ) )
}

_rpm_nodigsig()
{
    if [ -z "$nodig" -a -z "$nosig" ]; then
        local rpmver

        rpmver=$(rpm --version)
        rpmver=${rpmver##* }

        if [[ "$rpmver" > "4.0.4" ]]; then
            nodig="--nodigest"
        fi
        if [[ "$rpmver" > "4.0.99" ]]; then
            nosig="--nosignature"
        fi
    fi
}

# rpm(8) completion
#
_rpm()
{
    local cur prev opts nodig nosig

    COMPREPLY=()
    cur=`_get_cword`
    prev=${COMP_WORDS[COMP_CWORD-1]}
    nodig=""
    nosig=""
    _rpm_nodigsig

    if [ $COMP_CWORD -eq 1 ]; then
        # first parameter on line
        case "$cur" in
            -b*)
                COMPREPLY=( $( compgen -W '-ba -bb -bc -bi -bl -bp -bs' \
                    -- "$cur" ) )
                ;;
            -t*)
                COMPREPLY=( $( compgen -W '-ta -tb -tc -ti -tl -tp -ts' \
                    -- "$cur" ) )
                ;;
            --*)
                COMPREPLY=( $( compgen -W '--help --version --initdb \
                    --checksig --recompile --rebuild --resign --addsign \
                    --rebuilddb --showrc --setperms --setugids --tarbuild \
                    --eval --install --upgrade --query --freshen --erase \
                    --verify --querytags --rmsource --rmspec --clean \
                    --import' -- "$cur" ) )
                ;;
            *)
                COMPREPLY=( $( compgen -W '-b -e -E -F -i -q -t -U -V' \
                    -- "$cur" ) )
                ;;
        esac

    return 0
    fi

    case "$prev" in
        --@(@(db|exclude)path|prefix|relocate|root))
            _filedir -d
            return 0
            ;;
        --eval|-E)
            # get a list of macros
            COMPREPLY=( $( rpm --showrc | sed -ne \
                's/^-\?[0-9]\+[:=][[:space:]]\+\('${cur#%}'[^[:space:](]*\).*/\1/p' ) )
            COMPREPLY=( "${COMPREPLY[@]/#/%}" )
            return 0
            ;;
        --pipe)
            COMPREPLY=( $( compgen -c -- "$cur" ) )
            return 0
            ;;
        --rcfile)
            _filedir
            return 0
            ;;
        --specfile)
            # complete on .spec files
            _filedir spec
            return 0
            ;;
        --whatprovides)
            if [[ "$cur" == */* ]]; then
                _filedir
            else
                # complete on capabilities
            local IFS=$'\n'
            COMPREPLY=( $( compgen -W "$( rpm -qa $nodig $nosig \
                --queryformat='%{providename}\n' )" -- "$cur" ) )
            fi
            return 0
            ;;
        --whatrequires)
            if [[ "$cur" == */* ]]; then
                _filedir
            else
                # complete on capabilities
                local IFS=$'\n'
                COMPREPLY=( $( compgen -W "$( rpm -qa $nodig $nosig \
                        --queryformat='%{requirename}\n' )" \
                        -- "$cur" ) )
            fi
            return 0
            ;;
        --target)
            COMPREPLY=( $( compgen -W "$( command rpm --showrc | sed -ne \
                's/^\s*compatible\s\+build\s\+archs\s*:\s*\(.*\)/\1/ p' )" \
                -- "$cur" ) )
            return 0
            ;;
        --define|-D)
            # argument required but no completions available
            return 0
            ;;
    esac

    # options common to all modes
    opts="--define --eval --macros --nodigest --nosignature --rcfile \
        --quiet --pipe --verbose"

    case "${COMP_WORDS[1]}" in
        -@([iFU]*|-install|-freshen|-upgrade))
            if [[ "$cur" == -* ]]; then
                COMPREPLY=( $( compgen -W "$opts --percent --force \
                --test --replacepkgs --replacefiles --root \
                --excludedocs --includedocs --noscripts --ignorearch \
                --dbpath --prefix --ignoreos --nodeps --allfiles \
                --ftpproxy --ftpport --justdb --httpproxy --httpport \
                --noorder --relocate --badreloc --notriggers \
                --excludepath --ignoresize --oldpackage \
                --queryformat --repackage --nosuggests" -- "$cur" ) )
            else
                _filedir 'rpm'
            fi
            ;;
        -@(e|-erase))
            if [[ "$cur" == -* ]]; then
                COMPREPLY=( $( compgen -W "$opts --allmatches \
                --noscripts --notriggers --nodeps --test --repackage" \
                -- "$cur" ) )
            else
                _rpm_installed_packages "$nodig" "$nosig"
            fi
            ;;
        -@(q*|-query))
            # options common to all query types
            opts="$opts --changelog --configfiles --conflicts --docfiles
                --dump --enhances --filesbypkg --filecaps --fileclass
                --filecolor --fileprovide --filerequire --filesbypkg
                --info --list --obsoletes --pipe --provides
                --queryformat --rcfile --requires --scripts --suggests
                --triggeredby --triggers --whatprovides --whatrequires --xml"

            if [ "${COMP_LINE#* -*([^ -])f}" != "$COMP_LINE" ]; then
                # -qf completion
                if [[ "$cur" == -* ]]; then
                    COMPREPLY=( $( compgen -W "$opts --dbpath --fscontext \
                        --last --root --state" -- "$cur" ) )
                else
                    _filedir
                fi
            elif [ "${COMP_LINE#* -*([^ -])g}" != "$COMP_LINE" ]; then
                # -qg completion
                _rpm_groups
            elif [ "${COMP_LINE#* -*([^ -])p}" != "$COMP_LINE" ]; then
                # -qp; uninstalled package completion
                if [[ "$cur" == -* ]]; then
                    COMPREPLY=( $( compgen -W "$opts --ftpport --ftpproxy \
                        --httpport --httpproxy" -- "$cur" ) )
                else
                    _filedir 'rpm'
                fi
            else
                # -q; installed package completion
                if [[ "$cur" == -* ]]; then
                    COMPREPLY=( $( compgen -W "$opts --dbpath --fscontext \
                        --last --root --state" -- "$cur" ) )
                elif [ "${COMP_LINE#* -*([^ -])a}" == "$COMP_LINE" ]; then
                    _rpm_installed_packages "$nodig" "$nosig"
                fi
            fi
            ;;
        -@(K*|-checksig))
            if [[ "$cur" == -* ]]; then
                COMPREPLY=( $( compgen -W "$opts --nopgp --nogpg --nomd5" \
                    -- "$cur" ) )
            else
                _filedir 'rpm'
            fi
            ;;
        -@([Vy]*|-verify))
            if [[ "$cur" == -* ]]; then
                COMPREPLY=( $( compgen -W "$opts --root --dbpath --nodeps \
                    --nogroup --nolinkto --nomode --nomtime --nordev --nouser \
                    --nofiles --noscripts --nomd5 --querytags --specfile \
                    --whatrequires --whatprovides" -- "$cur" ) )
            # check whether we're doing file completion
            elif [ "${COMP_LINE#* -*([^ -])f}" != "$COMP_LINE" ]; then
                _filedir
            elif [ "${COMP_LINE#* -*([^ -])g}" != "$COMP_LINE" ]; then
                _rpm_groups
            elif [ "${COMP_LINE#* -*([^ -])p}" != "$COMP_LINE" ]; then
                _filedir 'rpm'
            else
                _rpm_installed_packages "$nodig" "$nosig"
            fi
            ;;
        -[bt]*)
            if [[ "$cur" == -* ]]; then
                COMPREPLY=( $( compgen -W "$opts --short-circuit --timecheck \
                    --clean --rmsource --rmspec --test --sign --buildroot \
                    --target --nobuild --nodeps --nodirtokens" -- "$cur" ) )
            elif [[ ${COMP_WORDS[1]} == -b* ]]; then
                _filedir 'spec'
            else
                _filedir '@(t?(ar.)@([gx]z|bz?(2))|tar.@(lzma|Z))'
            fi
            ;;
        --re@(build|compile))
            if [[ "$cur" == -* ]]; then
                COMPREPLY=( $( compgen -W "$opts --nodeps --rmsource \
                  --rmspec --sign --nodirtokens --target" -- "$cur" ) )
            else
                _filedir '?(no)src.rpm'
            fi
            ;;
        --tarbuild)
            _filedir '@(t?(ar.)@([gx]z|bz?(2))|tar.@(lzma|Z))'
            ;;
        --@(re|add)sign)
            _filedir 'rpm'
            ;;
        --set@(perms|gids))
            _rpm_installed_packages "$nodig" "$nosig"
            ;;
        --@(clean|rms@(ource|pec)))
            if [[ "$cur" == -* ]]; then
                COMPREPLY=( $( compgen -W '--clean --rmsource --rmspec' \
                    -- "$cur" ) )
            else
                _filedir 'spec'
            fi
            ;;
        --@(import|dbpath|root))
            if [[ "$cur" == -* ]]; then
            COMPREPLY=( $( compgen -W '--import --dbpath --root' \
                    -- "$cur" ) )
            else
                _filedir
            fi
            ;;
    esac

    return 0
}
complete -F _rpm $filenames rpm rpmbuild
}

# Local variables:
# mode: shell-script
# sh-basic-offset: 4
# sh-indent-comment: t
# indent-tabs-mode: nil
# End:
# ex: ts=4 sw=4 et filetype=sh
