6 ######################################################################################
10 ["Undefined operation."]="未定義のオペレーションです。"
11 ["only one operation may be used at a time"]="一度に使用できるオペレーションは1つだけです"
12 ["Failed to set the argument of %s"]="%sの引数の設定に失敗しました"
13 ["Setting that command is not currently supported."]="そのコマンドの設定は現在サポートされていません。"
14 ["Install dependent packages..."]="依存パッケージをインストールします..."
15 ["No package with an exact name match was found."]="完全に一致する名前のパッケージが見つかりませんでした。"
16 ["Select a package %s with an exact name match"]="名前が完全に一致するパッケージ %s を選択します"
17 ["Download PKGBUILD of %s"]="%s のPKGBUILDをダウンロード"
19 ######################################################################################
31 aururl="https://aur.archlinux.org/"
34 #-- options (bool) --#
47 makepkg_command="/usr/bin/makepkg"
49 makepkg_config="/etc/makepkg.conf"
55 pacman_command="/usr/bin/pacman"
57 pacman_config="/etc/pacman.conf"
63 git_command="/usr/bin/git"
69 gpg_command="/usr/bin/gpg"
75 sudo_command="/usr/bin/sudo"
81 ######################################################################################
86 # https://github.com/FascodeNet/alterlinux/blob/dev/tools/msg.sh の変数名にアンダーバーを追加し関数化
88 local OPTIND OPTARG arg
90 local _appname="msg.sh"
91 local _bash_debug=false
95 local _msg_type="info"
97 local _label_space="7"
99 local _customized_label=false
100 local _customized_label_color=false
102 local _noappname=false
103 local _noadjust=false
104 local _output="stdout"
107 echo "usage ${0} [option] [type] [message]"
109 echo "Display a message with a colored app name and message type label"
111 echo " General type:"
112 echo " info General message"
113 echo " warn Warning message"
114 echo " error Error message"
115 echo " debug Debug message"
117 echo " General options:"
118 echo " -a [name] Specify the app name"
119 echo " -c [character] Specify the character to adjust the label"
120 echo " -l [label] Specify the label."
121 echo " -n | --nocolor No output colored output"
122 echo " -o [option] Specify echo options"
123 echo " -r [color] Specify the color of label"
124 echo " -s [number] Specifies the label space."
125 echo " -x | --bash-debug Enables output bash debugging"
126 echo " -h | --help This help message"
128 echo " --nolabel Do not output label"
129 echo " --noappname Do not output app name"
130 echo " --noadjust Do not adjust the width of the label"
133 while getopts "a:c:l:no:r:s:xh-:" arg; do
139 _adjust_chr="${OPTARG}"
142 _customized_label=true
143 _msg_label="${OPTARG}"
149 _echo_opts="${OPTARG}"
152 _customized_label_color=true
184 _label_space="${OPTARG}"
225 shift $((OPTIND - 1))
250 # You can specify multiple decorations with ;.
251 # 0 => All attributs off (ノーマル)
253 # 4 => Underscore (下線)
255 # 7 => Reverse video on (色反転)
262 [[ "${_customized_label_color}" = false ]] && _labelcolor="32"
263 [[ "${_customized_label}" = false ]] && _msg_label="Info"
269 [[ "${_customized_label_color}" = false ]] && _labelcolor="33"
270 [[ "${_customized_label}" = false ]] && _msg_label="Warning"
276 [[ "${_customized_label_color}" = false ]] && _labelcolor="35"
277 [[ "${_customized_label}" = false ]] && _msg_label="Debug"
283 [[ "${_customized_label_color}" = false ]] && _labelcolor="31"
284 [[ "${_customized_label}" = false ]] && _msg_label="Error"
288 echo "Please specify the message type" >&2
292 echo "Unknown message type" >&2
297 _word_count="${#_msg_label}"
302 if [[ "${_nolabel}" = false ]]; then
303 if [[ "${_noadjust}" = false ]]; then
304 for __time in $( seq 1 $(( ${_label_space} - ${_word_count})) ); do
305 echo -ne "${_adjust_chr}"
308 if [[ "${_nocolor}" = false ]]; then
309 echo -ne "\e[$([[ -v _backcolor ]] && echo -n "${_backcolor}"; [[ -v _labelcolor ]] && echo -n ";${_labelcolor}"; [[ -v _decotypes ]] && echo -n ";${_decotypes}")m${_msg_label}\e[m "
311 echo -ne "${_msg_label} "
317 if [[ "${_noappname}" = false ]]; then
318 if [[ "${_nocolor}" = false ]]; then
319 echo -ne "\e[36m[${_appname}]\e[m "
321 echo -ne "[${_appname}] "
326 for _count in $(seq "1" "$(echo -ne "${_message}\n" | wc -l)"); do
327 _echo_message=$(echo -ne "${_message}\n" |head -n "${_count}" | tail -n 1 )
328 _full_message="$(echo_appname)$(echo_type)${_echo_message}"
331 echo ${_echo_opts} "${_full_message}" >&1
334 echo ${_echo_opts} "${_full_message}" >&2
337 echo ${_echo_opts} "${_full_message}" > ${_output}
349 local _locale="$(echo "${LANG}" | cut -d "." -f 1)"
353 local _translated_text="$(eval echo '$'{${_locale}["${*}"]})"
355 if [[ -z "${_translated_text}" ]]; then
358 echo "${_translated_text}"
362 local _text _fulltext=() _main
364 if declare -p "${_locale}" 2> /dev/null 1>/dev/null; then
365 _main="$(_get_text ${1})"
370 echo "$(printf "${_main}" ${@})"
372 _msg_translate "${@}"
377 # Show an INFO message
380 if [[ "${msgdebug}" = false ]]; then
383 local _msg_opts="-a ${wfa_name}"
384 if [[ "${1}" = "-n" ]]; then
385 _msg_opts="${_msg_opts} -o -n"
388 [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
389 [[ "${nocolor}" = true ]] && _msg_opts="${_msg_opts} -n"
390 msg ${_msg_opts} info "$(translate "${@}")"
391 if [[ "${bash_debug}" = true ]]; then
396 # Show an Warning message
399 if [[ "${msgdebug}" = false ]]; then
402 local _msg_opts="-a ${wfa_name}"
403 if [[ "${1}" = "-n" ]]; then
404 _msg_opts="${_msg_opts} -o -n"
407 [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
408 [[ "${nocolor}" = true ]] && _msg_opts="${_msg_opts} -n"
409 msg ${_msg_opts} warn "$(translate "${@}")"
410 if [[ "${bash_debug}" = true ]]; then
415 # Show an debug message
418 if [[ "${msgdebug}" = false ]]; then
421 if [[ "${debug}" = true ]]; then
422 local _msg_opts="-a ${wfa_name}"
423 if [[ "${1}" = "-n" ]]; then
424 _msg_opts="${_msg_opts} -o -n"
427 [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
428 [[ "${nocolor}" = true ]] && _msg_opts="${_msg_opts} -n"
429 msg ${_msg_opts} debug "$(translate "${@}")"
431 if [[ "${bash_debug}" = true ]]; then
436 # Show an ERROR message then exit with status
438 # $2: exit code number (with 0 does not exit)
440 if [[ "${msgdebug}" = false ]]; then
443 local _msg_opts="-a ${wfa_name}"
444 if [[ "${1}" = "-n" ]]; then
445 _msg_opts="${_msg_opts} -o -n"
448 [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
449 [[ "${nocolor}" = true ]] && _msg_opts="${_msg_opts} -n"
450 msg ${_msg_opts} error "$(translate "${@}")"
451 if [[ "${bash_debug}" = true ]]; then
456 ######################################################################################
461 # Delete the file if it exists.
462 # For directories, rm -rf is used.
463 # If the file does not exist, skip it.
464 # remove <file> <file> ...
466 local _list=($(echo "$@")) _file
467 for _file in "${_list[@]}"; do
468 msg_debug "Removing ${_file}"
469 if [[ -f "${_file}" ]]; then
471 elif [[ -d "${_file}" ]]; then
478 local _pacman_help=false
483 echo "${wfa_command}"
484 echo "${wfa_command} <operation> [...]"
487 echo " ${wfa_command} {-h --help}"
488 echo " ${wfa_command} {-V --version}"
489 #echo " ${wfa_command} {-D --database} <options> <package(s)>"
490 #echo " ${wfa_command} {-F --files} [options] [package(s)]"
491 echo " ${wfa_command} {-Q --query} [options] [package(s)]"
492 echo " ${wfa_command} {-R --remove} [options] <package(s)>"
493 echo " ${wfa_command} {-S --sync} [options] [package(s)]"
494 #echo " ${wfa_command} {-T --deptest} [options] [package(s)]"
495 #echo " ${wfa_command} {-U --upgrade} [options] <file(s)>"
497 #echo "New operations:"
498 #echo " ${wfa_command} {-P --show} [options]"
499 #echo " ${wfa_command} {-G --getpkgbuild} [package(s)]"
502 echo " --repo Assume targets are from the repositories"
503 echo " -a --aur Assume targets are from the AUR"
505 echo "Permanent configuration options:"
506 echo " --aururl <url> Set an alternative AUR URL"
507 echo " --makepkg <file> makepkg command to use"
508 echo " --mflags <flags> Pass arguments to makepkg"
509 echo " --pacman <file> pacman command to use"
510 echo " --git <file> git command to use"
511 echo " --gitflags <flags> Pass arguments to git"
512 echo " --gpg <file> gpg command to use"
513 echo " --gpgflags <flags> Pass arguments to gpg"
514 echo " --config <file> pacman.conf file to use"
515 echo " --makepkgconf <file> makepkg.conf file to use"
516 echo " --nomakepkgconf Use the default makepkg.conf"
520 local _wfa_usage_sync
522 echo "usage: ${wfa_command} {-S --sync} [options] [package(s)]"
524 echo " -b, --dbpath <path> set an alternate database location"
525 echo " --config <path> set an alternate configuration file"
526 echo " --noconfirm do not ask for any confirmation"
530 if [[ "${operation}" = "none" ]]; then
532 elif [[ "${_pacman_help}" = true ]]; then
533 "${pacman_command}" -h --${operation}
534 elif [[ "$(type -t "_wfa_usage_${operation}" )" = "function" ]]; then
535 _wfa_usage_${operation}
537 msg_error "Undefined operation."
543 if [[ "${operation}" = "none" ]]; then
545 add_args pacman "--${operation}"
547 msg_error "only one operation may be used at a time"
553 if (( ${UID} == 0 )); then
561 run_sudo "${pacman_command}" ${@}
565 # https://github.com/FascodeNet/aptpac/blob/master/aptpac のADD_OPTION関数を参考
566 # Usage: add_args [pacman/makepkg] <args1> <args2>...
574 _args_array=(${makepkg_args})
576 makepkg_args=${_args_array[@]}
577 msg_debug "makepkg ARGS: ${makepkg_args}"
581 _args_array=(${pacman_args})
583 pacman_args=${_args_array[@]}
584 msg_debug "pacman ARGS: ${pacman_args}"
587 _args_array=(${mpg_args})
589 git_args=${_args_array[@]}
590 msg_debug "git ARGS: ${git_args}"
593 _args_array=(${gpg_args})
595 gpg_args=${_args_array[@]}
596 msg_debug "gpg ARGS: ${gpg_args}"
599 _args_array=(${sudo_args})
601 sudo_args=${_args_array[@]}
602 msg_debug "sudo ARGS: ${sudo_args}"
605 msg_error "Failed to set the argument of %s" "${_target}"
606 msg_error "Setting that command is not currently supported."
612 # 引数で指定されたパッケージがAUR以外の場所に存在しない場合にのみ正常終了します(AURのパッケージの場合に正常終了)
613 check_aur_package() {
614 local _package="${1}"
615 # 参考: https://qiita.com/Hayao0819/items/a8740a17301fafa2fdab
616 if [[ -z "$(pacman -Ssq "${_package}" 2>/dev/null | grep -o ".*${_package}$")" ]]; then
625 # 引数で指定されたパッケージが既にインストールされている場合は正常終了します。
626 check_installed_package() {
627 local _package="${1}"
628 if "${pacman_command}" -Qq "${_package}" > /dev/null 2>&1; then
636 local _user_config_dir
637 if [[ -v XDG_CONFIG_HOME ]]; then
638 _user_config_dir="${XDG_CONFIG_HOME}"
640 _use_config_dir="${HOME}/.config"
642 if [[ -f "${_use_config_dir}/user-dirs.dirs" ]]; then
643 source "${_use_config_dir}/user-dirs.dirs"
645 if [[ -v XDG_CACHE_HOME ]]; then
646 echo -n "${XDG_CACHE_HOME}"
649 echo -n "${HOME}/.cache"
654 # Usage: get_srcinfo_data <path> <var>
655 # 参考: https://qiita.com/withelmo/items/b0e1ffba639dd3ae18c0
657 local _srcinfo="${1}" _ver="${2}"
658 local _srcinfo_json=$(python << EOF
659 from srcinfo.parse import parse_srcinfo; import json
663 parsed, errors = parse_srcinfo(text)
664 print(json.dumps(parsed))
667 echo "${_srcinfo_json}" | jq -rc "${2}" | tr '\n' ' '
671 # AURからパッケージをビルドしてインストールします
672 # 現在1つのパッケージしか指定できません
673 install_aur_package() {
674 local _package="${1}"
677 if [[ ! -v wfa_cache_dir ]]; then
678 wfa_cache_dir="$(get_cache_dir)/wfa"
680 mkdir -p "${wfa_cache_dir}/archive"
681 mkdir -p "${wfa_cache_dir}/build/${_package}"
684 local _aur_json=$(curl -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name&arg=${_package}" | jq -r)
685 if (( "$(echo "${_aur_json}" | jq -r ".resultcount")" == 0 )); then
686 msg_error "Could not find all required packages:\n ${_package}"
690 local _found_packages="$(echo "${_aur_json}" | jq -r --tab '.results[].Name')"
691 #msg_debug "Found package: $(echo ${_found_packages} | tr '\n' ' ')"
693 if [[ -n "$(echo "${_found_packages}" | grep -x "${_package}" )" ]]; then
694 msg_debug "Select a package %s with an exact name match" "${_package}"
696 msg_error "No package with an exact name match was found."
701 msg_info "Download PKGBUILD of %s" "${_package}" #ここまで翻訳
702 _aur_json=$(echo "${_aur_json}" | jq -r ".results[] | select(.Name == \"${_package}\")" )
703 local _aur_snapshot_url="${aururl%/}$(echo "${_aur_json}" | jq -r ".URLPath")"
704 local _aur_version="$(echo "${_aur_json}" | jq -r ".Version")"
705 msg_debug "Get PKGBUILD from ${_aur_snapshot_url}"
707 local _pkgbuild_archive_path="${wfa_cache_dir}/archive/${_package}-${_aur_version}"
708 local _download_pkgbuild=true
709 if [[ -f "${_pkgbuild_archive_path}" ]]; then
710 msg_warn "PKGBUILD has already been downloaded."
711 msg_warn -n "Do you want to overwrite and download? [n] :"
713 if [[ "${noconfirm}" = true ]]; then
719 case "${_yes_or_no}" in
720 "y" | "Y" | "yes" | "Yes" | "YES" ) _download_pkgbuild=true ;;
721 * ) _download_pkgbuild=false ;;
724 if [[ "${_download_pkgbuild}" = true ]]; then
725 remove "${_pkgbuild_archive_path}"
726 curl -L -C - -f -o "${_pkgbuild_archive_path}" "${_aur_snapshot_url}"
730 msg_info "Unpacking the tarball of PKGBUILD ..."
731 tar -xv -f "${_pkgbuild_archive_path}" -C "${wfa_cache_dir}/build/" > /dev/null 2>&1
734 local _build_dir="${wfa_cache_dir}/build/${_package}"
735 if [[ ! -f "${_build_dir}/.SRCINFO" ]]; then
736 msg_warn ".SRCINFO was not found.\nGenerate it using makepkg."
739 "${makepkg_command}" --printsrcinfo > "${_build_dir}/.SRCINFO"
743 local _makedepends="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".makedepends[]?")"
744 local _depends="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".depends[]?")"
745 local _conflicts="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".conflicts[]?")"
746 msg_debug "makedepends: ${_makedepends}"
747 msg_debug "depends: ${_depends}"
748 msg_debug "conflicts: ${_conflicts}"
752 local _pkg _conflicts_found=false
753 for _pkg in ${_conflicts[@]}; do
754 if "${pacman_command}" -Qq "${_pkg}" > /dev/null 2>&1 ; then
755 _conflicts_found=true
756 msg_error "${_package} is colliding with ${_pkg}"
759 if "${pacman_command}" -Qq "${_package}" > /dev/null 2>&1 && [[ ! "$("${pacman_command}" -Qq "${_package}" 2> /dev/null)" = "${_package}" ]]; then
760 msg_error "${_package} is colliding with $("${pacman_command}" -Qq "${_package}")"
761 _conflicts_found=true
763 if [[ "${_conflicts_found}" = true ]]; then
764 msg_error "A conflict was found."
770 if [[ "${nodeps}" = false ]]; then
771 msg_info "Install dependent packages..."
772 local _force_aur="${force_aur}"
774 install_package "${_depends}"
775 force_aur="${_force_aur}"
781 if [[ -d "${_build_dir}/src" ]]; then
782 msg_info "Found ${_build_dir}/src"
783 msg_info "Packages to cleanBuild? [n] :"
786 if [[ "${noconfirm}" = true ]]; then
792 case "${_yes_or_no}" in
793 "y" | "Y" | "yes" | "Yes" | "YES" ) add_args makepkg "--clean" ;;
799 add_args "makepkg" "-sf"
802 "${makepkg_command}" "${makepkg_args}"
809 "${makepkg_command}" --printsrcinfo > "${_build_dir}/.SRCINFO"
811 local _pkgnames=($(get_srcinfo_data "${_build_dir}/.SRCINFO" ".packages | keys[]" | sed 's/ //g'))
812 local _pkgver="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".pkgver" | sed 's/ //g')"
813 local _pkgrel="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".pkgrel" | sed 's/ //g')"
814 local _arch_array=($(get_srcinfo_data "${_build_dir}/.SRCINFO" ".arch[]"))
816 if [[ "${_arch_array[*]}" = "any" ]]; then
822 source "${makepkg_config}"
825 local _pkgfilelist=()
826 for _pkgname in ${_pkgnames[@]}; do
827 _pkgfilelist+=("${_build_dir}/${_pkgname}-${_pkgver}-${_pkgrel}-${_arch}${_PKGEXT}")
831 run_pacman -U --noconfirm ${_pkgfilelist[@]}
835 search_aur_package() {
836 local _package="${1}"
837 local _aur_json=$(curl -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name-desc&arg=${_package}" | jq -r )
838 local _found_result_count="$(echo "${_aur_json}" | jq -r ".resultcount")"
839 if (( "${_found_result_count}" == 0 )); then
840 msg_error "Could not find all required packages:\n ${_package}"
843 _aur_json=$(echo "${_aur_json}" | jq -r ".results[]")
847 local _found_pkgname=($(echo "${_aur_json}" | jq -r ".Name" ))
852 local _found_package __pkgver __popularity __vote __pkgdesc
853 for _found_package in ${_found_pkgname[@]}; do
854 _found_json="$(echo ${_aur_json} | jq "select(.Name == \"${_found_package}\")")"
855 __pkgver="$(echo "${_found_json}" | jq -r ".Version" )"
856 __popularity="$(echo "${_found_json}" | jq -r ".Popularity" )"
857 __vote="$(echo "${_found_json}" | jq -r ".NumVotes" )"
858 __pkgdesc="$(echo "${_found_json}" | jq -r ".Description" )"
860 echo "aur/${_found_package} ${__pkgver} (+${__vote} ${__popularity})"
862 unset __pkgver __popularity __vote __pkgdesc _found_json
867 operation_version() {
868 # Pyalpmからlibalpmの値を取得
869 # 参考: https://pyalpm.readthedocs.io/en/latest/pyalpm/pyalpm.html
870 local _libalpm_version="$(python3 -c 'import pyalpm; print(pyalpm.alpmversion())')"
871 local _pacman_version="$("${pacman_command}" -Q pacman | cut -d ' ' -f 2)"
872 echo "wfa v${wfa_version} - pacman v${_pacman_version} - libalpm v${_libalpm_version}"
876 run_pacman ${pacman_args} "${specified_packages[@]}"
879 # Usage: install_package <package1> <package2>...
882 for _package in ${@}; do
883 if ! check_installed_package "${_package}"; then
884 if ! check_aur_package "${_package}"; then
885 # 公式パッケージなのでpacmanでそのままインストール
886 run_pacman ${pacman_args} "${_package}"
889 install_aur_package "${_package}"
890 #msg_error "Getting the AUR package has not been implemented yet.
899 if [[ "${sync_search}" = true ]]; then
900 for _package in ${specified_packages[@]}; do
901 search_aur_package "${_package}"
903 "${pacman_command}" ${pacman_args} ${specified_packages[@]}
905 for _package in ${specified_packages[@]}; do
906 if ! check_aur_package "${_package}" && [[ "${force_aur}" = false ]]; then
907 # 公式パッケージなのでpacmanでそのままインストール
908 run_pacman ${pacman_args} "${_package}"
911 install_aur_package "${_package}"
912 #msg_error "Getting the AUR package has not been implemented yet."
922 _opt_short="QRShVdb:ays"
923 _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"
925 OPT=$(getopt -o ${_opt_short} -l ${_opt_long} -- ${ARGUMENT})
926 [[ ${?} != 0 ]] && exit 1
927 unset _opt_short _opt_long
930 msg_debug "Argument: ${OPT}"
935 set_operation "query"
939 set_operation "remove"
947 set_operation "version"
966 msg_debug "Assume targets are from the AUR"
971 add_args pacman "--debug"
976 add_args pacman "--nodeps"
980 add_args pacman "--dbpath '${2}'"
984 option_y_count=$(( option_y_count + 1 ))
988 add_args pacman "--search"
997 add_args pacman "--noconfirm"
1002 pacman_config="${2}"
1003 add_args pacman "--config \"${2}\""
1007 makepkg_command="${2}"
1015 pacman_command="${2}"
1027 if [[ "${nomakepkgconf}" = false ]]; then
1028 makepkg_config="${2}"
1030 msg_warn "--nomakepkgconf is specified.\n--makepkgconf has been ignored."
1035 makepkg_config="/etc/makepkg.conf"
1063 specified_packages=(${@})
1065 # Run database update
1066 if (( "${option_y_count}" == 1 )); then
1068 elif (( "${option_y_count}" >= 2 )); then
1072 case "${operation}" in
1086 msg_error "Undefined operation."