OSDN Git Service

[update] : Added --recursive
[alterlinux/wfa.git] / wfa
diff --git a/wfa b/wfa
index 5427ad3..13fff5f 100755 (executable)
--- a/wfa
+++ b/wfa
@@ -65,10 +65,14 @@ declare -A ja_JP=(
     ["Please install with %s"]="%s でインストールしてください"
     ["Voted for %s"]="%s に投票しました"
     ["Unvoted for %s"]="%s の投票を解除しました"
-
+    ["Help for this operation is not implemented"]="このオペレーションのヘルプは実装されていません"
     ["(Orphaned)"]="(メンテナ不在)"
     ["[Installed]"]="[インストール済み]"
     ["This is a feature that has not been implemented yet"]="まだ実装されていない機能です"
+    ["Operation: %s"]="オペレーション: %s"
+    ["Raw popularity: %s"]="人気度の正確な値: %s"
+    ["This program is an alpha version that is not yet stable\nIf you find a bug, please share it on GitHub\nhttps://github.com/hayao0819/wfa/issues"]="このプログラムはまだ安定しないアルファ版です\nもしバグを見つけたらGitHub上で共有してください\nhttps://github.com/hayao0819/wfa/issues"
+    ["Please make a contract with me and become a Puella Magi !"]="僕と契約して魔法少女になってよ! "
 )
 
 
@@ -85,6 +89,7 @@ declare -A C=()
 wfa_version="0.1"
 wfa_name="WFA"
 wfa_command="wfa"
+wfa_path="$(dirname "$(realpath "${0}")")/$(basename "${0}")"
 
 #-- options (int) --#
 option_y_count=0
@@ -153,6 +158,22 @@ curl_args=""
 # ここからメッセージ関連の関数定義
 
 
