OSDN Git Service

[update] : Added JP translation
[alterlinux/wfa.git] / wfa
diff --git a/wfa b/wfa
old mode 100644 (file)
new mode 100755 (executable)
index 212c4ba..d944205
--- a/wfa
+++ b/wfa
@@ -1 +1,1093 @@
-#!/usr/bin/env bash
\ No newline at end of file
+#!/usr/bin/env bash
+
+set -eu
+
+
+######################################################################################
+# ここから翻訳データ
+
+declare -A ja_JP=(
+    ["Undefined operation"]="未定義のオペレーションです"
+    ["only one operation may be used at a time"]="一度に使用できるオペレーションは1つだけです"
+    ["Failed to set the argument of %s"]="%sの引数の設定に失敗しました"
+    ["Setting that command is not currently supported"]="そのコマンドの設定は現在サポートされていません"
+    ["Install dependent packages..."]="依存パッケージをインストールします..."
+    ["No package with an exact name match was found"]="完全に一致する名前のパッケージが見つかりませんでした"
+    ["Select a package %s with an exact name match"]="名前が完全に一致するパッケージ %s を選択します"
+    ["Download PKGBUILD of %s"]="%s のPKGBUILDをダウンロード"
+    ["Get PKGBUILD from %s"]="%sからPKGBUILDを取得します"
+    ["PKGBUILD has already been downloaded"]="PKGBUILDは既にダウンロードされています"
+    ["Do you want to overwrite and download? [n] :"]="上書きダウンロードしますか? [n] :"
+    ["Unpacking the tarball of PKGBUILD ..."]="PKGBUILDを展開しています ..."
+)
+######################################################################################
+# ここからデフォルト設定の定義
+
+#-- wfa configs --#
+wfa_version="0.1"
+wfa_name="WFA"
+wfa_command="wfa"
+
+#-- options (int) --#
+option_y_count=0
+
+#-- options (str) --#
+aururl="https://aur.archlinux.org/"
+operation="none"
+
+#-- options (bool) --#
+bash_debug=false
+debug=false
+force_aur=false
+msgdebug=false
+nocolor=false
+noconfirm=false
+nodeps=false
+nomakepkgconf=false
+sync_search=false
+
+#-- makepkg --#
+# 実行ファイル
+makepkg_command="/usr/bin/makepkg" 
+# 設定ファイル
+makepkg_config="/etc/makepkg.conf"
+# 引数
+makepkg_args=""
+
+#-- pacman --#
+# 実行ファイル
+pacman_command="/usr/bin/pacman"
+# 設定ファイル
+pacman_config="/etc/pacman.conf"
+# 引数
+pacman_args=""
+
+#-- git --#
+# 実行ファイル
+git_command="/usr/bin/git"
+# 引数
+git_args=""
+
+#-- gpg --#
+# 実行ファイル
+gpg_command="/usr/bin/gpg"
+# 引数
+gpg_args=""
+
+#-- sudo --#
+# 実行ファイル
+sudo_command="/usr/bin/sudo"
+# 引数
+sudo_args=""
+
+
+
+######################################################################################
+# ここからメッセージ関連の関数定義
+
+
+# メッセージ出力の制御
+# https://github.com/FascodeNet/alterlinux/blob/dev/tools/msg.sh の変数名にアンダーバーを追加し関数化
+msg() {
+    local OPTIND OPTARG arg
+
+    local _appname="msg.sh"
+    local _bash_debug=false
+    local _nocolor=false
+    local _echo_opts=""
+    local _message=""
+    local _msg_type="info"
+    local _msg_label=""
+    local _label_space="7"
+    local _adjust_chr=" "
+    local _customized_label=false
+    local _customized_label_color=false
+    local _nolabel=false
+    local _noappname=false
+    local _noadjust=false
+    local _output="stdout"
+
+    _help() {
+        echo "usage ${0} [option] [type] [message]"
+        echo
+        echo "Display a message with a colored app name and message type label"
+        echo
+        echo " General type:"
+        echo "    info                      General message"
+        echo "    warn                      Warning message"
+        echo "    error                     Error message"
+        echo "    debug                     Debug message"
+        echo
+        echo " General options:"
+        echo "    -a [name]                 Specify the app name"
+        echo "    -c [character]            Specify the character to adjust the label"
+        echo "    -l [label]                Specify the label."
+        echo "    -n | --nocolor            No output colored output"
+        echo "    -o [option]               Specify echo options"
+        echo "    -r [color]                Specify the color of label"
+        echo "    -s [number]               Specifies the label space."
+        echo "    -x | --bash-debug         Enables output bash debugging"
+        echo "    -h | --help               This help message"
+        echo
+        echo "         --nolabel            Do not output label"
+        echo "         --noappname          Do not output app name"
+        echo "         --noadjust           Do not adjust the width of the label"
+    }
+
+    while getopts "a:c:l:no:r:s:xh-:" arg; do
+        case ${arg} in
+                a) 
+                    _appname="${OPTARG}"
+                    ;;
+                c) 
+                    _adjust_chr="${OPTARG}"
+                    ;;
+                l) 
+                    _customized_label=true
+                    _msg_label="${OPTARG}"
+                    ;;
+                n)
+                    _nocolor=true
+                    ;;
+                o)
+                    _echo_opts="${OPTARG}"
+                    ;;
+                r)
+                    _customized_label_color=true
+                    case ${OPTARG} in
+                        "black")
+                            _labelcolor="30"
+                            ;;
+                        "red")
+                            _labelcolor="31"
+                            ;;
+                        "green")
+                            _labelcolor="32"
+                            ;;
+                        "yellow")
+                            _labelcolor="33"
+                            ;;
+                        "blue")
+                            _labelcolor="34"
+                            ;;
+                        "magenta")
+                            _labelcolor="35"
+                            ;;
+                        "cyan")
+                            _labelcolor="36"
+                            ;;
+                        "white")
+                            _labelcolor="37"
+                            ;;
+                        *)
+                            return 1
+                            ;;
+                    esac
+                    ;;
+                s)
+                    _label_space="${OPTARG}"
+                    ;;
+                x)
+                    _bash_debug=true
+                    set -xv
+                    ;;
+                h)
+                    _help
+                    shift 1
+                    exit 0
+                    ;;
+                -)
+                    case "${OPTARG}" in
+                        "nocolor")
+                            _nocolor=true
+                            ;;
+                        "bash-debug")
+                            _bash_debug=true
+                            set -xv
+                            ;;
+                        "help") 
+                            _help
+                            exit 0
+                            ;;
+                        "nolabel")
+                            _nolabel=true
+                            ;;
+                        "noappname")
+                            _noappname=true
+                            ;;
+                        "noadjust")
+                            _noadjust=true 
+                            ;;
+                        *)
+                            _help
+                            exit 1
+                            ;;
+                    esac
+        esac
+    done
+
+    shift $((OPTIND - 1))
+
+    # Color echo
+    #
+    # Text Color
+    # 30 => Black
+    # 31 => Red
+    # 32 => Green
+    # 33 => Yellow
+    # 34 => Blue
+    # 35 => Magenta
+    # 36 => Cyan
+    # 37 => White
+    #
+    # Background color
+    # 40 => Black
+    # 41 => Red
+    # 42 => Green
+    # 43 => Yellow
+    # 44 => Blue
+    # 45 => Magenta
+    # 46 => Cyan
+    # 47 => White
+    #
+    # Text decoration
+    # You can specify multiple decorations with ;.
+    # 0 => All attributs off (ノーマル)
+    # 1 => Bold on (太字)
+    # 4 => Underscore (下線)
+    # 5 => Blink on (点滅)
+    # 7 => Reverse video on (色反転)
+    # 8 => Concealed on
+
+    case ${1} in
+        "info")
+            _msg_type="type"
+            _output="stdout"
+            [[ "${_customized_label_color}" = false ]] && _labelcolor="32"
+            [[ "${_customized_label}"       = false ]] && _msg_label="Info"
+            shift 1
+            ;;
+        "warn")
+            _msg_type="warn"
+            _output="stdout"
+            [[ "${_customized_label_color}" = false ]] && _labelcolor="33"
+            [[ "${_customized_label}"       = false ]] && _msg_label="Warning"
+            shift 1
+            ;;
+        "debug")
+            _msg_type="debug"
+            _output="stdout"
+            [[ "${_customized_label_color}" = false ]] && _labelcolor="35"
+            [[ "${_customized_label}"       = false ]] && _msg_label="Debug"
+            shift 1
+            ;;
+        "error")
+            _msg_type="error"
+            _output="stderr"
+            [[ "${_customized_label_color}" = false ]] && _labelcolor="31"
+            [[ "${_customized_label}"       = false ]] && _msg_label="Error"
+            shift 1
+            ;;
+        "")
+            echo "Please specify the message type" >&2
+            exit 1
+            ;;
+        *)
+            echo "Unknown message type" >&2
+            exit 1
+            ;;
+    esac
+
+    _word_count="${#_msg_label}"
+    _message="${@}"
+
+    echo_type() {
+        local __time
+        if [[ "${_nolabel}" = false ]]; then
+            if [[ "${_noadjust}" = false ]]; then
+                for __time in $( seq 1 $(( ${_label_space} - ${_word_count})) ); do
+                    echo -ne "${_adjust_chr}"
+                done
+            fi
+            if [[ "${_nocolor}" = false ]]; then
+                echo -ne "\e[$([[ -v _backcolor ]] && echo -n "${_backcolor}"; [[ -v _labelcolor ]] && echo -n ";${_labelcolor}"; [[ -v _decotypes ]] && echo -n ";${_decotypes}")m${_msg_label}\e[m "
+            else
+                echo -ne "${_msg_label} "
+            fi
+        fi
+    }
+
+    echo_appname() {
+        if [[ "${_noappname}" = false ]]; then
+            if [[ "${_nocolor}" = false ]]; then
+                echo -ne "\e[36m[${_appname}]\e[m "
+            else
+                echo -ne "[${_appname}] "
+            fi
+        fi
+    }
+
+    for _count in $(seq "1" "$(echo -ne "${_message}\n" | wc -l)"); do
+        _echo_message=$(echo -ne "${_message}\n" |head -n "${_count}" | tail -n 1 )
+        _full_message="$(echo_appname)$(echo_type)${_echo_message}"
+        case "${_output}" in
+            "stdout")
+                echo ${_echo_opts} "${_full_message}" >&1
+                ;;
+            "stderr")
+                echo ${_echo_opts} "${_full_message}" >&2
+                ;;
+            *)
+                echo ${_echo_opts} "${_full_message}" > ${_output}
+                ;;
+        esac
+    done
+}
+
+# テキストの翻訳
+#set -xv
+translate() {
+    local _msg_translate
+    _msg_translate() {
+        local _get_text
+        local _locale="$(echo "${LANG}" | cut -d "." -f 1)"
+
+        _get_text() {
+            set +eu
+            local _translated_text="$(eval echo '$'{${_locale}["${*}"]})"
+            set -eu
+            if [[ -z "${_translated_text}" ]]; then
+                echo "${*}"
+            else
+                echo "${_translated_text}"
+            fi
+        }
+
+        local _text _fulltext=() _main
+
+        if declare -p "${_locale}" 2> /dev/null 1>/dev/null; then
+            _main="$(_get_text ${1})"
+        else
+            _main="${1}"
+        fi
+        shift 1
+        echo "$(printf "${_main}" ${@})"
+    }
+    _msg_translate "${@}"
+}
+
+
+
+# Show an INFO message
+# $1: message string
+msg_info() {
+    if [[ "${msgdebug}" = false ]]; then
+        set +xv
+    fi
+    local _msg_opts="-a ${wfa_name}"
+    if [[ "${1}" = "-n" ]]; then
+        _msg_opts="${_msg_opts} -o -n"
+        shift 1
+    fi
+    [[ "${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
+}
+
+# Show an Warning message
+# $1: message string
+msg_warn() {
+    if [[ "${msgdebug}" = false ]]; then
+        set +xv
+    fi
+    local _msg_opts="-a ${wfa_name}"
+    if [[ "${1}" = "-n" ]]; then
+        _msg_opts="${_msg_opts} -o -n"
+        shift 1
+    fi
+    [[ "${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
+}
+
+# Show an debug message
+# $1: message string
+msg_debug() {
+    if [[ "${msgdebug}" = false ]]; then
+        set +xv
+    fi
+    if [[ "${debug}" = true ]]; then
+        local _msg_opts="-a ${wfa_name}"
+        if [[ "${1}" = "-n" ]]; then
+            _msg_opts="${_msg_opts} -o -n"
+            shift 1
+        fi
+        [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
+        [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
+        msg ${_msg_opts} debug "$(translate "${@}")"
+    fi
+    if [[ "${bash_debug}" = true ]]; then
+        set -xv
+    fi
+}
+
+# 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
+    local _msg_opts="-a ${wfa_name}"
+    if [[ "${1}" = "-n" ]]; then
+        _msg_opts="${_msg_opts} -o -n"
+        shift 1
+    fi
+    [[ "${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
+}
+
+######################################################################################
+# ここから実際の処理開始
+# ここから下のメッセージは翻訳可能です
+
+# rm helper
+# Delete the file if it exists.
+# For directories, rm -rf is used.
+# If the file does not exist, skip it.
+# remove <file> <file> ...
+remove() {
+    local _list=($(echo "$@")) _file
+    for _file in "${_list[@]}"; do
+        msg_debug "Removing ${_file}"
+        if [[ -f "${_file}" ]]; then    
+            rm -f "${_file}"
+        elif [[ -d "${_file}" ]]; then
+            rm -rf "${_file}"
+        fi
+    done
+}
+
+usage (){
+    local _pacman_help=false
+
+    local _wfa_usage
+    _wfa_usage() {
+        echo "Usage:"
+        echo "${wfa_command}"
+        echo "${wfa_command} <operation> [...]"
+        echo
+        echo "operations:"
+        echo "    ${wfa_command} {-h --help}"
+        echo "    ${wfa_command} {-V --version}"
+       #echo "    ${wfa_command} {-D --database}    <options> <package(s)>"
+       #echo "    ${wfa_command} {-F --files}       [options] [package(s)]"
+        echo "    ${wfa_command} {-Q --query}       [options] [package(s)]"
+        echo "    ${wfa_command} {-R --remove}      [options] <package(s)>"
+        echo "    ${wfa_command} {-S --sync}        [options] [package(s)]"
+       #echo "    ${wfa_command} {-T --deptest}     [options] [package(s)]"
+       #echo "    ${wfa_command} {-U --upgrade}     [options] <file(s)>"
+       #echo
+       #echo "New operations:"
+       #echo "    ${wfa_command} {-P --show}        [options]"
+       #echo "    ${wfa_command} {-G --getpkgbuild} [package(s)]"
+        echo
+        echo "New options:"
+        echo "       --repo             Assume targets are from the repositories"
+        echo "    -a --aur              Assume targets are from the AUR"
+        echo
+        echo "Permanent configuration options:"
+        echo "    --aururl      <url>   Set an alternative AUR URL"
+        echo "    --makepkg     <file>  makepkg command to use"
+        echo "    --mflags      <flags> Pass arguments to makepkg"
+        echo "    --pacman      <file>  pacman command to use"
+        echo "    --git         <file>  git command to use"
+        echo "    --gitflags    <flags> Pass arguments to git"
+        echo "    --gpg         <file>  gpg command to use"
+        echo "    --gpgflags    <flags> Pass arguments to gpg"
+        echo "    --config      <file>  pacman.conf file to use"
+        echo "    --makepkgconf <file>  makepkg.conf file to use"
+        echo "    --nomakepkgconf       Use the default makepkg.conf"
+        echo
+    }
+
+    local _wfa_usage_sync
+    _wfa_usage_sync() {
+        echo "usage:  ${wfa_command} {-S --sync} [options] [package(s)]"
+        echo "options:"
+        echo "  -b, --dbpath <path>  set an alternate database location"
+        echo "      --config <path>  set an alternate configuration file"
+        echo "      --noconfirm      do not ask for any confirmation"
+
+    }
+
+    if [[ "${operation}" = "none" ]]; then
+        _wfa_usage
+    elif [[ "${_pacman_help}" = true ]]; then
+        "${pacman_command}" -h --${operation}
+    elif [[ "$(type -t "_wfa_usage_${operation}" )" = "function" ]]; then
+        _wfa_usage_${operation}
+    else
+        msg_error "Undefined operation"
+        exit 1
+    fi
+}
+
+set_operation() {
+    if [[ "${operation}" = "none" ]]; then
+        operation="${1}"
+        add_args pacman "--${operation}"
+    else
+        msg_error "only one operation may be used at a time"
+        exit 1
+    fi
+}
+
+run_sudo() {
+    if (( ${UID} == 0 )); then
+        ${@}
+    else
+        sudo ${@}
+    fi
+}
+
+run_pacman() {
+    run_sudo "${pacman_command}" ${@}
+}
+
+# pacmanの引数を追加する
+# https://github.com/FascodeNet/aptpac/blob/master/aptpac のADD_OPTION関数を参考
+# Usage: add_args [pacman/makepkg] <args1> <args2>...
+add_args() {
+    local _target="${1}"
+    local _args_array
+    shift 1
+
+    case "${_target}" in
+        "makepkg")
+            _args_array=(${makepkg_args})
+            _args_array+=(${@})
+            makepkg_args=${_args_array[@]}
+            msg_debug "makepkg ARGS: ${makepkg_args}"
+            ;;
+
+        "pacman")
+            _args_array=(${pacman_args})
+            _args_array+=(${@})
+            pacman_args=${_args_array[@]}
+            msg_debug "pacman ARGS: ${pacman_args}"
+            ;;
+        "git")
+            _args_array=(${mpg_args})
+            _args_array+=(${@})
+            git_args=${_args_array[@]}
+            msg_debug "git ARGS: ${git_args}"
+            ;;
+        "gpg")
+            _args_array=(${gpg_args})
+            _args_array+=(${@})
+            gpg_args=${_args_array[@]}
+            msg_debug "gpg ARGS: ${gpg_args}"
+            ;;
+        "sudo")
+            _args_array=(${sudo_args})
+            _args_array+=(${@})
+            sudo_args=${_args_array[@]}
+            msg_debug "sudo ARGS: ${sudo_args}"
+            ;;
+        *)
+            msg_error "Failed to set the argument of %s" "${_target}"
+            msg_error "Setting that command is not currently supported"
+            exit 1
+            ;;
+    esac
+}
+
+# 引数で指定されたパッケージがAUR以外の場所に存在しない場合にのみ正常終了します(AURのパッケージの場合に正常終了)
+check_aur_package() {
+    local _package="${1}"
+    # 参考: https://qiita.com/Hayao0819/items/a8740a17301fafa2fdab
+    if [[ -z "$(pacman -Ssq "${_package}" 2>/dev/null | grep -o ".*${_package}$")" ]]; then
+        #AUR以外のリポジトリに存在しない
+        return 0
+    else
+        return 1
+    fi
+}
+
+
+# 引数で指定されたパッケージが既にインストールされている場合は正常終了します。
+check_installed_package() {
+    local _package="${1}"
+    if "${pacman_command}" -Qq "${_package}" > /dev/null 2>&1; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+get_cache_dir() {
+    local _user_config_dir
+    if [[ -v XDG_CONFIG_HOME ]]; then
+        _user_config_dir="${XDG_CONFIG_HOME}"
+    else
+        _use_config_dir="${HOME}/.config"
+    fi
+    if [[ -f "${_use_config_dir}/user-dirs.dirs" ]]; then
+        source "${_use_config_dir}/user-dirs.dirs"
+    fi
+    if [[ -v XDG_CACHE_HOME ]]; then
+        echo -n "${XDG_CACHE_HOME}"
+        return 0
+    else
+        echo -n "${HOME}/.cache"
+        return 0
+    fi
+}
+
+# Usage: get_srcinfo_data <path> <var>
+# 参考: https://qiita.com/withelmo/items/b0e1ffba639dd3ae18c0
+get_srcinfo_data() {
+    local _srcinfo="${1}" _ver="${2}"
+    local _srcinfo_json=$(python << EOF
+from srcinfo.parse import parse_srcinfo; import json
+text = """
+$(cat ${1})
+"""
+parsed, errors = parse_srcinfo(text)
+print(json.dumps(parsed))
+EOF
+)
+    echo "${_srcinfo_json}" | jq -rc "${2}" | tr '\n' ' '
+}
+
+
+# AURからパッケージをビルドしてインストールします
+# 現在1つのパッケージしか指定できません
+install_aur_package() {
+    local _package="${1}"
+
+    # Create cache dir
+    if [[ ! -v wfa_cache_dir ]]; then
+        wfa_cache_dir="$(get_cache_dir)/wfa"
+    fi
+    mkdir -p "${wfa_cache_dir}/archive"
+    mkdir -p "${wfa_cache_dir}/build/${_package}"
+
+    # AurJsonから値を取得
+    local _aur_json=$(curl -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
+        msg_error "Could not find all required packages:\n     ${_package}"
+        exit 1
+    fi
+
+    local _found_packages="$(echo "${_aur_json}" | jq -r --tab '.results[].Name')"
+    #msg_debug "Found package: $(echo ${_found_packages} | tr '\n' ' ')"
+
+    if [[ -n "$(echo "${_found_packages}" | grep -x "${_package}" )" ]]; then
+        msg_debug "Select a package %s with an exact name match" "${_package}"
+    else
+        msg_error "No package with an exact name match was found"
+        exit 1
+    fi
+
+    # PKGBUILDをダウンロード
+    msg_info "Download PKGBUILD of %s" "${_package}"
+    _aur_json=$(echo "${_aur_json}" | jq -r ".results[] | 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}"
+
+    local _pkgbuild_archive_path="${wfa_cache_dir}/archive/${_package}-${_aur_version}"
+    local _download_pkgbuild=true
+    if [[ -f "${_pkgbuild_archive_path}" ]]; then
+        msg_warn "PKGBUILD has already been downloaded"
+        msg_warn -n "Do you want to overwrite and download? [n] :"
+        local _yes_or_no
+        if [[ "${noconfirm}" = true ]]; then
+            echo
+            _yes_or_no="No"
+        else
+            read _yes_or_no
+        fi
+        case "${_yes_or_no}" in
+            "y" | "Y" | "yes" | "Yes" | "YES" ) _download_pkgbuild=true  ;;
+            *                                 ) _download_pkgbuild=false ;;
+        esac
+    fi
+    if [[ "${_download_pkgbuild}" = true ]]; then
+        remove "${_pkgbuild_archive_path}"
+        curl -L -C - -f -o "${_pkgbuild_archive_path}" "${_aur_snapshot_url}"
+    fi
+
+    # PKGBUILDを展開
+    msg_info "Unpacking the tarball of PKGBUILD ..."  #ここまで翻訳
+    tar -xv -f "${_pkgbuild_archive_path}" -C "${wfa_cache_dir}/build/" > /dev/null 2>&1
+
+    # .SRCINFOを解析
+    local _build_dir="${wfa_cache_dir}/build/${_package}"
+    if [[ ! -f "${_build_dir}/.SRCINFO" ]]; then
+        msg_warn ".SRCINFO was not found.\nGenerate it using makepkg."
+        (
+            cd "${_build_dir}"
+            "${makepkg_command}" --printsrcinfo > "${_build_dir}/.SRCINFO"
+        )
+    fi
+
+    local _makedepends="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".makedepends[]?")"
+    local _depends="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".depends[]?")"
+    local _conflicts="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".conflicts[]?")"
+    msg_debug "makedepends: ${_makedepends}"
+    msg_debug "depends: ${_depends}"
+    msg_debug "conflicts: ${_conflicts}"
+
+
+    # 衝突を確認
+    local _pkg _conflicts_found=false
+    for _pkg in ${_conflicts[@]}; do
+        if "${pacman_command}" -Qq "${_pkg}" > /dev/null 2>&1 ; then
+            _conflicts_found=true
+            msg_error "${_package} is colliding with ${_pkg}"
+        fi
+    done
+    if "${pacman_command}" -Qq "${_package}" > /dev/null 2>&1 &&  [[ ! "$("${pacman_command}" -Qq "${_package}" 2> /dev/null)" = "${_package}" ]]; then
+        msg_error "${_package} is colliding with $("${pacman_command}" -Qq "${_package}")"
+        _conflicts_found=true
+    fi
+    if [[ "${_conflicts_found}" = true ]]; then
+        msg_error "A conflict was found."
+        exit 1
+    fi
+
+
+    # 依存パッケージをインストール
+    if [[ "${nodeps}" = false ]]; then
+        msg_info "Install dependent packages..."
+        local _force_aur="${force_aur}"
+        force_aur=false
+        install_package "${_depends}"
+        force_aur="${_force_aur}"
+        unset _force_aur
+    fi
+
+    # ビルド準備
+    # srcdirの確認
+    if [[ -d "${_build_dir}/src" ]]; then
+        msg_info "Found ${_build_dir}/src"
+        msg_info "Packages to cleanBuild? [n] :"
+        local _yes_or_no
+        unset _yes_or_no
+        if [[ "${noconfirm}" = true ]]; then
+            echo
+            _yes_or_no="No"
+        else
+            read _yes_or_no
+        fi
+        case "${_yes_or_no}" in
+            "y" | "Y" | "yes" | "Yes" | "YES" ) add_args makepkg "--clean" ;;
+        esac
+    fi
+
+
+    # ビルド
+    add_args "makepkg" "-sf"
+    (
+        cd "${_build_dir}"
+        "${makepkg_command}" "${makepkg_args}"
+    )
+
+
+    # ビルド後のパッケージ一覧を生成
+    (
+        cd "${_build_dir}"
+        "${makepkg_command}" --printsrcinfo > "${_build_dir}/.SRCINFO"
+    )
+    local _pkgnames=($(get_srcinfo_data "${_build_dir}/.SRCINFO" ".packages | keys[]" | sed 's/ //g'))
+    local _pkgver="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".pkgver" | sed 's/ //g')"
+    local _pkgrel="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".pkgrel" | sed 's/ //g')"
+    local _arch_array=($(get_srcinfo_data "${_build_dir}/.SRCINFO" ".arch[]"))
+    local _arch _pkgname
+    if [[ "${_arch_array[*]}" = "any" ]]; then
+        _arch="any"
+    else
+        _arch="$(uname -m)"
+    fi
+    local _PKGEXT=$(
+        source "${makepkg_config}"
+        echo "${PKGEXT}"
+    )
+    local _pkgfilelist=()
+    for _pkgname in ${_pkgnames[@]}; do
+        _pkgfilelist+=("${_build_dir}/${_pkgname}-${_pkgver}-${_pkgrel}-${_arch}${_PKGEXT}")
+    done
+
+    # インストール
+    run_pacman -U --noconfirm ${_pkgfilelist[@]}
+}
+
+# AURのパッケージを検索
+search_aur_package() {
+    local _package="${1}"
+    local _aur_json=$(curl -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
+        msg_error "Could not find all required packages:\n     ${_package}"
+        exit 1
+    fi
+    _aur_json=$(echo "${_aur_json}" | jq -r ".results[]")
+
+    #echo ${_aur_json} 
+
+    local _found_pkgname=($(echo "${_aur_json}" | jq -r ".Name" ))
+
+
+
+
+    local  _found_package __pkgver __popularity __vote __pkgdesc
+    for _found_package in ${_found_pkgname[@]}; do
+        _found_json="$(echo ${_aur_json} | jq "select(.Name == \"${_found_package}\")")"
+        __pkgver="$(echo "${_found_json}" | jq -r ".Version" )"
+        __popularity="$(echo "${_found_json}" | jq -r ".Popularity" )"
+        __vote="$(echo "${_found_json}" | jq -r ".NumVotes" )"
+        __pkgdesc="$(echo "${_found_json}" | jq -r ".Description" )"
+    
+        echo "aur/${_found_package} ${__pkgver} (+${__vote} ${__popularity})"
+        echo "    ${__pkgdesc}"
+        unset __pkgver __popularity __vote __pkgdesc _found_json
+    done
+}
+
+# バージョンを表示して終了
+operation_version() {
+    # Pyalpmからlibalpmの値を取得
+    # 参考: https://pyalpm.readthedocs.io/en/latest/pyalpm/pyalpm.html
+    local _libalpm_version="$(python3 -c 'import pyalpm; print(pyalpm.alpmversion())')"
+    local _pacman_version="$("${pacman_command}" -Q pacman | cut -d ' ' -f 2)"
+    echo "wfa v${wfa_version} - pacman v${_pacman_version} - libalpm v${_libalpm_version}"
+}
+
+operation_remove() {
+    run_pacman ${pacman_args} "${specified_packages[@]}"
+}
+
+# Usage: install_package <package1> <package2>...
+install_package() {
+    local _package
+    for _package in ${@}; do
+        if ! check_installed_package "${_package}"; then
+            if ! check_aur_package "${_package}"; then
+                # 公式パッケージなのでpacmanでそのままインストール
+                run_pacman ${pacman_args} "${_package}"
+            else
+                # AUR上のパッケージの場合の処理
+                install_aur_package "${_package}"
+                #msg_error "Getting the AUR package has not been implemented yet.
+                #exit 1
+            fi
+        fi
+    done
+}
+
+operation_sync(){
+    local _package
+    if [[ "${sync_search}" = true ]]; then
+        for _package in ${specified_packages[@]}; do
+            search_aur_package "${_package}"
+        done
+        "${pacman_command}" ${pacman_args} ${specified_packages[@]}
+    else
+        for _package in ${specified_packages[@]}; do
+            if ! check_aur_package "${_package}" && [[ "${force_aur}" = false ]]; then
+                # 公式パッケージなのでpacmanでそのままインストール
+                run_pacman ${pacman_args} "${_package}"
+            else
+                # AUR上のパッケージの場合の処理
+                install_aur_package "${_package}"
+                #msg_error "Getting the AUR package has not been implemented yet."
+                #exit 1
+            fi
+        done
+    fi
+}
+
+
+# Parse options
+ARGUMENT="${@}"
+_opt_short="QRShVdb:ays"
+_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"
+
+OPT=$(getopt -o ${_opt_short} -l ${_opt_long} -- ${ARGUMENT})
+[[ ${?} != 0 ]] && exit 1
+unset _opt_short _opt_long
+
+eval set -- "${OPT}"
+msg_debug "Argument: ${OPT}"
+
+while :; do
+    case ${1} in
+        -Q | --query)
+            set_operation "query"
+            shift 1
+            ;;
+        -R | --remove)
+            set_operation "remove"
+            shift 1
+            ;;
+        -S | --sync)
+            set_operation "sync"
+            shift 1
+            ;;
+        -V | --version)
+            set_operation "version"
+            shift 1
+            ;;
+        --)
+            shift
+            break
+            ;;
+        *)
+            shift 1
+            ;;
+    esac
+done
+
+eval set -- "${OPT}"
+
+while :; do
+    case ${1} in
+        -a | --aur)
+            force_aur=true
+            msg_debug "Assume targets are from the AUR"
+            shift 1
+            ;;
+        --debug)
+            debug=true
+            add_args pacman "--debug"
+            shift 1
+            ;;
+        -d | --nodeps)
+            nodeps=true
+            add_args pacman "--nodeps"
+            shift 1
+            ;;
+        -b | --dbpath)
+            add_args pacman "--dbpath '${2}'"
+            shift 2
+            ;;
+        -y | --refresh)
+            option_y_count=$(( option_y_count + 1 ))
+            shift 1
+            ;;
+        -s | --search)
+            add_args pacman "--search"
+            sync_search=true
+            shift 1
+            ;;
+        --aururl)
+            aururl="${2}"
+            shift 2
+            ;;
+        --noconfirm)
+            add_args pacman "--noconfirm"
+            noconfirm=true
+            shift 1
+            ;;
+        --config)
+            pacman_config="${2}"
+            add_args pacman "--config \"${2}\""
+            shift 2
+            ;;
+        --makepkg)
+            makepkg_command="${2}"
+            shift 2
+            ;;
+        --mflags)
+            makepkg_args="${2}"
+            shift 2
+            ;;
+        --pacman)
+            pacman_command="${2}"
+            shift 2
+            ;;
+        --git)
+            git_command="${2}"
+            shift 2
+            ;;
+        --gitflags)
+            git_args="${2}"
+            shift 2
+            ;;
+        --makepkgconfig)
+            if [[ "${nomakepkgconf}" = false ]]; then
+                makepkg_config="${2}"
+            else
+                msg_warn "--nomakepkgconf is specified.\n--makepkgconf has been ignored."
+            fi
+            shift 2
+            ;;
+        --nomakepkgconf)
+            makepkg_config="/etc/makepkg.conf"
+            nomakepkgconf=true
+            shift 1
+        ;;
+        --bash-debug)
+            bash_debug=true
+            set -xv
+            shift 1
+            ;;
+        --msg-debug)
+            msgdebug=true
+            shift 1
+            ;;
+        -h | --help)
+            usage
+            shift 1
+            exit 0
+            ;;
+        --)
+            shift
+            break
+            ;;
+        *)
+            shift 1
+            ;;
+    esac
+done
+
+specified_packages=(${@})
+
+# Run database update
+if (( "${option_y_count}" == 1 )); then
+    run_pacman -Sy
+elif (( "${option_y_count}" >= 2 )); then
+    run_pacman -Syy
+fi
+
+case "${operation}" in
+    "version")
+        operation_version
+        ;;
+    "sync")
+        operation_sync
+        ;;
+    "remove")
+        operation_remove
+        ;;
+    "none")
+        exit 0
+        ;;
+    *)
+        msg_error "Undefined operation"
+        exit 1
+        ;;
+esac