Advertisement
davidva

pacaur modified asking sudo with zenity

Apr 7th, 2014
275
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 51.57 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. #
  4. # pacaur: a fast workflow AUR helper using cower as backend
  5. #
  6.  
  7. version="4.1.25"
  8.  
  9. #
  10. # Config
  11. #
  12.  
  13. # internationalization
  14. LC_COLLATE=C                                # getopts sorting
  15. TEXTDOMAIN='pacaur'
  16. TEXTDOMAINDIR='/usr/share/locale'
  17.  
  18. # source makepkg variables
  19. source /etc/makepkg.conf
  20. [[ -r "$HOME/.makepkg.conf" ]] && source "$HOME/.makepkg.conf"
  21.  
  22. # set variables
  23. tmpdir="${TMPDIR:-/tmp}/pacaurtmp-$USER"    # temp directory
  24. builddir="${BUILDDIR:-$tmpdir}"             # build directory
  25. editor="${EDITOR:-vi}"                      # PKGBUILD editor
  26. editpkgbuild=true                           # edit PKGBUILD
  27. editinstall=true                            # edit install script
  28. fallback=true                               # pacman fallback to the AUR
  29. clean=true                                  # cleanup after install
  30. cleandevel=true                             # cleanup devel after install
  31. secure=false                                # enhanced security
  32. sudoloop=false                              # prevent sudo timeout
  33.  
  34. # set pacman binary
  35. pacmanbin="${PACMAN:-pacman}"
  36.  
  37. # source xdg config
  38. if [[ -n "${XDG_CONFIG_DIRS}" ]]; then
  39.     xdg_config=($(awk -F ":" '{for (i=1; i<=NF; i++) print $i}' <<< ${XDG_CONFIG_DIRS}))
  40.     for i in "${xdg_config[@]}"; do
  41.         [[ -d "$i" ]] && export XDG_CONFIG_DIRS="$i" && break
  42.     done
  43. fi
  44. configdir="${XDG_CONFIG_DIRS:-/etc/xdg}/pacaur"
  45. userconfigdir="${XDG_CONFIG_HOME:-${HOME}/.config}/pacaur"
  46. source "$configdir/config"
  47. [[ -r "$userconfigdir/config" ]] && source "$userconfigdir/config"
  48.  
  49. # set up directories
  50. [[ -d "$tmpdir" ]] && [[ ! -w "$tmpdir" ]] && sudo rm -rf "$tmpdir"
  51. [[ ! -d "$tmpdir" ]] && mkdir -p "$tmpdir"
  52. [[ ! -d "$builddir" ]] && mkdir -p "$builddir"
  53.  
  54. #
  55. # Functions
  56. #
  57.  
  58. ClassifyPkgs() {
  59.     if [[ $fallback = true ]]; then
  60.         [[ $repo ]] && repopkgs=("${pkgs[@]}")
  61.         [[ $aur ]] && aurpkgs=("${pkgs[@]}")
  62.         if [[ ! $repo && ! $aur ]]; then
  63.             getignoredgrps
  64.             for i in "${pkgs[@]}"; do
  65.                 [[ $i == aur/* ]] && i=${i:4} && aurpkgs+=("$i") && continue
  66.                 [[ " ${ignoredgrps[@]} " =~ " $i " ]] && repopkgs+=("$i") && continue
  67.                 [[ -z "$(expac -S '%n' "$i" || expac -Sg '%n' "$i")" ]] && aurpkgs+=("$i") || repopkgs+=("$i")
  68.             done
  69.         fi
  70.     else
  71.         [[ ! $aur ]] && repopkgs=("${pkgs[@]}") || aurpkgs=("${pkgs[@]}")
  72.     fi
  73. }
  74.  
  75. Core() {
  76.     getignoredpkgs
  77.     [[ $upgrade ]] && UpgradeAur
  78.     IgnoreChecks
  79.     DownloadPkgs
  80.     IgnoreDepsChecks
  81.     ProviderChecks
  82.     getversionedpkgs
  83.     ConflictChecks
  84.     ReinstallChecks
  85.     OutofdateChecks
  86.     Prompt
  87.     MakePkgs
  88. }
  89.  
  90. UpgradeAur() {
  91.     note "i" $"${colorW}Starting AUR upgrade...${reset}"
  92.     [[ -e "$tmpdir/ignoretmp" ]] && rm "$tmpdir/ignoretmp"
  93.     aurpkgs+=($(cower -u ${coweropts[@]} ${pkgs[@]} 2>"$tmpdir/ignoretmp" | sed -r "s:\x1B\[[0-9;]*[mK]::g" | awk -F " " '{print $2}'))
  94.     [[ -e "$tmpdir/ignoretmp" ]] && aurpkgs+=($(awk -F " " '{print $2}' "$tmpdir/ignoretmp" | sed -r "s:\x1B\[[0-9;]*[mK]::g"))
  95.  
  96.     # foreign packages check
  97.     foreignpkgs=($($pacmanbin -Qmq | LC_COLLATE=C sort -u))
  98.     downloadjson ${foreignpkgs[@]}
  99.     allaurpkgs=($(getjsonvar "Name" | LC_COLLATE=C sort -u))
  100.     aurforeignpkgs=($(LC_COLLATE=C comm -23 <(echo "${foreignpkgs[@]}" | tr ' ' '\n') <(echo "${allaurpkgs[@]}" | tr ' ' '\n')))
  101.     for i in "${aurforeignpkgs[@]}"; do
  102.         note "w" $"${colorW}$i${reset} is ${colorY}not present${reset} in AUR -- skipping"
  103.     done
  104.  
  105.     # add devel packages
  106.     if [[ $devel ]]; then
  107.         for i in "${allaurpkgs[@]}"; do
  108.             [[ -n "$(echo "$i" | grep -E "\-(cvs|svn|git|hg|bzr|darcs)$")" ]] && aurpkgs+=("$i")
  109.        done
  110.    fi
  111.  
  112.    # avoid possible duplicate
  113.    aurpkgs=($(tr ' ' '\n' <<< ${aurpkgs[@]} | sort -u))
  114.  
  115.    nothingtodo ${aurpkgs[@]}
  116. }
  117.  
  118. IgnoreChecks() {
  119.    [[ -z "${ignoredpkgs[@]}" ]] && return
  120.  
  121.    checkaurpkgs=("${aurpkgs[@]}")
  122.    unset aurpkgs
  123.  
  124.    # check targets
  125.    downloadjson ${checkaurpkgs[@]}
  126.    checkaurpkgsAname=($(getjsonvar "Name"))    # return sorted results
  127.    checkaurpkgsAver=($(getjsonvar "Version"))
  128.    checkaurpkgsQver=($(expac -Q '%v' "${checkaurpkgsAname[@]}"))
  129.    for ((i=0; i<${#checkaurpkgsAname[@]}; i++)); do
  130.        [[ -n "$(echo "${checkaurpkgsAname[$i]}" | grep -E "\-(cvs|svn|git|hg|bzr|darcs)$")" ]] && checkaurpkgsAver[$i]=$"latest"
  131.    done
  132.    for ((i=0; i<${#checkaurpkgs[@]}; i++)); do
  133.        if [[ " ${ignoredpkgs[@]} " =~ " ${checkaurpkgs[$i]} " ]]; then
  134.            if [[ ! $upgrade && ! $noconfirm ]]; then
  135.                if ! proceed "y" $"${checkaurpkgs[$i]} is in IgnorePkg/IgnoreGroup. Install anyway?"; then
  136.                    note "w" $"${colorW}${checkaurpkgs[$i]}${reset}: ignoring package upgrade"
  137.                    continue
  138.                fi
  139.            else
  140.                note "w" $"${colorW}${checkaurpkgs[$i]}${reset}: ignoring package upgrade (${colorR}${checkaurpkgsQver[$i]}${reset} => ${colorG}${checkaurpkgsAver[$i]}${reset})"
  141.                continue
  142.            fi
  143.        fi
  144.        aurpkgs+=("${checkaurpkgs[$i]}")
  145.    done
  146.  
  147.    nothingtodo ${aurpkgs[@]}
  148. }
  149.  
  150. DownloadAur() {
  151.    while read -r flag pkg info; do
  152.        case $flag in
  153.            S)  [[ $operation = download && -n "$info" ]] && note "i" $"$pkg downloaded to $builddir";
  154.                [[ -n "$info" ]] && deps+=("$pkg");;
  155.            W)  [[ $operation = download && -n "$info" ]] && repo=$(echo $info | awk -F " " '{print $6}') && note "s" $"${colorW}$pkg${reset} is available in ${colorM}$repo${reset}" || repodeps+=("$pkg");;
  156.            E)  [[ $operation = download && -e "$builddir/$pkg/PKGBUILD" ]] && note "f" $"\`$builddir/$pkg' already exists. Use -f to overwrite." || note "f" $"no results found for $pkg";
  157.                errdeps+=("$pkg");;
  158.        esac
  159.    done < <(cower ${coweropts[@]} -db $@ ${ignoreopts[@]} -t $builddir 2>&1)
  160.  
  161.    # PKGBUILDs check
  162.    for i in "${deps[@]}"; do
  163.        [[ ! -e "$builddir/$i/PKGBUILD" ]] && errdeps+=("$i") && note "f" $"Could not read ${colorW}$i${reset} PKGBUILD: badly packaged tarball"
  164.    done
  165.    [[ -n "${errdeps[@]}" ]] && exit 1
  166. }
  167.  
  168. DownloadPkgs() {
  169.    if [[ $secure = true ]]; then
  170.        if [[ $operation = download && $count -lt 2 ]]; then
  171.            DownloadAur ${aurpkgs[@]} && return
  172.        else
  173.            [[ $operation != download ]] && note "i" $"resolving dependencies..."
  174.            coweropts+=("-d") && DownloadAur ${aurpkgs[@]} # recursive here
  175.        fi
  176.  
  177.        # check for CARCH 32/64bits bash magic
  178.        for i in "${deps[@]}"; do
  179.            [[ -n "$(grep 'CARCH' "$builddir/$i/PKGBUILD")" ]] && note "e" $"${colorW}CARCH${reset} variable detected in ${colorW}$i${reset}. Enable the full bash dependency solver with the --insecure option."
  180.        done
  181.        [[ -n "${repodeps[@]}" ]] && repodeps=($(expac -S -1 '%n' "${repodeps[@]}"))
  182.    else
  183.        [[ $operation != download ]] && note "i" $"resolving dependencies..."
  184.        allaurdeps+=("${aurpkgs[@]}")
  185.        FindPkgsDeps ${aurpkgs[@]}
  186.        deps=("${allaurdeps[@]}")
  187.  
  188.        # reduce root binary deps
  189.        repodeps=($(tr ' ' '\n' <<< ${repodeps[@]} | sort -u))
  190.    fi
  191.  
  192.    # return AUR deps pkgs only
  193.    aurdepspkgs=(${deps[@]:${#aurpkgs[@]}:${#deps[@]}})
  194.  
  195.    # return binary deps
  196.    if [[ -n "${repodeps[@]}" ]]; then
  197.        [[ $operation = download && $count -ge 2 ]] && expac -S -1 $"${colorY}::${reset} ${colorW}%n${reset} is available in ${colorM}%r${reset}" ${repodeps[@]}
  198.        for i in "${repodeps[@]}"; do
  199.            allrepopkgs+=($(pactree -su "$i" | awk -F " " '{print $NF}'))
  200.        done
  201.        repodepspkgs=($($pacmanbin -T "${allrepopkgs[@]}" | sort -u))
  202.    fi
  203. }
  204.  
  205. FindPkgsDeps() {
  206.    [[ -z "${depspkgsaur[@]}" ]] && depspkgsaur=("${aurpkgs[@]}")
  207.  
  208.    coweropts+=("--ignorerepo")
  209.    DownloadAur ${depspkgsaur[@]}
  210.    [[ $operation = download && $count -lt 2 ]] && return
  211.  
  212.    # source pkgs
  213.    for i in "${deps[@]}"; do
  214.        PreviewPkgs $i
  215.        source "$builddir/$i/PKGBUILD" && sourcedpkgs+=(${depends[*]} ${makedepends[*]})
  216.    done
  217.  
  218.    # remove installed deps
  219.    depspkgs=($($pacmanbin -T "${sourcedpkgs[@]}" | sort -u))
  220.  
  221.    # split binary and AUR depends pkgs
  222.    [[ -e "$tmpdir/tmpdeps" ]] && rm "$tmpdir/tmpdeps"
  223.    [[ -n "${depspkgs[@]}" ]] && repodeps+=($(expac -S -1 -v '%n' "${depspkgs[@]}" 2>"$tmpdir/tmpdeps"))
  224.    [[ -e "$tmpdir/tmpdeps" ]] && depspkgsaur=($(awk -F " " '{print $3}' "$tmpdir/tmpdeps" | tr -d "'\`")) || unset depspkgsaur
  225.    unset deps depends makedepends sourcedpkgs depspkgs
  226.  
  227.    if [[ -n "${depspkgsaur[@]}" ]]; then
  228.        # remove AUR package versioning
  229.        for ((i=0; i<${#depspkgsaur[@]}; i++)); do
  230.            depspkgsaur[$i]=$(awk -F ">|<|=" '{print $1}' <<< ${depspkgsaur[$i]})
  231.        done
  232.        # ensure correct dependency order
  233.        depspkgsaurtmp=(${depspkgsaur[@]})
  234.        for ((i=0; i<${#depspkgsaurtmp[@]}; i++)); do
  235.            if [[ " ${allaurdeps[@]} " =~ " ${depspkgsaurtmp[$i]} " ]]; then
  236.                allaurdeps=($(tr ' ' '\n' <<< ${allaurdeps[@]} | sed "s/^${depspkgsaurtmp[$i]}$//g")) && allaurdeps+=("${depspkgsaurtmp[$i]}")
  237.                # avoid duplicated download
  238.                depspkgsaur=($(tr ' ' '\n' <<< ${depspkgsaur[@]} | sed "s/^${depspkgsaurtmp[$i]}$//g")) && deps+=("${depspkgsaurtmp[$i]}")
  239.            fi
  240.        done
  241.    fi
  242.  
  243.    if [[ -n "${depspkgsaur[@]}" ]]; then
  244.        allaurdeps+=("${depspkgsaur[@]}")
  245.        FindPkgsDeps ${depspkgsaur[@]}
  246.    fi
  247. }
  248.  
  249. PreviewPkgs() {
  250.    # sanitize
  251.    cp "$builddir/$i/PKGBUILD" "$builddir/$i/PKGBUILD.sudocheck"
  252.    while [[ -n "$(grep -Po '^depends=\($|^depends=\([^)].*[^)]$' "$builddir/$i/PKGBUILD.sudocheck")" ]]; do
  253.        sed -i -e '/^depends=*[^)]/N' -e 's/ \+/ /' -e 's/\t/ /' -e 's/\n//' "$builddir/$i/PKGBUILD.sudocheck"
  254.    done
  255.    while [[ -n "$(grep -Po '^optdepends=\($|^optdepends=\([^)].*[^)]$' "$builddir/$i/PKGBUILD.sudocheck")" ]]; do
  256.        sed -i -e '/^optdepends=*[^)]/N' -e 's/ \+/ /' -e 's/\t/ /' -e 's/\n//' "$builddir/$i/PKGBUILD.sudocheck"
  257.    done
  258.  
  259.    # sudo security check
  260.    [[ -n "$(grep -w 'sudo' "$builddir/$i/PKGBUILD.sudocheck" | grep -Ev '^depends|^optdepends|^pkgdesc')" ]] && note "w" $"Potentially dangerous '${colorR}sudo${reset}' detected in ${colorW}$i${reset}" && EditPkgs $i || return
  261.    if [[ ! $noconfirm ]]; then
  262.        if proceed "n" $"Do you really want to continue?"; then
  263.            CleanUp ${deps[@]} &>/dev/null
  264.            exit
  265.        fi
  266.    fi
  267. }
  268.  
  269. IgnoreDepsChecks() {
  270.    [[ -z "${ignoredpkgs[@]}" ]] && return
  271.    unset deps
  272.  
  273.    # add checked targets
  274.    deps+=("${aurpkgs[@]}")
  275.  
  276.    # check dependencies
  277.    for i in "${repodepspkgs[@]}"; do
  278.        if [[ " ${ignoredpkgs[@]} " =~ " $i " ]]; then
  279.            note "w" $"${colorW}$i${reset}: ignoring package upgrade"
  280.            CleanUp ${aurpkgs[@]} &>/dev/null
  281.            CleanUp ${aurdepspkgs[@]} &>/dev/null
  282.            note "e" $"Unresolved dependency '${colorW}$i${reset}'"
  283.        fi
  284.    done
  285.    for i in "${aurdepspkgs[@]}"; do
  286.        if [[ " ${ignoredpkgs[@]} " =~ " $i " ]]; then
  287.            if [[ ! $noconfirm ]]; then
  288.                if ! proceed "y" $"$i dependency is in IgnorePkg/IgnoreGroup. Install anyway?"; then
  289.                    CleanUp ${aurpkgs[@]} &>/dev/null
  290.                    CleanUp ${aurdepspkgs[@]} &>/dev/null
  291.                    note "e" $"Unresolved dependency '${colorW}$i${reset}'"
  292.                fi
  293.            else
  294.                note "w" $"${colorW}$i${reset}: ignoring package upgrade"
  295.                CleanUp ${aurpkgs[@]} &>/dev/null
  296.                CleanUp ${aurdepspkgs[@]} &>/dev/null
  297.                note "e" $"Unresolved dependency '${colorW}$i${reset}'"
  298.            fi
  299.        fi
  300.        deps+=("$i")
  301.    done
  302. }
  303.  
  304. ProviderChecks() {
  305.    [[ -z "${repodepspkgs[@]}" ]] && return
  306.    allproviders=($(expac -S '%S' "${repodepspkgs[@]}" | sort -u))
  307.    # remove installed providers
  308.    providersdeps=($($pacmanbin -T "${allproviders[@]}" | sort -u))
  309.  
  310.    for ((i=0; i<${#providersdeps[@]}; i++)); do
  311.        providers=($(expac -Ss '%n' "^${providersdeps[$i]}$"))
  312.        [[ ! ${#providers[@]} -gt 1 ]] && continue
  313.  
  314.        # skip if already provided
  315.        for j in "${providerpkgs[@]}"; do
  316.            provided+=($(expac -S '%P' "$j"))
  317.        done
  318.        [[ -n "${provided[@]}" ]] && [[ " ${provided[@]} " =~ " ${providersdeps[$i]} " ]] && continue
  319.  
  320.        if [[ ! $noconfirm ]]; then
  321.            note "i" $"${colorW}There are ${#providers[@]} providers available for ${providersdeps[$i]}:${reset}"
  322.            expac -S -1 '   %!) %n (%r) ' "${providers[@]}"
  323.  
  324.            local nb=-1
  325.            providersnb=$(( ${#providers[@]} -1 )) # count from 0
  326.            while [[ $nb -lt 0 || $nb -ge ${#providers} ]]; do
  327.  
  328.                printf "\n%s " $"Enter a number (default=0):"
  329.                nbchar=$(wc -l <<< ${#providers[@]})
  330.                read -n ${#nbchar} nb
  331.                echo
  332.  
  333.                case $nb in
  334.                    [0-9]) [[ $nb -lt 0 || $nb -ge ${#providers[@]} ]] && echo && note "f" $"invalid value: $nb is not between 0 and $providersnb" && ((i--)) || break;;
  335.                    '') nb=0;;
  336.                    *) note "f" $"invalid number: $nb";;
  337.                esac
  338.  
  339.            done
  340.        else
  341.            local nb=0
  342.        fi
  343.        providerpkgs+=(${providers[$nb]})
  344.        [[ $nb -ne 0 ]] && rmproviderpkgs+=(${providersdeps[$i]})
  345.    done
  346.  
  347.    # pactree always return default choice so update binary deps list
  348.    if [[ -n "${rmproviderpkgs[@]}" ]]; then
  349.        # remove deps of default providers
  350.        for i in "${rmproviderpkgs[@]}"; do
  351.            providerpkgsrm+=($(pactree -su "$i"))
  352.        done
  353.        providerpkgsrm=($($pacmanbin -T "${providerpkgsrm[@]}" | sort -u))
  354.        repodepspkgs=($(LC_COLLATE=C comm -23 <(echo "${repodepspkgs[@]}" | tr ' ' '\n') <(echo "${providerpkgsrm[@]}" | tr ' ' '\n')))
  355.  
  356.        # add deps of selected providers instead
  357.        for i in "${providerpkgs[@]}"; do
  358.            providerdeps+=($(pactree -su "$i"))
  359.        done
  360.        repodepspkgs+=($($pacmanbin -T "${providerdeps[@]}" | sort -u))
  361.    fi
  362. }
  363.  
  364. ConflictChecks() {
  365.    note "i" $"looking for inter-conflicts..."
  366.  
  367.    allQprovides=($(expac -Q '%n'))
  368.    allQprovides+=($(expac -Q '%S')) # no versioning
  369.    allQprovides=($(echo "${allQprovides[@]}" | tr ' ' '\n' | LC_COLLATE=C sort -u))
  370.    allQconflicts=($(expac -Q '%C' | tr ' ' '\n' | LC_COLLATE=C sort -u))
  371.  
  372.    # AUR conflicts
  373.    Aprovides=(${depsAname[@]})
  374.    for ((i=0; i<${#depsAname[@]}; i++)); do
  375.        Aprovides+=("$(grep "^provides=" "$builddir/${depsAname[$i]}/PKGBUILD" | cut -d '=' -f2 | tr -d "'\"()")")
  376.        Aconflicts+=("$(grep "^conflicts=" "$builddir/${depsAname[$i]}/PKGBUILD" | cut -d '=' -f2 | tr -d "'\"()")")
  377.    done
  378.    Aprovides=($(echo "${Aprovides[@]}" | tr ' ' '\n' | LC_COLLATE=C sort -u))
  379.    Aconflicts=($(echo "${Aconflicts[@]}" | tr ' ' '\n' | LC_COLLATE=C sort -u))
  380.    aurconflicts+=($(LC_COLLATE=C comm -12 <(echo "${Aprovides[@]}" | tr ' ' '\n') <(echo "${allQconflicts[@]}" | tr ' ' '\n')))
  381.    aurconflicts+=($(LC_COLLATE=C comm -12 <(echo "${Aconflicts[@]}" | tr ' ' '\n') <(echo "${allQprovides[@]}" | tr ' ' '\n')))
  382.    aurconflicts=($(echo "${aurconflicts[@]}" | tr ' ' '\n' | LC_COLLATE=C sort -u))
  383.  
  384.    for i in "${aurconflicts[@]}"; do
  385.        unset aurAconflicts
  386.        [[ " ${depsAname[@]} " =~ " $i " ]] && aurAconflicts=("$i")
  387.        for ((k=0; k<${#depsAname[@]}; k++)); do
  388.            [[ " $(grep "^conflicts=" "$builddir/${depsAname[$k]}/PKGBUILD" | cut -d '=' -f2 | tr -d "'\"()") " =~ " $i " ]] && aurAconflicts+=("${depsAname[$k]}")
  389.        done
  390.  
  391.        for j in "${aurAconflicts[@]}"; do
  392.            unset k Aprovides
  393.            k=$(expac -Q '%n' $i)
  394.            [[ $j = $k || -z "$k" ]] && continue # skip if reinstalling or if no conflict exists
  395.  
  396.            Aprovides=("$j")
  397.            if [[ ! $noconfirm && ! " ${aurconflictingpkgs[@]} " =~ " $k " ]]; then
  398.                if ! proceed "n" $"$j and $k are in conflict ($i). Remove $k?"; then
  399.                    aurconflictingpkgs+=("$j" "$k")
  400.                    for ((l=0; l<${#depsAname[@]}; l++)); do
  401.                        [[ " ${depsAname[$l]} " =~ "$k" ]] && depsQver[$l]=$(expac -Q '%v' "$k")
  402.                    done
  403.                    Aprovides+=("$(grep "^provides=" "$builddir/$j/PKGBUILD" | cut -d '=' -f2 | tr -d "'\"()")")
  404.                    [[ ! " ${Aprovides[@]} " =~ " $k " ]] && checkQrequires $k
  405.                    break
  406.                else
  407.                    note "f" $"unresolvable package conflicts detected"
  408.                    note "f" $"failed to prepare transaction (conflicting dependencies)"
  409.                    note "e" "$j and $k are in conflict"
  410.                fi
  411.            fi
  412.            Aprovides+=("$(grep "^provides=" "$builddir/$j/PKGBUILD" | cut -d '=' -f2 | tr -d "'\"()")")
  413.            [[ ! " ${Aprovides[@]} " =~ " $k " ]] && checkQrequires $k
  414.        done
  415.    done
  416.  
  417.    nothingtodo ${deps[@]}
  418.  
  419.    # repo conflicts
  420.    if [[ -n "${repodepspkgs[@]}" ]]; then
  421.        repodepsprovides=(${repodepspkgs[@]})
  422.        repodepsprovides+=($(expac -S '%S' "${repodepspkgs[@]}")) # no versioning
  423.        repodepsprovides=($(echo "${repodepsprovides[@]}" | tr ' ' '\n' | LC_COLLATE=C sort -u))
  424.        repodepsconflicts=($(expac -S '%C' "${repodepspkgs[@]}" | tr ' ' '\n' | LC_COLLATE=C sort -u))
  425.        repoconflicts+=($(LC_COLLATE=C comm -12 <(echo "${repodepsprovides[@]}" | tr ' ' '\n') <(echo "${allQconflicts[@]}" | tr ' ' '\n')))
  426.        repoconflicts+=($(LC_COLLATE=C comm -12 <(echo "${repodepsconflicts[@]}" | tr ' ' '\n') <(echo "${allQprovides[@]}" | tr ' ' '\n')))
  427.        repoconflicts=($(echo "${repoconflicts[@]}" | tr ' ' '\n' | LC_COLLATE=C sort -u))
  428.    fi
  429.  
  430.    for i in "${repoconflicts[@]}"; do
  431.        unset Qprovides
  432.        repoSconflicts=($(expac -S '%n %C %S' "${repodepspkgs[@]}" | grep -E "[^a-zA-Z0-9_@\.\+-]+[\+]*$i" | grep -E "$i[\+]*[^a-zA-Z0-9_@\.\+-]+" | awk -F " " '{print $1}'))
  433.        for j in "${repoSconflicts[@]}"; do
  434.            unset k && k=$(expac -Q '%n' $i)
  435.            [[ -z "$k" ]] && continue # skip when no conflict with repopkgs
  436.  
  437.            if [[ ! $noconfirm && ! " ${repoconflictingpkgs[@]} " =~ " $k " ]]; then
  438.                if ! proceed "n" $"$j and $k are in conflict ($i). Remove $k?"; then
  439.                    repoconflictingpkgs+=("$j" "$k")
  440.                    Qprovides=("$(expac -S '%S' "$k")")
  441.                    [[ ! " ${Qprovides[@]} " =~ " $k " ]] && checkQrequires $k
  442.                    break
  443.                else
  444.                    note "f" $"unresolvable package conflicts detected"
  445.                    note "f" $"failed to prepare transaction (conflicting dependencies)"
  446.                    note "e" "$j and $k are in conflict"
  447.                fi
  448.            fi
  449.            Qprovides=("$(expac -S '%S' "$k")")
  450.            [[ ! " ${Qprovides[@]} " =~ " $k " ]] && checkQrequires $k
  451.        done
  452.    done
  453. }
  454.  
  455. ReinstallChecks() {
  456.    depsAtmp=(${depsAname[@]})
  457.    for ((i=0; i<${#depsAtmp[@]}; i++)); do
  458.        [[ ! " ${aurpkgs[@]} " =~ " ${depsAname[$i]} " || " ${aurconflictingpkgs[@]} " =~ " ${depsAname[$i]} " ]] && continue
  459.        [[ -z "${depsQver[$i]}" || "${depsQver[$i]}" = '#' || $(vercmp "${depsAver[$i]}" "${depsQver[$i]}") -gt 0 ]] && continue
  460.        if [[ -n "$(echo "${depsAname[$i]}" | grep -E "\-(cvs|svn|git|hg|bzr|darcs)$")" ]]; then
  461.            note "w" $"${colorW}${depsAname[$i]}${reset} latest revision -- fetching"
  462.        else
  463.            if [[ ! $needed ]]; then
  464.                note "w" $"${colorW}${depsAname[$i]}-${depsQver[$i]}${reset} is up to date -- reinstalling"
  465.            else
  466.                note "w" $"${colorW}${depsAname[$i]}-${depsQver[$i]}${reset} is up to date -- skipping"
  467.                deps=($(tr ' ' '\n' <<< ${deps[@]} | sed "s/^${depsAname[$i]}$//g"))
  468.                unset depsAname[$i] depsQver[$i] depsAver[$i] depsAood[$i]
  469.            fi
  470.        fi
  471.    done
  472.    [[ $needed ]] && depsAname=(${depsAname[@]}) && depsQver=(${depsQver[@]}) && depsAver=(${depsAver[@]}) && depsAood=(${depsAood[@]})
  473.  
  474.    nothingtodo ${deps[@]}
  475. }
  476.  
  477. OutofdateChecks() {
  478.    for ((i=0; i<${#depsAname[@]}; i++)); do
  479.        [[ "${depsAood[$i]}" -gt 0 ]] && note "w" $"${colorW}${depsAname[$i]}-${depsAver[$i]}${reset} has been flagged ${colorR}out of date${reset} on ${colorY}$(date -d "@${depsAood[$i]}" "+%Y-%m-%d")${reset}"
  480.    done
  481. }
  482.  
  483. Prompt() {
  484.    # compute binary size
  485.    if [[ -n "${repodepspkgs[@]}" ]]; then
  486.        binaryksize=($(expac -S -1 '%k' "${repodepspkgs[@]}"))
  487.        binarymsize=($(expac -S -1 '%m' "${repodepspkgs[@]}"))
  488.        sumk=0
  489.        summ=0
  490.        for ((i=0; i<${#repodepspkgs[@]}; i++)); do
  491.            getcachedpkg "${repodepspkgs[$i]}-${repodepsSver[$i]}" '/var/cache/pacman/pkg'
  492.            [[ $cachedpkg ]] && binaryksize=(${binaryksize[@]/${binaryksize[$i]}/0})
  493.            sumk=$(($sumk + ${binaryksize[$i]}))
  494.            summ=$(($summ + ${binarymsize[$i]}))
  495.        done
  496.        sumk=$(awk '{ printf("%.2f\n", $1/$2) }' <<< "$sumk 1048576")
  497.        summ=$(awk '{ printf("%.2f\n", $1/$2) }' <<< "$summ 1048576")
  498.    fi
  499.  
  500.    # cached packages check
  501.    for ((i=0; i<${#depsAname[@]}; i++)); do
  502.        [[ ! $PKGDEST || $rebuild ]] && break
  503.        getcachedpkg "${depsAname[$i]}-${depsAver[$i]}" "$PKGDEST"
  504.        [[ $cachedpkg ]] && cachedpkgs+=(${depsAname[$i]}) && depsAcached[$i]=$"(cached)" || depsAcached[$i]=""
  505.        unset cachedpkg
  506.    done
  507.  
  508.    if [[ -n "$(grep '^VerbosePkgLists' '/etc/pacman.conf')" ]]; then
  509.        strname=$"Name"; stroldver=$"Old Version"; strnewver=$"New Version"; strsize=$"Download Size"
  510.        lname=$(getlength ${depsArepo[@]} ${repodepsSrepo[@]} "$strname")
  511.        lver=$(getlength ${depsQver[@]} ${depsAver[@]} ${repodepsQver[@]} ${repodepsSver[@]} "$stroldver" "$strnewver")
  512.        lsize=$(getlength "$strsize")
  513.  
  514.        # local version column cleanup
  515.        for ((i=0; i<${#deps[@]}; i++)); do
  516.            [[ "${depsQver[$i]}" =~ '#' ]] && unset depsQver[$i]
  517.        done
  518.        # show detailed output
  519.        printf "\n${colorY}%s${reset}\n\n" $"AUR Packages  (${#deps[@]}):"
  520.        printf "${colorW}%-${lname}s  %-${lver}s  %-${lver}s${reset}\n\n" "$strname" "$stroldver" "$strnewver"
  521.        for ((i=0; i<${#deps[@]}; i++)); do
  522.            printf "%-${lname}s  ${colorR}%-${lver}s${reset}  ${colorG}%-${lver}s${reset}  %${lsize}s\n" "${depsArepo[$i]}" "${depsQver[$i]}" "${depsAver[$i]}" "${depsAcached[$i]}";
  523.        done
  524.  
  525.        if [[ -n "${repodepspkgs[@]}" ]]; then
  526.            for ((i=0; i<${#repodepspkgs[@]}; i++)); do
  527.                binarysize[$i]=$(awk '{ printf("%.2f\n", $1/$2) }' <<< "${binaryksize[$i]} 1048576")
  528.            done
  529.            printf "\n${colorY}%s${reset}\n\n" $"Repo Packages (${#repodepspkgs[@]}):"
  530.            printf "${colorW}%-${lname}s  %-${lver}s  %-${lver}s  %s${reset}\n\n" $"Name" $"Old Version" $"New Version" $"Download Size"
  531.            for ((i=0; i<${#repodepspkgs[@]}; i++)); do
  532.                printf "%-${lname}s  ${colorR}%-${lver}s${reset}  ${colorG}%-${lver}s${reset}  %${lsize}s\n" "${repodepsSrepo[$i]}" "${repodepsQver[$i]}" "${repodepsSver[$i]}" $"${binarysize[$i]} MiB";
  533.            done
  534.        fi
  535.    else
  536.        # show version
  537.        for ((i=0; i<${#deps[@]}; i++)); do
  538.            depsver="${depsver}${depsAname[$i]}-${depsAver[$i]}  "
  539.        done
  540.        for ((i=0; i<${#repodepspkgs[@]}; i++)); do
  541.            repodepspkgsver="${repodepspkgsver}${repodepspkgs[$i]}-${repodepsSver[$i]}  "
  542.        done
  543.        printf "\n${colorY}%-17s${reset} %s\n" $"AUR Packages  (${#deps[@]}):" "$depsver"
  544.        [[ -n "${repodepspkgs[@]}" ]] && printf "${colorY}%-17s${reset} %s\n" $"Repo Packages (${#repodepspkgs[@]}):" "$repodepspkgsver"
  545.    fi
  546.  
  547.    if [[ -n "${repodepspkgs[@]}" ]]; then
  548.        strrepodlsize=$"Repo Download Size:"; strrepoinsize=$"Repo Installed Size:"; strsumk=$"$sumk MiB"; strsumm=$"$summ MiB"
  549.        lreposizelabel=$(getlength "$strrepodlsize" "$strrepoinsize")
  550.        lreposize=$(getlength "$strsumk" "$strsumm")
  551.        printf "\n${colorW}%-${lreposizelabel}s${reset}  %${lreposize}s\n" "$strrepodlsize" "$strsumk"
  552.        printf "${colorW}%-${lreposizelabel}s${reset}  %${lreposize}s\n" "$strrepoinsize" "$strsumm"
  553.    fi
  554.  
  555.    echo
  556.    if [[ ! $noconfirm ]]; then
  557.        [[ $installpkg ]] && action=$"installation" || action=$"download"
  558.        if ! proceed "y" $"Proceed with $action?"; then
  559.            CleanUp ${deps[@]} &>/dev/null
  560.            exit
  561.        fi
  562.    fi
  563.  
  564.    EditPkgs ${deps[@]}
  565. }
  566.  
  567. EditPkgs() {
  568.    [[ $noedit ]] && return
  569.    for i in "$@"; do
  570.        [[ " ${cachedpkgs[@]} " =~ " $i " ]] && continue
  571.        getinstallscript $i
  572.        if [[ ! $edit ]]; then
  573.            # edit pkgbuild
  574.            if [[ ! $editpkgbuild = false ]]; then
  575.                if proceed "y" $"View $i PKGBUILD?"; then
  576.                    [[ -e "$builddir/$i/PKGBUILD" ]] && $editor "$builddir/$i/PKGBUILD" && note "s" $"${colorW}$i${reset} PKGBUILD viewed" || note "e" $"Could not open ${colorW}$i${reset} PKGBUILD"
  577.                fi
  578.            fi
  579.            # edit install script
  580.            if [[ ! $editinstall = false && -n "$installscript" ]]; then
  581.                if proceed "y" $"View $i .install script?"; then
  582.                    [[ -e "$builddir/$i/$installscript" ]] && $editor "$builddir/$i/$installscript" && note "s" $"${colorW}$i${reset} install script viewed" || note "e" $"Could not open ${colorW}$i${reset} install script"
  583.                fi
  584.            fi
  585.        else
  586.            [[ -e "$builddir/$i/PKGBUILD" ]] && $editor "$builddir/$i/PKGBUILD" && note "s" $"${colorW}$i${reset} PKGBUILD viewed" || note "e" $"Could not open ${colorW}$i${reset} PKGBUILD"
  587.            if [[ -n "$installscript" ]]; then
  588.                [[ -e "$builddir/$i/$installscript" ]] && $editor "$builddir/$i/$installscript" && note "s" $"${colorW}$i${reset} install script viewed" || note "e" $"Could not open ${colorW}$i${reset} install script"
  589.            fi
  590.        fi
  591.    done
  592. }
  593.  
  594. MakePkgs() {
  595.    # current orphan packages
  596.    oldorphanpkgs=($($pacmanbin -Qdtq | LC_COLLATE=C sort -u))
  597.  
  598.    # set lock
  599.    [[ -e "$tmpdir/build.lock" ]] && note "e" "build lock exists in $tmpdir" && exit 1
  600.    touch "$tmpdir/build.lock"
  601.  
  602.    # initialize sudo
  603.    if zenity --password | sudo -S -v; then
  604.        [[ $sudoloop = true ]] && zenitysudov &
  605.    fi
  606.  
  607.    # reverse deps order
  608.    deps=($(awk -F " " '{for (i=NF;i>=1;i--) print $i}' <<< ${deps[@]} | awk -F "\n" '{print}'))
  609.  
  610.    # check destination folder
  611.    [[ ! $installpkg ]] && [[ ! $PKGDEST ]] && [[ $clean = true ]] && note "e" $"${colorW}PKGDEST${reset} variable in /etc/makepkg.conf is unset or ${colorW}clean${reset} option is disabled"
  612.  
  613.    # install provider packages
  614.    if [[ -n "${providerpkgs[@]}" ]]; then
  615.        note "i" $"Installing ${colorW}${providerpkgs[@]}${reset} dependencies..."
  616.        yes `gettext pacman Y` sudo $pacmanbin -S ${providerpkgs[@]} --asdeps
  617.    fi
  618.  
  619.    # check package cache
  620.    for ((i=0; i<${#depsAname[@]}; i++)); do
  621.        unset cachedpkg
  622.        [[ $PKGDEST && ! $rebuild ]] && getcachedpkg "${depsAname[$i]}-${depsAver[$i]}" "$PKGDEST"
  623.        if [[ $cachedpkg ]]; then
  624.            if [[ $installpkg ]]; then
  625.                note "i" $"Installing ${colorW}${depsAname[$i]}${reset} cached package..."
  626.                yes `gettext pacman Y`  sudo  $pacmanbin -U $cachedpkg ${pacopts[@]}
  627.                [[ ! $upgrade ]] && ! [[ " ${pkgs[@]} " =~ " ${depsAname[$i]} " ]] && sudo  $pacmanbin -D ${depsAname[$i]} --asdeps ${pacopts[@]} &>/dev/null
  628.            else
  629.                note "i" $"Package ${colorW}${depsAname[$i]}${reset} already available in cache"
  630.            fi
  631.            deps=($(tr ' ' '\n' <<< ${deps[@]} | sed "s/^${depsAname[$i]}$//g"))
  632.        fi
  633.    done
  634.  
  635.    # build
  636.    for i in "${deps[@]}"; do
  637.        note "i" $"Building ${colorW}$i${reset} package..."
  638.        cd "$builddir/$i"
  639.  
  640.        # build devel if necessary only
  641.        makeopts=(${makeopts[@]/-e/})
  642.        if [[ -n "$(echo "$i" | grep -E "\-(cvs|svn|git|hg|bzr|darcs)$")" && ! $rebuild ]]; then
  643.            if [[ -n "$(grep -E '^pkgver[ ]*[(]+[)]+' "PKGBUILD")" ]]; then
  644.                makepkg -o ${makeopts[@]}
  645.                aurdevelpkgsAver=$(grep '^pkgver=' "PKGBUILD" | cut -d '=' -f 2- | tr -d "'\"")
  646.                aurdevelpkgsArel=$(grep '^pkgrel=' "PKGBUILD" | cut -d '=' -f 2- | tr -d "'\"")
  647.                aurdevelpkgsAepo=$(grep '^epoch=' "PKGBUILD" | cut -d '=' -f 2- | tr -d "'\"")
  648.                aurdevelpkgsQver=$(expac -Q '%v' "$i")
  649.                if [[ -n "$aurdevelpkgsAepo" ]]; then
  650.                    aurdevelpkgsAall="$aurdevelpkgsAepo:$aurdevelpkgsAver-$aurdevelpkgsArel"
  651.                else
  652.                    aurdevelpkgsAall="$aurdevelpkgsAver-$aurdevelpkgsArel"
  653.                fi
  654.                if [[ $(vercmp "$aurdevelpkgsQver" "$aurdevelpkgsAall") -eq 0 ]]; then
  655.                    note "w" "${colorW}$i${reset} is up-to-date -- skipping"
  656.                    continue
  657.                else
  658.                    makeopts+=('-e')
  659.                fi
  660.            fi
  661.        fi
  662.  
  663.        if [[ $installpkg ]]; then
  664.            # install
  665.            yes `gettext pacman Y` | makepkg -sfi ${makeopts[@]}
  666.        else
  667.            if [[ " ${aurdepspkgs[@]} " =~ " $i " ]]; then
  668.                # install AUR deps
  669.                note "i" $"Installing ${colorW}$i${reset} dependencies..."
  670.                yes `gettext pacman Y` | makepkg -sfi ${makeopts[@]}
  671.            else
  672.                # install then remove binary deps
  673.                yes `gettext pacman Y` | makepkg -sfr ${makeopts[@]}
  674.            fi
  675.        fi
  676.        # clean
  677.        CleanUp $i
  678.  
  679.        # set dep status
  680.        if [[ $installpkg ]]; then
  681.            [[ ! $upgrade ]] && ! [[ " ${pkgs[@]} " =~ " $i " ]] && sudo  $pacmanbin -D $i --asdeps ${pacopts[@]} &>/dev/null
  682.            [[ " ${pacopts[@]} " =~ " --asdeps " ]] && sudo  $pacmanbin -D $i --asdeps ${pacopts[@]} &>/dev/null
  683.            [[ " ${pacopts[@]} " =~ " --asexplicit " ]] && sudo  $pacmanbin -D $i --asexplicit ${pacopts[@]} &>/dev/null
  684.        else
  685.            sudo  $pacmanbin -D $i --asdeps ${pacopts[@]} &>/dev/null
  686.        fi
  687.    done
  688.  
  689.    # remove AUR deps
  690.    if [[ ! $installpkg && -n "${aurdepspkgs[@]}" ]]; then
  691.        note "i" $"Removing installed AUR dependencies..."
  692.        zenity --password | sudo -S $pacmanbin -Rsn ${aurdepspkgs[@]} --noconfirm
  693.    fi
  694.  
  695.    # remove locks
  696.    [[ -e "$tmpdir/sudov.lock" ]] && rm "$tmpdir/sudov.lock"
  697.    rm "$tmpdir/build.lock"
  698.  
  699.    # new orphan packages check
  700.    orphanpkgs=($($pacmanbin -Qdtq | LC_COLLATE=C sort -u))
  701.    neworphanpkgs=($(LC_COLLATE=C comm -23 <(echo "${orphanpkgs[@]}" | tr ' ' '\n') <(echo "${oldorphanpkgs[@]}" | tr ' ' '\n')))
  702.    for i in "${neworphanpkgs[@]}"; do
  703.        note "w" $"${colorW}$i${reset} is a ${colorY}new orphan${reset} package"
  704.    done
  705. }
  706.  
  707. CleanUp() {
  708.    [[ ! $clean = true ]] && return
  709.    if [[ -n "$@" ]]; then
  710.        cd "$builddir"
  711.        for i in "$@"; do
  712.            if [[ ! $cleandevel = true && -n "$(echo "$i" | grep -E "\-(cvs|svn|git|hg|bzr|darcs)$")" && $count -lt 2 ]]; then
  713.                note "w" $"${colorW}$i${reset} cleaning skipped"
  714.                continue
  715.            else
  716.                # hack for vcs protected files
  717.                chmod -R 755 $i &>/dev/null
  718.                rm -r $i &>/dev/null && note "s" $"${colorW}$i${reset} cleaned" || note "w" $"Could not clean ${colorW}$i${reset}"
  719.            fi
  720.        done
  721.    else
  722.        # hack for vcs protected files
  723.        chmod -R 755 $builddir/* &>/dev/null
  724.        rm -r $builddir/* &>/dev/null && note "s" $"Build directory cleaned" || note "w" $"Build directory already cleaned"
  725.    fi
  726. }
  727.  
  728. SearchInfoAur() {
  729.    cower ${coweropts[@]} $@
  730. }
  731.  
  732. CheckRepo() {
  733.    getignoredpkgs
  734.    repopkgsQood=($($pacmanbin -Quq $@))
  735.    if [[ -n "${repopkgsQood[@]}" ]]; then
  736.        [[ $quiet ]] && echo "${repopkgsQood[@]}" | tr ' ' '\n' && return
  737.        repopkgsQver=($(expac -Q '%v' "${repopkgsQood[@]}"))
  738.        repopkgsSver=($(expac -S -1 '%v' "${repopkgsQood[@]}"))
  739.        repopkgsSrepo=($(expac -S -1 '%r' "${repopkgsQood[@]}"))
  740.        for ((i=0; i<${#repopkgsQood[@]}; i++)); do
  741.            repopkgsQgrp[$i]=$(expac -Q -l " " '(%G)' "${repopkgsQood[$i]}" | sed 's/()//g')
  742.            [[ " ${ignoredpkgs[@]} " =~ " ${repopkgsQood[$i]} " ]] && repopkgsQignore[$i]=$"[ ignored ]"
  743.        done
  744.        lname=$(getlength "${repopkgsQood[@]}")
  745.        lQver=$(getlength "${repopkgsQver[@]}")
  746.        lSver=$(getlength "${repopkgsSver[@]}")
  747.        lrepo=$(getlength "${repopkgsSrepo[@]}")
  748.        lgrp=$(getlength "${repopkgsQgrp[@]}")
  749.        for ((i=0; i<${#repopkgsQood[@]}; i++)); do
  750.            printf "${colorB}::${reset} ${colorM}%-${lrepo}s${reset}  ${colorW}%-${lname}s${reset}  ${colorR}%-${lQver}s${reset}  ->  ${colorG}%-${lSver}s${reset}  ${colorB}%-${lgrp}s${reset}  ${colorY}%s${reset}\n" "${repopkgsSrepo[$i]}" "${repopkgsQood[$i]}" "${repopkgsQver[$i]}" "${repopkgsSver[$i]}" "${repopkgsQgrp[$i]}" "${repopkgsQignore[$i]}"
  751.        done
  752.    fi
  753. }
  754.  
  755. CheckAur() {
  756.    getignoredpkgs
  757.    aurpkgsQood=($(cower ${coweropts[@]} $@ | sed -r "s:\x1B\[[0-9;]*[mK]::g"))
  758.    if [[ -n "${aurpkgsQood[@]}" ]]; then
  759.        [[ $quiet ]] && echo "${aurpkgsQood[@]}" | tr ' ' '\n' && return
  760.        downloadjson ${aurpkgsQood[@]}
  761.        aurpkgsAname=($(getjsonvar "Name"))    # return sorted results
  762.        aurpkgsAver=($(getjsonvar "Version"))
  763.        aurpkgsQver=($(expac -Q '%v' "${aurpkgsAname[@]}"))
  764.        for ((i=0; i<${#aurpkgsQood[@]}; i++)); do
  765.            [[ " ${ignoredpkgs[@]} " =~ " ${aurpkgsQood[$i]} " ]] && aurpkgsQignore[$i]=$"[ ignored ]"
  766.        done
  767.        [[ ! $lname ]] && lname=$(getlength "${aurpkgsAname[@]}")
  768.        [[ ! $lQver ]] && lQver=$(getlength "${aurpkgsQver[@]}")
  769.        [[ ! $lSver ]] && lSver=$(getlength "${aurpkgSver[@]}")
  770.        [[ ! $lrepo ]] && lrepo=3
  771.        for ((i=0; i<${#aurpkgsAname[@]}; i++)); do
  772.            printf "${colorB}::${reset} ${colorM}%-${lrepo}s${reset}  ${colorW}%-${lname}s${reset}  ${colorR}%-${lQver}s${reset}  ->  ${colorG}%-${lSver}s${reset}  ${colorB}%-${lgrp}s${reset}  ${colorY}%s${reset}\n" "aur" "${aurpkgsAname[$i]}" "${aurpkgsQver[$i]}" "${aurpkgsAver[$i]}" " " "${aurpkgsQignore[$i]}"
  773.        done
  774.    fi
  775. }
  776.  
  777. CleanCache() {
  778.    if [[ $PKGDEST && $PKGDEST != '/var/cache/pacman/pkg/' ]]; then
  779.        [[ ! $aur ]] && echo
  780.        printf "%s %s\n" $"AUR cache directory:" "$PKGDEST"
  781.        if [[ $count -eq 1 ]]; then
  782.            printf "${colorW}%s${reset}\n %s\n" $"Packages to keep:" $"All locally installed packages"
  783.            if ! proceed "y" $"Do you want to remove all other packages from AUR cache?"; then
  784.                exit
  785.            fi
  786.            printf "%s\n" $"removing old packages from cache..."
  787.            paccache -ru -k0 -c $PKGDEST &>/dev/null
  788.        else
  789.            if ! proceed "n" $"Do you want to remove ALL files from AUR cache?"; then
  790.                printf "%s\n" $"removing all files from AUR cache..."
  791.                paccache -r -k0 -c $PKGDEST &>/dev/null
  792.            fi
  793.        fi
  794.    fi
  795. }
  796.  
  797. getversionedpkgs() {
  798.    downloadjson ${deps[@]}
  799.    depsAname=($(getjsonvar "Name"))    # return sorted results
  800.    depsAver=($(getjsonvar "Version"))
  801.    depsAood=($(getjsonvar "OutOfDate"))
  802.    depsArepo=("${depsAname[@]/#/aur/}" )
  803.    for ((i=0; i<${#depsAname[@]}; i++)); do
  804.        depsQver[$i]=$(expac -Q '%v' "${depsAname[$i]}")
  805.        [[ -z "${depsQver[$i]}" ]] && depsQver[$i]="#"  # avoid empty elements shift
  806.         [[ -n "$(echo "${depsAname[$i]}" | grep -E "\-(cvs|svn|git|hg|bzr|darcs)$")" ]] && depsAver[$i]=$"latest"
  807.    done
  808.    if [[ -n "${repodepspkgs[@]}" ]]; then
  809.        repodepspkgs=($(expac -S -1 '%n' "${repodepspkgs[@]}" | LC_COLLATE=C sort -u))
  810.        repodepsSver=($(expac -S -1 '%v' "${repodepspkgs[@]}"))
  811.        repodepsQver=($(expac -Q '%v' "${repodepspkgs[@]}"))
  812.        repodepsSrepo=($(expac -S -1 '%r/%n' "${repodepspkgs[@]}"))
  813.    fi
  814. }
  815.  
  816. getignoredgrps() {
  817.    ignoredgrps+=($(grep '^IgnoreGroup' '/etc/pacman.conf' | cut -d '=' -f 2- | tr -d "'\""))
  818. }
  819.  
  820. getignoredpkgs() {
  821.    ignoredpkgs+=($(grep '^IgnorePkg' '/etc/pacman.conf' | cut -d '=' -f 2- | tr -d "'\""))
  822.    [[ -e "$HOME/.config/cower/config" ]] && ignoredpkgs+=($(grep '^IgnorePkg' "$HOME/.config/cower/config" | cut -d '=' -f 2- | tr -d "'\""))
  823.    ignoredpkgs=(${ignoredpkgs[@]//,/ })
  824. }
  825.  
  826. getinstallscript() {
  827.    [[ ! -d "$builddir/$1" ]] && return
  828.    unset installscriptpath installscript
  829.    installscriptpath=$(find "$builddir/$1/" -maxdepth 1 -name "*.install")
  830.    [[ $installscriptpath ]] && installscript=$(basename $installscriptpath)
  831. }
  832.  
  833. getcachedpkg() {
  834.    cachedpkg="$2/$1-${CARCH}${PKGEXT}"
  835.    [[ ! -f "$cachedpkg" ]] && cachedpkg="$2/$1-any${PKGEXT}"
  836.    [[ ! -f "$cachedpkg" ]] && unset cachedpkg
  837. }
  838.  
  839. downloadjson() {
  840.    urlencodedpkgs=($(sed 's/+/%2b/g' <<< $@ | sed 's/@/%40/g')) # pkgname consists of alphanum@._+-
  841.    urlargs="$(printf "&arg[]=%s" "${urlencodedpkgs[@]}")"
  842.    curl -sfg --compressed -C 0 "https://aur.archlinux.org/rpc.php?type=multiinfo$urlargs" -o "$tmpdir/raw.json" || note "e" $"Could not connect to the AUR"
  843. }
  844.  
  845. getjsonvar() {
  846.    json_reformat < "$tmpdir/raw.json" | tr -d "\" " | grep -Po "$1:.*" | sed -r "s/$1:/$1#/g" | tr -d ',' | awk -F "#" '{print $2}'
  847. }
  848.  
  849. checkQrequires() {
  850.     Qrequires=$(expac -Q '%n %D' | grep -E " $@[\+]*[^a-zA-Z0-9_@\.\+-]+" | awk -F " " '{print $1}' | tr '\n' ' ')
  851.     if [[ -n "${Qrequires[@]}" ]]; then
  852.         note "f" $"failed to prepare transaction (could not satisfy dependencies)"
  853.         note "e" $"${Qrequires[@]}: requires $@"
  854.     fi
  855. }
  856.  
  857. proceed() {
  858.     Y="`gettext pacman Y`"; y="$(echo $Y | tr '[:upper:]' '[:lower:]')";
  859.     N="`gettext pacman N`"; n="$(echo $N | tr '[:upper:]' '[:lower:]')"
  860.     case "$1" in
  861.         y)  printf "${colorB}%s${reset} ${colorW}%s${reset}" "::" $"$2 [Y/n] "
  862.             read -n 1 answer
  863.             echo
  864.             case $answer in
  865.                 $Y|$y|'') return 0;;
  866.                 *) return 1;;
  867.             esac;;
  868.         n)  printf "${colorB}%s${reset} ${colorW}%s${reset}" "::" $"$2 [y/N] "
  869.             read -n 1 answer
  870.             echo
  871.             case $answer in
  872.                 $N|$n|'') return 0;;
  873.                 *) return 1;;
  874.             esac;;
  875.     esac
  876. }
  877.  
  878. note() {
  879.     case "$1" in
  880.         i) echo -e "${colorB}::${reset} $2";;   # info
  881.         s) echo -e "${colorG}::${reset} $2";;   # success
  882.         w) echo -e "${colorY}::${reset} $2";;   # warn
  883.         f) echo -e "${colorR}::${reset} $2";;   # fail
  884.         e) echo -e "${colorR}::${reset} $2";    # error
  885.            exit 1;;
  886.     esac
  887. }
  888.  
  889. getlength() {
  890.     local length=0
  891.     for i in "$@"; do
  892.         x=${#i}
  893.         [[ $x -gt $length ]] && length=$x
  894.     done
  895.     echo $length
  896. }
  897.  
  898. nothingtodo() {
  899.     [[ -z "$@" ]] && printf "%s\n" $" there is nothing to do" && exit || return 0
  900. }
  901.  
  902. sudov() {
  903.     touch "$tmpdir/sudov.lock"
  904.     while [[ -e "$tmpdir/sudov.lock" ]]; do
  905.         sudo -n -v
  906.         sleep 2
  907.     done
  908. }
  909.  
  910. trap ctrlc INT
  911. ctrlc() {
  912.     echo
  913.     [[ -e "$tmpdir/sudov.lock" ]] && rm "$tmpdir/sudov.lock"
  914.     [[ -e "$tmpdir/build.lock" ]] && rm "$tmpdir/build.lock"
  915.     [[ $operation = sync ]] && CleanUp $(echo "${pkgs[@]} ${deps[@]}" | tr ' ' '\n' | LC_COLLATE=C sort -u)
  916.     exit
  917. }
  918.  
  919. usage() {
  920.     printf "%s\n" $"usage:  pacaur <operation> [options] [package(s)]"
  921.     printf "%s\n" $"operations:"
  922.     printf "%s\n" $" pacman extension"
  923.     printf "%s\n" $"   -S, -Q           extend pacman operations to the AUR"
  924.     printf "%s\n" $" AUR only"
  925.     printf "%s\n" $"   -s, --search     search AUR repository for matching strings"
  926.     printf "%s\n" $"   -i, --info       view package information -- pass twice for details"
  927.     printf "%s\n" $"   -d, --download   download target(s) -- pass twice to download AUR dependencies"
  928.     printf "%s\n" $"   -m, --makepkg    download and make target(s)"
  929.     printf "%s\n" $"   -y, --sync       download, make and install target(s)"
  930.     printf "%s\n" $"   -k, --check      check for AUR update(s)"
  931.     printf "%s\n" $"   -u, --update     update AUR package(s)"
  932.     printf "%s\n" $" general"
  933.     printf "%s\n" $"   -v, --version    display version information"
  934.     printf "%s\n" $"   -h, --help       display help information"
  935.     printf "%s\n" $"   --fixbackend     quickly rebuild backend"
  936.     echo
  937.     printf "%s\n" $"options:"
  938.     printf "%s\n" $" pacman extension - can be used with the -S, -Ss, -Si, -Sii, -Sw, -Su, -Qu, -Sc, -Scc operations"
  939.     printf "%s\n" $"   -a, --aur        only search, install or clean packages from the AUR"
  940.     printf "%s\n" $"   -r, --repo       only search, install or clean packages from the repositories"
  941.     printf "%s\n" $" general"
  942.     printf "%s\n" $"   -e, --edit       edit target(s) PKGBUILD and view install script"
  943.     printf "%s\n" $"   -c, --clean      clean target(s) build files -- can be combined with the -m, -y, -u operations"
  944.     printf "%s\n" $"   -q, --quiet      show less information for query and search"
  945.     printf "%s\n" $"   --devel          consider AUR development packages upgrade"
  946.     printf "%s\n" $"   --ignore         ignore a package upgrade (can be used more than once)"
  947.     printf "%s\n" $"   --noconfirm      do not prompt for any confirmation"
  948.     printf "%s\n" $"   --noedit         do not prompt to edit files"
  949.     printf "%s\n" $"   --rebuild        always rebuild package(s)"
  950.     echo
  951. }
  952.  
  953. version() {
  954.     echo "pacaur $version"
  955. }
  956.  
  957. fixbackend() {
  958.     note "i" $"Rebuilding ${colorW}cower${reset} backend..."
  959.     [[ -n "$(expac -Q '%n' "cower")" ]] && cowerbin=cower || cowerbin=cower-git # cower-git compatibility
  960.     downloadjson $cowerbin
  961.     cowerbinurl=($(getjsonvar "URLPath"))
  962.     curl -sf --compressed -C 0 "https://aur.archlinux.org${cowerbinurl%/*}/PKGBUILD" -o "$tmpdir/$cowerbin.PKGBUILD" || note "e" $"Could not connect to the AUR"
  963.     mkdir -p "$builddir/$cowerbin" && cd "$builddir/$cowerbin"
  964.     makepkg -p $tmpdir/$cowerbin.PKGBUILD -sfic ${makeopts[@]} --noconfirm
  965.     CleanUp $cowerbin
  966. }
  967.  
  968. #
  969. # Main
  970. #
  971.  
  972. # get short arguments
  973. args=("$@")
  974. for i in "${args[@]}"; do
  975.     [[ "$i" =~ ^-[a-zA-Z0-9] ]] && opts+=("$i")
  976. done
  977.  
  978. # get options
  979. count=0
  980. while [[ -n "${!OPTIND}" ]]; do
  981.     while getopts "sidmykufecqrahvVDQRSTUbglnoptw-:" OPT; do
  982.         pacmanarg+=("-$OPT");
  983.         case "$OPT" in
  984.             -)
  985.                 case "$OPTARG" in
  986.                     search) operation=search; coweropts+=("-s"); aur='1';;
  987.                     info) operation=info; coweropts+=("-i"); aur='1';;
  988.                     download) operation=download; ((count++));;
  989.                     makepkg) operation=sync; coweropts+=("-f"); aur='1';;
  990.                     sync) operation=sync; installpkg=true; coweropts+=("-f"); aur='1';;
  991.                     check) operation=upgrades; coweropts+=("-uq"); aur='1';;
  992.                     update) operation=sync; upgrade=true; installpkg=true; coweropts+=("-f"); selective=true; aur='1';;
  993.                     force) coweropts+=("-f"); pacopts+=("--force");;
  994.                     edit) edit=true; [[ ! $pacQ && ! $operation ]] && operation=editpkg;;
  995.                     clean) operation=cleanpkg; clean=true; ((count++));;
  996.                     quiet) quiet=true; pacopts+=("--quiet"); coweropts+=("-q");;
  997.                     repo) repo='1';;
  998.                     aur) aur='1';;
  999.                     devel) devel=true;;
  1000.                     asroot) makeopts+=("--asroot");;
  1001.                     ignore) ignoredpkgs+=("${!OPTIND}"); ignoreopts+=("--ignore ${!OPTIND}"); shift;;
  1002.                     color) color=${!OPTIND}; pacopts+=("--color ${!OPTIND}") && coweropts+=("--color=${!OPTIND}"); shift;;
  1003.                     ignore-ood) coweropts+=("--ignore-ood");;
  1004.                     no-ignore-ood) coweropts+=("--no-ignore-ood");;
  1005.                     votes) coweropts+=("--rsort=votes");;
  1006.                     asdep|asdeps) pacopts+=("--asdeps"); makeopts+=("--asdeps");;
  1007.                     needed) needed=true; pacopts+=("--needed"); makeopts+=("--needed");;
  1008.                     noconfirm) noconfirm=true; pacopts+=("--noconfirm");;
  1009.                     noedit) noedit=true;;
  1010.                     rebuild) rebuild=true;;
  1011.                     insecure) secure=false;;
  1012.                     fixbackend|allanbrokeit) fixbackend; exit;;
  1013.                     root) root=true;;
  1014.                     version) version; exit;;
  1015.                     help) usage; exit;;
  1016.                     *) pacopts+=("--$OPTARG");;
  1017.                 esac;;
  1018.             s)  [[ $pacS ]] && operation=search && coweropts+=("-s");
  1019.                 [[ $pac || $pacQ || $pacS ]] && continue || operation=search; coweropts+=("-s"); aur='1';;
  1020.             i)  [[ $pacS ]] && operation=info && coweropts+=("-i");
  1021.                 [[ $pac || $pacQ || $pacS ]] && continue || operation=info; coweropts+=("-i"); aur='1';;
  1022.             d)  [[ $pac || $pacQ || $pacS ]] && continue || operation=download; ((count++));;
  1023.             m)  [[ $pac || $pacQ || $pacS ]] && continue || operation=sync; coweropts+=("-f"); aur='1';;
  1024.             y)  [[ $pacS ]] && operation=sync && refresh=true;
  1025.                 [[ $pac || $pacQ || $pacS ]] && continue || operation=sync; installpkg=true; coweropts+=("-f"); aur='1';;
  1026.             k)  [[ $pac || $pacQ || $pacS ]] && continue || operation=upgrades; coweropts+=("-uq"); aur='1';;
  1027.             u)  [[ $pacQ ]] && operation=upgrades && coweropts+=("-uq");
  1028.                 [[ $pacS ]] && operation=sync && upgrade=true && coweropts+=("-f");
  1029.                 [[ $pac || $pacQ || $pacS ]] && continue || operation=sync; upgrade=true; installpkg=true; coweropts+=("-f"); selective=true; aur='1';;
  1030.             f)  [[ $pac || $pacQ || $pacS ]] && continue || coweropts+=("-f");;
  1031.             e)  [[ $pacQ ]] && pacopts+=("--explicit") && continue || edit=true;
  1032.                 [[ ! $operation ]] && operation=editpkg;;
  1033.             c)  [[ $pacS ]] && operation=cleancache && ((count++));
  1034.                 [[ $pac || $pacQ || $pacS ]] && continue || [[ ! $operation ]] && operation=cleanpkg; clean=true && ((count++));;
  1035.             q)  quiet=true; pacopts+=("--quiet"); coweropts+=("-q");;
  1036.             r)  repo='1';;
  1037.             a)  aur='1';;
  1038.             Q)  pacQ='1';;
  1039.             S)  pacS='1'; operation=sync; coweropts+=("-f");
  1040.                 [[ "${opts[@]}" =~ "w" ]] && continue || installpkg=true;
  1041.                 [[ "${opts[@]}" =~ "g" || "${opts[@]}" =~ "l" || "${opts[@]}" =~ "p" ]] && unset operation;;
  1042.             [A-Z]) pac='1';;
  1043.             h)  [[ "${opts[@]}" =~ ^-[A-Z] ]] && unset operation && continue || usage; exit;;
  1044.             v)  [[ "${opts[@]}" =~ ^-[A-Z] ]] && unset operation && continue || version; exit;;
  1045.             *)  continue;;
  1046.         esac
  1047.     done
  1048.     # packages
  1049.     [[ -z "${!OPTIND}" ]] && break || pkgs+=("${!OPTIND}")
  1050.     shift $OPTIND
  1051.     OPTIND=1
  1052. done
  1053.  
  1054. pacmanarg=(${pacmanarg[@]/--/})
  1055. pacmanarg=(${pacmanarg[@]/-r/})
  1056. [[ $pacS ]] && pacmanarg=(${pacmanarg[@]/-e/})
  1057.  
  1058. # color
  1059. if [[ -n "$(grep '^Color' '/etc/pacman.conf')" && $color != 'never' ]]; then
  1060.     [[ $color = 'always' ]] && coweropts+=("--color=always") || coweropts+=("--color=auto")
  1061.     reset="\e[0m"
  1062.     colorR="\e[1;31m"
  1063.     colorG="\e[1;32m"
  1064.     colorY="\e[1;33m"
  1065.     colorB="\e[1;34m"
  1066.     colorM="\e[1;35m"
  1067.     colorC="\e[1;36m"
  1068.     colorW="\e[1;39m"
  1069. elif [[ -z "$(grep '^Color' '/etc/pacman.conf')" && ($color = 'always' || $color = 'auto') ]]; then
  1070.     pacopts+=("--color $color") && coweropts+=("--color=$color")
  1071.     reset="\e[0m"
  1072.     colorR="\e[1;31m"
  1073.     colorG="\e[1;32m"
  1074.     colorY="\e[1;33m"
  1075.     colorB="\e[1;34m"
  1076.     colorM="\e[1;35m"
  1077.     colorC="\e[1;36m"
  1078.     colorW="\e[1;39m"
  1079. else
  1080.     [[ $color != 'always' && $color != 'auto' ]] && makeopts+=("--nocolor")
  1081. fi
  1082.  
  1083. # sanity check
  1084. [[ ! $editor ]] && [[ ! -f /usr/bin/vi ]] && note "e" $"${colorW}editor${reset} variable unset"
  1085. [[ ! -w "$builddir" ]] && note "e" $"${colorW}$builddir${reset} does not have write permission."
  1086. [[ -z "${pkgs[@]}" ]] && [[ $operation = download || $operation = sync || $operation = editpkg || ($operation = cleanpkg && $count -eq 1) ]] && [[ ! $refresh && ! $upgrade ]] && note "e" $"no targets specified (use -h for help)"
  1087. [[ $repo && $aur ]] && note "e" $"target not found"
  1088. [[ $root ]] && note "e" $"alternative installation root option not supported"
  1089.  
  1090. # operations
  1091. case $operation in
  1092.     download)
  1093.         # download (-d) handling
  1094.         ClassifyPkgs ${pkgs[@]}
  1095.         DownloadAur ${repopkgs[@]}
  1096.         DownloadPkgs
  1097.         EditPkgs ${deps[@]}
  1098.         exit;;
  1099.     cleanpkg)
  1100.         # clean (-c) handling
  1101.         CleanUp ${pkgs[@]}
  1102.         exit;;
  1103.     editpkg)
  1104.         # edit (-e) handling
  1105.         EditPkgs ${pkgs[@]}
  1106.         exit;;
  1107.     search)
  1108.         # search (-Ss, -s) handling
  1109.         [[ ! $aur ]] && $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${pkgs[@]}
  1110.         [[ ! $repo ]] && [[ $fallback = true || $aur ]] && SearchInfoAur ${pkgs[@]}
  1111.         exit;;
  1112.     info)
  1113.         # info (-Si, -i) handling
  1114.         [[ -z "${pkgs[@]}" ]] && $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} || ClassifyPkgs ${pkgs[@]}
  1115.         [[ -n "${repopkgs[@]}" ]] && $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${repopkgs[@]}
  1116.         if [[ -n "${aurpkgs[@]}" ]]; then
  1117.             [[ $fallback = true && ! $aur ]] && note "w" $"Package(s) ${colorW}${aurpkgs[*]}${reset} not found in repositories, trying ${colorM}AUR${reset}..."
  1118.             SearchInfoAur ${aurpkgs[@]}
  1119.         fi
  1120.         exit;;
  1121.     sync)
  1122.         # sync (-S, -y), downloadonly (-Sw, -m), refresh (-Sy), sysupgrade (-Su, -u) handling
  1123.         if [[ ! $upgrade ]]; then
  1124.             [[ -z "${pkgs[@]}" ]] && zenity --password | sudo -S $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} || ClassifyPkgs ${pkgs[@]}
  1125.             [[ -n "${repopkgs[@]}" ]] && zenity --password | sudo -S $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${repopkgs[@]}
  1126.             if [[ -n "${aurpkgs[@]}" ]]; then
  1127.                 [[ $refresh ]] && [[ -z "${repopkgs[@]}" ]] && zenity --password | sudo -S $pacmanbin -Sy ${pacopts[@]} ${ignoreopts[@]}
  1128.                 [[ $fallback = true && ! $aur ]] && note "w" $"Package(s) ${colorW}${aurpkgs[*]}${reset} not found in repositories, trying ${colorM}AUR${reset}..."
  1129.                 Core ${aurpkgs[@]}
  1130.             fi
  1131.         else
  1132.             [[ ! $selective ]] && ClassifyPkgs ${pkgs[@]} && unset pkgs # selective upgrade switch
  1133.             [[ ! $aur ]] && zenity --password | sudo -S $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${repopkgs[@]}
  1134.             [[ -n "${aurpkgs[@]}" ]] && [[ $fallback = true && ! $aur ]] && note "w" $"Package(s) ${colorW}${aurpkgs[*]}${reset} not found in repositories, trying ${colorM}AUR${reset}..."
  1135.             [[ ! $repo ]] && [[ $fallback = true || $aur ]] && Core ${aurpkgs[@]}
  1136.         fi
  1137.         exit;;
  1138.     upgrades)
  1139.         # upgrades (-Qu, -k) handling
  1140.         [[ ! $aur ]] && CheckRepo ${pkgs[@]}
  1141.         [[ ! $repo ]] && [[ $fallback = true || $aur ]] && CheckAur ${pkgs[@]}
  1142.         exit;;
  1143.     cleancache)
  1144.         # clean (-Sc) handling
  1145.         [[ ! $aur ]] && sudo  $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${repopkgs[@]}
  1146.         [[ ! $repo ]] && [[ $fallback = true || $aur ]] && CleanCache ${pkgs[@]}
  1147.         exit;;
  1148.     *)  # others operations handling
  1149.         if [[ -z "${pkgs[@]}" || -n "$(grep -e "-[QTglp]" <<< ${pacmanarg[@]})" ]]; then
  1150.             $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${pkgs[@]}
  1151.         else
  1152.             sudo  $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${pkgs[@]}
  1153.         fi
  1154.         exit;;
  1155. esac
  1156. # vim:set ts=4 sw=2 et:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement