# bash completion for rpm

have rpm && {
# helper functions

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

    if [[ -r /var/log/rpmpkgs && \
        /var/log/rpmpkgs -nt /var/lib/rpm/Packages ]]; then
        # using RHL 7.2 or later - this is quicker than querying the DB
        COMPREPLY=( $( compgen -W "$( sed -ne \
            's|^\([^[:space:]]\{1,\}\)-[^[:space:]-]\{1,\}-[^[:space:]-]\{1,\}\.rpm$|\1|p' \
            /var/log/rpmpkgs )" -- "$cur" ) )
    elif type rpmqpack &>/dev/null ; then
        # SUSE's rpmqpack is faster than rpm -qa
        COMPREPLY=( $( compgen -W '$( rpmqpack )' -- "$cur" ) )
    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" && -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=()
    _get_comp_words_by_ref cur prev
    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
        --dbpath|--excludepath|--prefix|--relocate|--root)
            _filedir -d
            return 0
            ;;
        --eval|-E)
            # get a list of macros
            COMPREPLY=( $( compgen -W "$( rpm --showrc | sed -ne \
                's/^-\{0,1\}[0-9]\{1,\}[:=][[:space:]]\{1,\}\([^[:space:](]\{3,\}\).*/%\1/p' )" \
                -- "$cur" ) )
            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\s*build\s\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
            ;;
        --rebuild|--recompile)
            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))'
            ;;
        --resign|--addsign)
            _filedir 'rpm'
            ;;
        --setperms|--setgids)
            _rpm_installed_packages "$nodig" "$nosig"
            ;;
        --clean|--rmsource|--rmspec)
            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 -o 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