+start_msg_debug() {
+    if [[ "${msgdebug}" = true ]]; then
+        set -xv
+    else
+        set +vx
+    fi
+}
+
+end_msg_debug() {
+    if [[ "${bash_debug}" = true ]]; then
+        set -xv
+    else
+        set +xv
+    fi
+}
+
 # メッセージ出力の制御
 # https://github.com/FascodeNet/alterlinux/blob/dev/tools/msg.sh の変数名にアンダーバーを追加し関数化
 msg() {
@@ -412,7 +433,6 @@ msg() {
 }
 
 # テキストの翻訳
-#set -xv
 translate() {
     local _msg_translate
     _msg_translate() {
@@ -421,9 +441,15 @@ translate() {
 
         _get_text() {
             set +eu
+            if [[ -z "${*}" ]]; then
+                return 1
+            fi
             local _translated_text="$(eval echo '$'{${_locale}[\"${*}\"]})"
             set -eu
             if [[ -z "${_translated_text}" ]]; then
+                if [[ ! "${_locale}" = "C" ]] && [[ ! "${_locale}" = "en_US" ]]; then
+                    echo "$(text -nc cyan "[WFA]") $(text -nc yellow "Warning") No translation data was found (${*})" 1>&2
+                fi
                 echo "${*}"
             else
                 echo "${_translated_text}"
@@ -448,9 +474,7 @@ translate() {
 # Show an INFO message
 # $1: message string
 msg_info() {
-    if [[ "${msgdebug}" = false ]]; then
-        set +xv
-    fi
+    start_msg_debug
     local _msg_opts="-a ${wfa_name}"
     if [[ "${1}" = "-n" ]]; then
         _msg_opts="${_msg_opts} -o -n"
@@ -459,17 +483,13 @@ msg_info() {
     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
     msg ${_msg_opts} info "$(translate "${@}")"
-    if [[ "${bash_debug}" = true ]]; then
-        set -xv
-    fi
+    end_msg_debug
 }
 
 # Show an Warning message
 # $1: message string
 msg_warn() {
-    if [[ "${msgdebug}" = false ]]; then
-        set +xv
-    fi
+    start_msg_debug
     local _msg_opts="-a ${wfa_name}"
     if [[ "${1}" = "-n" ]]; then
         _msg_opts="${_msg_opts} -o -n"
@@ -478,17 +498,13 @@ msg_warn() {
     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
     msg ${_msg_opts} warn "$(translate "${@}")"
-    if [[ "${bash_debug}" = true ]]; then
-        set -xv
-    fi
+    end_msg_debug
 }
 
 # Show an debug message
 # $1: message string
 msg_debug() {
-    if [[ "${msgdebug}" = false ]]; then
-        set +xv
-    fi
+    start_msg_debug
     if [[ "${debug}" = true ]]; then
         local _msg_opts="-a ${wfa_name}"
         if [[ "${1}" = "-n" ]]; then
@@ -499,18 +515,14 @@ msg_debug() {
         [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
         msg ${_msg_opts} debug "$(translate "${@}")"
     fi
-    if [[ "${bash_debug}" = true ]]; then
-        set -xv
-    fi
+    end_msg_debug
 }
 
 # Show an ERROR message then exit with status
 # $1: message string
 # $2: exit code number (with 0 does not exit)
 msg_error() {
-    if [[ "${msgdebug}" = false ]]; then
-        set +xv
-    fi
+    start_msg_debug
     local _msg_opts="-a ${wfa_name}"
     if [[ "${1}" = "-n" ]]; then
         _msg_opts="${_msg_opts} -o -n"
@@ -519,14 +531,15 @@ msg_error() {
     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
     msg ${_msg_opts} error "$(translate "${@}")"
-    if [[ "${bash_debug}" = true ]]; then
-        set -xv
-    fi
+    end_msg_debug
 }
 
+# 使い方
+# text [-b/-c color/-n/-f/-l/]
 text() {
-    local OPTIND OPTARG arg _textcolor _decotypes=() _message
-    while getopts "c:b" arg; do
+    start_msg_debug
+    local OPTIND OPTARG arg _textcolor _decotypes="" _message _notranslate=false
+    while getopts "c:bnfl" arg; do
         case ${arg} in
             c)
                 case "${OPTARG}" in
@@ -560,19 +573,32 @@ text() {
                 esac
                 ;;
             b)
-                _decotypes+=(1)
+                _decotypes="${_decotypes};1"
+                ;;
+            f)
+                _decotypes="${_decotypes};5"
+                ;;
+            l)
+                _decotypes="${_decotypes};4"
+                ;;
+            n)
+                _notranslate=true
                 ;;
         esac
     done
     shift $((OPTIND - 1))
 
     _message="${@}"
-    _message="$(translate "${@}")"
+    if [[ "${_notranslate}" = false ]]; then
+        _message="$(translate "${@}")"
+    fi
     if [[ "${nocolor}" = true ]]; then
         echo -ne "${@}"
     else
-        echo -ne "\e[$([[ -v _textcolor ]] && echo -n ";${_textcolor}"; [[ -v _decotypes ]] && echo -n ";${_decotypes}")m${_message}\e[m"
+        echo -ne "\e[$([[ -v _textcolor ]] && echo -n ";${_textcolor}"; [[ -v _decotypes ]] && echo -n "${_decotypes}")m${_message}\e[m"
     fi
+
+    end_msg_debug
 }
 
 ######################################################################################
@@ -640,6 +666,11 @@ usage (){
         echo
         echo "wfa specific options:"
         echo "    -c --clean            Remove unneeded dependencies"
+        echo
+        echo "This program is an alpha version that is not yet stable"
+        echo "If you find a bug, please share it on GitHub"
+        echo "https://github.com/hayao0819/wfa/issues"
+        echo
     }
 
     local _wfa_usage_sync
@@ -664,6 +695,23 @@ usage (){
 
     }
 
+    local _wfa_usage_remove
+    _wfa_usage_remove() {
+        echo "usage:  ${wfa_command} {-R --remove} [options] <package(s)>"
+        echo "options:"
+        echo "  -b, --dbpath <path>  set an alternate database location"
+        echo "  -d, --nodeps         skip dependency version checks (-dd to skip all checks)"
+        echo "  -u, --unneeded       remove unneeded packages"
+        echo "      --arch <arch>    set an alternate architecture"
+        echo "      --color <when>   colorize the output"
+        echo "      --config <path>  set an alternate configuration file"
+        echo "      --confirm        always ask for confirmation"
+        echo "      --debug          display debug messages"
+        echo "      --disable-download-timeout"
+        echo "                       use relaxed timeouts for download"
+        echo "      --noconfirm      do not ask for any confirmation"
+    }
+
     if [[ "${operation}" = "none" ]]; then
         _wfa_usage
     elif [[ "${_pacman_help}" = true ]]; then
@@ -671,7 +719,7 @@ usage (){
     elif [[ "$(type -t "_wfa_usage_${operation}" )" = "function" ]]; then
         _wfa_usage_${operation}
     else
-        msg_error "Undefined operation"
+        msg_error "Help for this operation is not implemented"
         exit 1
     fi
 }
@@ -698,6 +746,10 @@ run_pacman() {
     run_sudo "${pacman_command}" ${@}
 }
 
+wfa() {
+    "${wfa_path}" ${@}
+}
+
 # pacmanの引数を追加する
 # https://github.com/FascodeNet/aptpac/blob/master/aptpac のADD_OPTION関数を参考
 # Usage: add_args [pacman/makepkg/git/gpg/sudo/curl] <args1> <args2>...
@@ -810,6 +862,14 @@ EOF
     echo "${_srcinfo_json}" | jq -rc "${2}" | tr '\n' ' '
 }
 
+get_aur_json() {
+    local _package="${1}"
+    local _aur_json=$("${curl_command}" ${curl_args} -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name&arg=${_package}" | jq -r)
+    if (( "$(echo "${_aur_json}" | jq -r ".resultcount")" != 0 )); then
+        echo "${_aur_json}" | jq -r ".results[]"
+    fi
+}
+
 
 # AURからパッケージをビルドしてインストールします
 # 現在1つのパッケージしか指定できません
@@ -825,13 +885,12 @@ install_aur_package() {
 
     # AurJsonから値を取得
     msg_info "Searching in AUR ..."
-    local _aur_json=$("${curl_command}" ${curl_args} -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name&arg=${_package}" | jq -r)
-    if (( "$(echo "${_aur_json}" | jq -r ".resultcount")" == 0 )); then
+    local _aur_json="$(get_aur_json "${_package}")"
+    if [[ -z "${_aur_json}" ]]; then
         msg_error "Could not find all required packages: %s" "${_package}"
         exit 1
     fi
-
-    local _found_packages="$(echo "${_aur_json}" | jq -r --tab '.results[].Name')"
+    local _found_packages="$(echo "${_aur_json}" | jq -r --tab '.Name')"
     #msg_debug "Found package: $(echo ${_found_packages} | tr '\n' ' ')"
 
     if [[ -n "$(echo "${_found_packages}" | grep -x "${_package}" )" ]]; then
@@ -843,7 +902,7 @@ install_aur_package() {
 
     # PKGBUILDをダウンロード
     msg_info "Download PKGBUILD of %s" "${_package}"
-    _aur_json=$(echo "${_aur_json}" | jq -r ".results[] | select(.Name == \"${_package}\")" )
+    _aur_json=$(echo "${_aur_json}" | jq -r "select(.Name == \"${_package}\")" )
     local _aur_snapshot_url="${aururl%/}$(echo "${_aur_json}" | jq -r ".URLPath")"
     local _aur_version="$(echo "${_aur_json}" | jq -r ".Version")"
     msg_debug "Get PKGBUILD from %s" "${_aur_snapshot_url}"
@@ -978,15 +1037,11 @@ install_aur_package() {
 # AURのパッケージを検索
 search_aur_package() {
     local _package="${1}"
-    #msg_info "Searching in AUR ..."
-    local _aur_json=$("${curl_command}" ${curl_args} -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name-desc&arg=${_package}" | jq -r )
-    local _found_result_count="$(echo "${_aur_json}" | jq -r ".resultcount")"
-    if (( "${_found_result_count}" == 0 )); then
+    local _aur_json="$(get_aur_json "${_package}")"
+    if [[ -z "${_aur_json}" ]]; then
         msg_error "Could not find all required packages: %s" "${_package}"
         exit 1
     fi
-    _aur_json=$(echo "${_aur_json}" | jq -r ".results[]")
-
     local _found_pkgname=($(echo "${_aur_json}" | jq -r ".Name" ))
 
     if [[ "${quiet}" = true ]]; then
@@ -1009,7 +1064,7 @@ search_aur_package() {
 
             # 人気度の少数2位以下を四捨五入
             # 参考: http://www.rivhiro-weather.com/knowledge/?p=536
-            msg_debug "Row popularity: %s" "${__popularity}"
+            msg_debug "Raw popularity: %s" "${__popularity}"
             __popularity="$(printf "%g\n" "${__popularity}" | awk '{printf("%4.2f", $1)}')"
 
             # 孤児判定
@@ -1024,7 +1079,7 @@ search_aur_package() {
             fi
 
             __output_text+=(
-                "$(text -c blue -b "aur")/$(text -b "${_found_package}") $(text -c cyan "${__pkgver}") (+$(text -b "${__vote} ${__popularity}"))"
+                "$(text -n -c blue -b "aur")/$(text -n -b "${_found_package}") $(text -n -c cyan "${__pkgver}") (+$(text -n -b "${__vote} ${__popularity}"))"
             )
             
             if [[ "${__orphaned}" = true ]]; then
@@ -1056,20 +1111,29 @@ operation_remove() {
 
 # Usage: install_package <package1> <package2>...
 install_package() {
-    local _package
+    local _package _repo_packages=() _aur_packages=()
     for _package in ${@}; do
         if ! check_installed_package "${_package}"; then
             if ! check_aur_package "${_package}"; then
                 # 公式パッケージなのでpacmanでそのままインストール
-                run_pacman ${pacman_args} "${_package}"
+                _repo_packages+=("${_package}")
             else
                 # AUR上のパッケージの場合の処理
-                install_aur_package "${_package}"
-                #msg_error "Getting the AUR package has not been implemented yet.
-                #exit 1
+                _aur_packages+=("${_package}")
             fi
         fi
     done
+
+    if (( "${#_repo_packages[@]}" > 0 )); then
+        run_pacman --asdeps ${pacman_args} "${_repo_packages[@]}"
+    fi
+
+    if (( "${#_aur_packages[@]}" > 0 )); then
+        unset _package
+        for _package in ${_aur_packages[@]}; do
+            install_aur_package "${_package}"
+        done
+    fi
 }
 
 upgrade_aur_package() {
@@ -1128,13 +1192,12 @@ operation_vote() {
     for _package in ${specified_packages[@]}; do
 
         # 存在するパッケージか確認
-        _aur_json=$("${curl_command}" ${curl_args} -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name-desc&arg=${_package}" | jq -r)
-        _found_result_count="$(echo "${_aur_json}" | jq -r ".resultcount")"
-        _aur_json=$(echo "${_aur_json}" | jq -r ".results[] | select(.Name == \"${_package}\")")
-        if (( "${_found_result_count}" == 0 )) || [[ -z "${_aur_json}" ]]; then
-            msg_error "Package not found on AUR: %s" "${_package}"
+        local _aur_json="$(get_aur_json "${_package}")"
+        if [[ -z "${_aur_json}" ]]; then
+            msg_error "Could not find all required packages: %s" "${_package}"
             exit 1
         fi
+        _aur_json=$(echo "${_aur_json}" | jq -r "select(.Name == \"${_package}\")")
 
         # jsonから値を取り出して整形
         _pkgver="$(echo "${_aur_json}" | jq -r ".Version" )"
@@ -1151,7 +1214,7 @@ operation_vote() {
         fi
 
         # 投票後の値を取得
-        _aur_json=$("${curl_command}" ${curl_args} -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name-desc&arg=${_package}" | jq -r ".results[] | select(.Name == \"${_package}\")")
+        _aur_json=$(get_aur_json | jq -r "select(.Name == \"${_package}\")")
         _after_popularity="$(printf "%g\n" "$(echo "${_aur_json}" | jq -r ".Popularity" )" | awk '{printf("%4.2f", $1)}')"
         _after_vote="$(echo "${_aur_json}" | jq -r ".NumVotes" )"
 
@@ -1160,10 +1223,26 @@ operation_vote() {
     done
 }
 
+unavailable_in_this_operation() {
+    msg_error "This option is not available in the current operation"
+    exit 1
+}
+
+# オペレーションを実行します
+run_operation() {
+    local _operation="${1}"
+    msg_debug "Operation: %s" "${_operation}"
+    if [[ "${quiet}" = false ]]; then
+        msg_warn "This program is an alpha version that is not yet stable\nIf you find a bug, please share it on GitHub\nhttps://github.com/hayao0819/wfa/issues"
+    fi
+
+    operation_${_operation}
+}
+
 # Parse options
 ARGUMENT="${@}"
-_opt_short="AQRShVdb:aysuc"q
-_opt_long="query,remove,sync,help,version,debug,dbpath:,aururl,aur,noconfirm,config:,makepkg:,mflags:,pacman:,git:,gitflags:,gpg:,gpgflags:,makepkgconf:,nomakepkgconf,nodeps,refresh,bash-debug,msg-debug,sysupgrade,color:,nocolor,clean,quiet,arch:,confirm,disable-download-timeout,curl:,curlflags:"
+_opt_short="AQRShVdb:aysucqn"
+_opt_long="query,remove,sync,help,version,debug,dbpath:,aururl,aur,noconfirm,config:,makepkg:,mflags:,pacman:,git:,gitflags:,gpg:,gpgflags:,makepkgconf:,nomakepkgconf,nodeps,refresh,bash-debug,msg-debug,sysupgrade,color:,nocolor,clean,quiet,arch:,confirm,disable-download-timeout,curl:,curlflags:,unneeded,puella,wfa-debug,cascade"
 
 OPT=$(getopt -o ${_opt_short} -l ${_opt_long} -- ${ARGUMENT})
 [[ ${?} != 0 ]] && exit 1
@@ -1231,17 +1310,105 @@ while :; do
             option_y_count=$(( option_y_count + 1 ))
             shift 1
             ;;
-        -s | --search)
-            add_args pacman "--search"
-            sync_search=true
+        -s | --search | --recursive)
+            case "${1}" in
+                --search)
+                    if [[ "${operation}" = "sync" ]]; then
+                        add_args pacman "--search"
+                        sync_search=true
+                    else
+                        unavailable_in_this_operation
+                    fi
+                    ;;
+                --recursive)
+                    if [[ "${operation}" = "remove" ]]; then
+                        add_args pacman "--recursive"
+                    else
+                        unavailable_in_this_operation
+                    fi
+                    ;;
+                -s)
+                    case "${operation}" in
+                        "sync")
+                            add_args pacman "--search"
+                            sync_search=true
+                            ;;
+                        "remove")
+                            add_args pacman "--recursive"
+                            ;;
+                        *)
+                            unavailable_in_this_operation
+                            ;;
+                    esac
+                    ;;
+            esac
             shift 1
             ;;
-        -u | --sysupgrade)
-            sync_upgrade=true
+        -u | --sysupgrade | --unneeded)
+            case "${1}" in
+                --sysupgrade)
+                    if [[ "${operation}" = "sync" ]]; then
+                        sync_upgrade=true
+                    else
+                        unavailable_in_this_operation
+                    fi
+                    ;;
+                --unneeded)
+                    if [[ "${operation}" = "remove" ]]; then
+                        add_args pacman "--unneeded"
+                    else
+                        unavailable_in_this_operation
+                    fi
+                    ;;
+                -u)
+                    case "${operation}" in
+                        "sync")
+                            sync_upgrade=true
+                            ;;
+                        "remove")
+                            add_args pacman "--unneeded"
+                            ;;
+                        "none")
+                            :
+                            ;;
+                        *)
+                            unavailable_in_this_operation
+                            ;;
+                    esac
+                    ;;
+            esac
             shift 1
             ;;
-        -c | --clean)
-            sync_clean_count=$(( sync_clean_count + 1 ))
+        -c | --clean | --cascade)
+            case "${1}" in
+                --clean)
+                    if [[ "${operation}" = "sync" ]]; then
+                        sync_clean_count=$(( sync_clean_count + 1 ))
+                    else
+                        unavailable_in_this_operation
+                    fi
+                    ;;
+                --cascade)
+                    if [[ "${operation}" = "remove"  ]]; then
+                        add_args pacman "--cascade"
+                    else
+                        unavailable_in_this_operation
+                    fi
+                    ;;
+                -c)
+                    case "${operation}" in
+                        "sync")
+                            sync_clean_count=$(( sync_clean_count + 1 ))
+                            ;;
+                        "remove")
+                            add_args pacman "--cascade"
+                            ;;
+                        *)
+                            unavailable_in_this_operation
+                            ;;
+                    esac
+                    ;;
+            esac
             shift 1
             ;;
         -q | --quiet)
@@ -1249,6 +1416,10 @@ while :; do
             add_args pacman "--quiet"
             shift 1
             ;;
+        -n | --nosave)
+            add_args pacman "--nosave"
+            shift 1
+            ;;
         --arch)
             arch="${2}"
             add_args pacman "--arch ${2}"
@@ -1350,6 +1521,16 @@ while :; do
             add_args curl "${2}"
             shift 2
             ;;
+        --puella)
+            text -flb "Please make a contract with me and become a Puella Magi !"
+            echo
+            shift 1
+            exit 0
+            ;;
+        --wfa-debug)
+            debug=true
+            shift 1
+            ;;
         -h | --help)
             usage
             shift 1
@@ -1376,17 +1557,8 @@ fi
 
 # set_operationで設定された操作を実行
 case "${operation}" in
-    "version")
-        operation_version
-        ;;
-    "sync")
-        operation_sync
-        ;;
-    "remove")
-        operation_remove
-        ;;
-    "vote")
-        operation_vote
+    "version" | "sync" | "remove" | "vote")
+        run_operation "${operation}"
         ;;
     "none")
         exit 0