OSDN Git Service

[update] : Added --bash-debug
[alterlinux/wfa.git] / wfa
diff --git a/wfa b/wfa
index 09ef3d7..7b183a4 100755 (executable)
--- a/wfa
+++ b/wfa
@@ -2,16 +2,67 @@
 
 set -eu
 
-msgdebug=false
-nocolor=false
-debug=false
-pacman_args=""
+######################################################################################
+
+#-- 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
+
+#-- 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=""
+
+
+######################################################################################
 
-wfa_version="0.1"
-aururl="https://aur.archlinux.org/"
 
 # メッセージ出力の制御
 # https://github.com/FascodeNet/alterlinux/blob/dev/tools/msg.sh の変数名にアンダーバーを追加し関数化
@@ -274,7 +325,10 @@ msg() {
 # Show an INFO message
 # $1: message string
 msg_info() {
-    local _msg_opts="-a WFA"
+    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
@@ -282,12 +336,18 @@ msg_info() {
     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
     msg ${_msg_opts} info "${1}"
+    if [[ "${bash_debug}" = true ]]; then
+        set -xv
+    fi
 }
 
 # Show an Warning message
 # $1: message string
 msg_warn() {
-    local _msg_opts="-a WFA"
+    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
@@ -295,13 +355,19 @@ msg_warn() {
     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
     msg ${_msg_opts} warn "${1}"
+    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"
+        local _msg_opts="-a ${wfa_name}"
         if [[ "${1}" = "-n" ]]; then
             _msg_opts="${_msg_opts} -o -n"
             shift 1
@@ -310,13 +376,19 @@ msg_debug() {
         [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
         msg ${_msg_opts} debug "${1}"
     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() {
-    local _msg_opts="-a WFA"
+    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
@@ -327,6 +399,9 @@ msg_error() {
     if [[ -n "${2:-}" ]]; then
         exit ${2}
     fi
+    if [[ "${bash_debug}" = true ]]; then
+        set -xv
+    fi
 }
 
 # rm helper
@@ -347,35 +422,73 @@ remove() {
 }
 
 usage (){
+    local _pacman_help=false
+
     local _wfa_usage
     _wfa_usage() {
         echo "Usage:"
-        echo "wfa"
-        echo "wfa <operation> [...]"
+        echo "${wfa_command}"
+        echo "${wfa_command} <operation> [...]"
         echo
         echo "operations:"
-        echo "wfa {-h --help}"
-        echo "wfa {-V --version}"
-        #echo "wfa {-D --database}    <options> <package(s)>"
-        #echo "wfa {-F --files}       [options] [package(s)]"
-        echo "wfa {-Q --query}       [options] [package(s)]"
-        echo "wfa {-R --remove}      [options] <package(s)>"
-        echo "wfa {-S --sync}        [options] [package(s)]"
-        #echo "wfa {-T --deptest}     [options] [package(s)]"
-        #echo "wfa {-U --upgrade}     [options] <file(s)>"
+        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
-        pacman -h --${operation}
+        msg_error "Undefined operation." 1
     fi
 }
 
 set_operation() {
     if [[ "${operation}" = "none" ]]; then
         operation="${1}"
-        add_pacman_args "--${operation}"
+        add_args pacman "--${operation}"
     else
         msg_error "only one operation may be used at a time" 1
     fi
@@ -390,23 +503,60 @@ run_sudo() {
 }
 
 run_pacman() {
-    run_sudo pacman ${pacman_args} ${@}
+    run_sudo "${pacman_command}" ${@}
 }
 
 # pacmanの引数を追加する
 # https://github.com/FascodeNet/aptpac/blob/master/aptpac のADD_OPTION関数を参考
-add_pacman_args() {
-    local _pacman_args_array=(${pacman_args})
-    _pacman_args_array+=(${@})
-    pacman_args=${_pacman_args_array[@]}
-    msg_debug "PACMAN ARGS: ${pacman_args}"
+# 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 ${_target}\nSetting that command is not currently supported." 1
+            ;;
+    esac
 }
 
 # 引数で指定されたパッケージがAUR以外の場所に存在しない場合にのみ正常終了します(AURのパッケージの場合に正常終了)
 check_aur_package() {
     local _package="${1}"
     # 参考: https://qiita.com/Hayao0819/items/a8740a17301fafa2fdab
-    if [[ -z "$(pacman -Fq "${_package}" 2>/dev/null | grep -o ".*${_package}$")" ]]; then
+    if [[ -z "$(pacman -Ssq "${_package}" 2>/dev/null | grep -o ".*${_package}$")" ]]; then
         #AUR以外のリポジトリに存在しない
         return 0
     else
@@ -415,6 +565,16 @@ check_aur_package() {
 }
 
 
+# 引数で指定されたパッケージが既にインストールされている場合は正常終了します。
+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
@@ -435,7 +595,7 @@ get_cache_dir() {
 }
 
 # Usage: get_srcinfo_data <path> <var>
-: << "DISABLED"
+# 参考: https://qiita.com/withelmo/items/b0e1ffba639dd3ae18c0
 get_srcinfo_data() {
     local _srcinfo="${1}" _ver="${2}"
     local _srcinfo_json=$(python << EOF
@@ -446,22 +606,8 @@ $(cat ${1})
 parsed, errors = parse_srcinfo(text)
 print(json.dumps(parsed))
 EOF
-    )
-    echo "${_srcinfo_json}" | jq -r .${2}
-}
-DISABLED
-
-get_srcinfo_data() {
-    local _srcinfo="${1}"
-    local _var="${2}"
-    local _pkg _output
-    if [[ ! -f "${_srcinfo}" ]]; then
-        msg_error ".SRCINFO does not exist."
-    fi
-    for _pkg in $(cat "${_srcinfo}" | grep "${_var} = " | cut -d ' ' -f "3"); do
-        _output+=(${_pkg})
-    done
-    echo -n "${_output[@]}"
+)
+    echo "${_srcinfo_json}" | jq -rc "${2}" | tr '\n' ' '
 }
 
 
@@ -522,18 +668,22 @@ install_aur_package() {
     fi
 
     # PKGBUILDを展開
-    tar -xv -f "${_pkgbuild_archive_path}" -C "${wfa_cache_dir}/build/"
+    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."
-        makepkg -p "${_build_dir}/PKGBUILD" --printsrcinfo > "${_build_dir}/.SRCINFO"
+        (
+            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")"
+    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}"
@@ -542,13 +692,13 @@ install_aur_package() {
     # 衝突を確認
     local _pkg _conflicts_found=false
     for _pkg in ${_conflicts[@]}; do
-        if pacman -Qq "${_pkg}" 2>/dev/null 1>&2 ; then
+        if "${pacman_command}" -Qq "${_pkg}" > /dev/null 2>&1 ; then
             _conflicts_found=true
             msg_error "${_package} is colliding with ${_pkg}"
         fi
     done
-    if pacman -Qq "${_package}" 2>/dev/null 1>&2; then
-        msg_error "${_package} is colliding with $(pacman -Qq "${_package}")"
+    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
@@ -557,11 +707,68 @@ install_aur_package() {
 
 
     # 依存パッケージをインストール
-    msg_info "Install dependent packages..."
-    install_package "${_makedepends}" "${_depends}"
+    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[@]}
 }
 
 # バージョンを表示して終了
@@ -569,21 +776,37 @@ 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 -Q pacman | cut -d ' ' -f 2)"
+    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 "${specified_packages[@]}"
+    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." 1
+            fi
+        fi
+    done
+}
+
+operation_sync(){
+    local _package
+    for _package in ${specified_packages[@]}; do
         if ! check_aur_package "${_package}" && [[ "${force_aur}" = false ]]; then
             # 公式パッケージなのでpacmanでそのままインストール
-            run_pacman "${_package}"
+            run_pacman ${pacman_args} "${_package}"
         else
             # AUR上のパッケージの場合の処理
             install_aur_package "${_package}"
@@ -592,15 +815,11 @@ install_package() {
     done
 }
 
-operation_sync(){
-    install_package "${specified_packages[@]}"
-}
-
 
 # Parse options
 ARGUMENT="${@}"
-_opt_short="QRShVdb:a"
-_opt_long="query,remove,sync,help,version,debug,dbpath:,aururl,aur,noconfirm"
+_opt_short="QRShVdb:ay"
+_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"
 
 OPT=$(getopt -o ${_opt_short} -l ${_opt_long} -- ${ARGUMENT})
 [[ ${?} != 0 ]] && exit 1
@@ -646,24 +865,76 @@ while :; do
             msg_debug "Assume targets are from the AUR"
             shift 1
             ;;
-        -d | --debug)
+        --debug)
             debug=true
-            add_pacman_args "--debug"
+            add_args pacman "--debug"
+            shift 1
+            ;;
+        -d | --nodeps)
+            nodeps=true
+            add_args pacman "--nodeps"
             shift 1
             ;;
         -b | --dbpath)
-            add_pacman_args "--dbpath '${2}'"
+            add_args pacman "--dbpath '${2}'"
             shift 2
             ;;
+        -y | --refresh)
+            option_y_count=$(( option_y_count + 1 ))
+            shift 1
+            ;;
         --aururl)
             aururl="${2}"
             shift 2
             ;;
         --noconfirm)
-            add_pacman_args "--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
+            ;;
         -h | --help)
             usage
             shift 1
@@ -681,6 +952,13 @@ 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