OSDN Git Service

e0af626d3c8a8db7fa57078dda3c6e7ff5f1f9f4
[alterlinux/wfa.git] / wfa
1 #!/usr/bin/env bash
2 #
3 # 1. Author info
4 #
5 # Yamada Hayao
6 # Twitter: @Hayao0819
7 # Email  : hayao@fascode.net
8 #
9 # (c) 2019-2020 Fascode Network.
10 #
11 # 2. Overview
12
13 # Wfa is a multilingual AUR helper written in bash that is being developed to replace yaourt
14 #
15 # 3. License
16
17 #        DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
18 #                    Version 2, December 2004 
19 #
20 # Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> 
21 #
22 # Everyone is permitted to copy and distribute verbatim or modified 
23 # copies of this license document, and changing it is allowed as long 
24 # as the name is changed. 
25 #
26 #            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
27 #   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 
28 #
29 #  0. You just DO WHAT THE FUCK YOU WANT TO.
30 #
31 #
32
33 set -eu
34
35
36 ######################################################################################
37 # ここから翻訳データ
38 # 翻訳はBashの連想配列を使用して行います
39 # 連想配列名は echo "${LANG}" | cut -d "." -f 1 の実行結果の値です
40
41
42 # 日本語
43 declare -A ja_JP=(
44     ["Undefined operation"]="未定義のオペレーションです"
45     ["only one operation may be used at a time"]="一度に使用できるオペレーションは1つだけです"
46     ["Failed to set the argument of %s"]="%sの引数の設定に失敗しました"
47     ["Setting that command is not currently supported"]="そのコマンドの設定は現在サポートされていません"
48     ["Searching in AUR ..."]="AUR内を検索しています..."
49     ["No package with an exact name match was found"]="完全に一致する名前のパッケージが見つかりませんでした"
50     ["Select a package %s with an exact name match"]="名前が完全に一致するパッケージ %s を選択します"
51     ["Download PKGBUILD of %s"]="%s のPKGBUILDをダウンロード"
52     ["Get PKGBUILD from %s"]="%sからPKGBUILDを取得します"
53     ["PKGBUILD has already been downloaded"]="PKGBUILDは既にダウンロードされています"
54     ["Do you want to overwrite and download? [n] :"]="上書きダウンロードしますか? [n] :"
55     ["Unpacking the tarball of PKGBUILD ..."]="PKGBUILDを展開しています ..."
56     [".SRCINFO was not found.\nGenerating it using makepkg"]=".SCRINFOが見つかりませんでした。makepkgを使用して生成しています"
57     ["Conflict(s) was found"]="衝突が見つかりました"
58     ["Install dependent packages..."]="依存パッケージをインストールします..."
59     ["Found %s"]="%s を見つけました"
60     ["Packages to cleanBuild? [n] :"]="パッケージをクリーンビルドしますか? [n] :"
61     ["Could not find all required packages: %s"]="必要なすべてのパッケージが見つかりませんでした: %s"
62     ["This is a feature that has not been implemented yet"]="まだ実装されていない機能です"
63     ["Package not found on AUR: %s"]="パッケージがAUR上から見つかりませんでした: "
64     ["There is no aurvote"]="aurvote が見つかりませんでした"
65     ["Please install with %s"]="%s でインストールしてください"
66     ["Voted for %s"]="%s に投票しました"
67     ["Unvoted for %s"]="%s の投票を解除しました"
68     ["Help for this operation is not implemented"]="このオペレーションのヘルプは実装されていません"
69
70     ["(Orphaned)"]="(メンテナ不在)"
71     ["[Installed]"]="[インストール済み]"
72     ["This is a feature that has not been implemented yet"]="まだ実装されていない機能です"
73 )
74
75
76 # English
77 # 翻訳データが存在しない場合はデフォルトメッセージ(英語)が出力されます
78 # そのため英語の翻訳データは必要ありません
79 declare -A en_US=()
80 declare -A C=()
81
82 ######################################################################################
83 # ここからデフォルト設定の定義
84
85 #-- wfa configs --#
86 wfa_version="0.1"
87 wfa_name="WFA"
88 wfa_command="wfa"
89 wfa_path="$(dirname "$(realpath "${0}")")/$(basename "${0}")"
90
91 #-- options (int) --#
92 option_y_count=0
93 sync_clean_count=0
94
95 #-- options (str) --#
96 arch="$(uname -m)"
97 aururl="https://aur.archlinux.org/"
98 operation="none"
99
100 #-- options (bool) --#
101 bash_debug=false
102 debug=false
103 force_aur=false
104 msgdebug=false
105 nocolor=false
106 noconfirm=false
107 nodeps=false
108 nomakepkgconf=false
109 sync_search=false
110 sync_upgrade=false
111 quiet=false
112
113 #-- makepkg --#
114 # 実行ファイル
115 makepkg_command="/usr/bin/makepkg" 
116 # 設定ファイル
117 makepkg_config="/etc/makepkg.conf"
118 # 引数
119 makepkg_args=""
120
121 #-- pacman --#
122 # 実行ファイル
123 pacman_command="/usr/bin/pacman"
124 # 設定ファイル
125 pacman_config="/etc/pacman.conf"
126 # 引数
127 pacman_args=""
128
129 #-- git --#
130 # 実行ファイル
131 git_command="/usr/bin/git"
132 # 引数
133 git_args=""
134
135 #-- gpg --#
136 # 実行ファイル
137 gpg_command="/usr/bin/gpg"
138 # 引数
139 gpg_args=""
140
141 #-- sudo --#
142 # 実行ファイル
143 sudo_command="/usr/bin/sudo"
144 # 引数
145 sudo_args=""
146
147 #-- curl --#
148 # 実行ファイル
149 curl_command="/usr/bin/curl"
150 # 引数
151 curl_args=""
152
153
154 ######################################################################################
155 # ここからメッセージ関連の関数定義
156
157
158 # メッセージ出力の制御
159 # https://github.com/FascodeNet/alterlinux/blob/dev/tools/msg.sh の変数名にアンダーバーを追加し関数化
160 msg() {
161     local OPTIND OPTARG arg
162
163     local _appname="msg.sh"
164     local _bash_debug=false
165     local _nocolor=false
166     local _echo_opts=""
167     local _message=""
168     local _msg_type="info"
169     local _msg_label=""
170     local _label_space="7"
171     local _adjust_chr=" "
172     local _customized_label=false
173     local _customized_label_color=false
174     local _nolabel=false
175     local _noappname=false
176     local _noadjust=false
177     local _output="stdout"
178
179     _help() {
180         echo "usage msg [option] [type] [message]"
181         echo
182         echo "Display a message with a colored app name and message type label"
183         echo
184         echo " General type:"
185         echo "    info                      General message"
186         echo "    warn                      Warning message"
187         echo "    error                     Error message"
188         echo "    debug                     Debug message"
189         echo
190         echo " General options:"
191         echo "    -a [name]                 Specify the app name"
192         echo "    -c [character]            Specify the character to adjust the label"
193         echo "    -l [label]                Specify the label."
194         echo "    -n | --nocolor            No output colored output"
195         echo "    -o [option]               Specify echo options"
196         echo "    -r [color]                Specify the color of label"
197         echo "    -s [number]               Specifies the label space."
198         echo "    -x | --bash-debug         Enables output bash debugging"
199         echo "    -h | --help               This help message"
200         echo
201         echo "         --nolabel            Do not output label"
202         echo "         --noappname          Do not output app name"
203         echo "         --noadjust           Do not adjust the width of the label"
204     }
205
206     while getopts "a:c:l:no:r:s:xh-:" arg; do
207         case ${arg} in
208                 a) 
209                     _appname="${OPTARG}"
210                     ;;
211                 c) 
212                     _adjust_chr="${OPTARG}"
213                     ;;
214                 l) 
215                     _customized_label=true
216                     _msg_label="${OPTARG}"
217                     ;;
218                 n)
219                     _nocolor=true
220                     ;;
221                 o)
222                     _echo_opts="${OPTARG}"
223                     ;;
224                 r)
225                     _customized_label_color=true
226                     case ${OPTARG} in
227                         "black")
228                             _labelcolor="30"
229                             ;;
230                         "red")
231                             _labelcolor="31"
232                             ;;
233                         "green")
234                             _labelcolor="32"
235                             ;;
236                         "yellow")
237                             _labelcolor="33"
238                             ;;
239                         "blue")
240                             _labelcolor="34"
241                             ;;
242                         "magenta")
243                             _labelcolor="35"
244                             ;;
245                         "cyan")
246                             _labelcolor="36"
247                             ;;
248                         "white")
249                             _labelcolor="37"
250                             ;;
251                         *)
252                             return 1
253                             ;;
254                     esac
255                     ;;
256                 s)
257                     _label_space="${OPTARG}"
258                     ;;
259                 x)
260                     _bash_debug=true
261                     set -xv
262                     ;;
263                 h)
264                     _help
265                     shift 1
266                     exit 0
267                     ;;
268                 -)
269                     case "${OPTARG}" in
270                         "nocolor")
271                             _nocolor=true
272                             ;;
273                         "bash-debug")
274                             _bash_debug=true
275                             set -xv
276                             ;;
277                         "help") 
278                             _help
279                             exit 0
280                             ;;
281                         "nolabel")
282                             _nolabel=true
283                             ;;
284                         "noappname")
285                             _noappname=true
286                             ;;
287                         "noadjust")
288                             _noadjust=true 
289                             ;;
290                         *)
291                             _help
292                             exit 1
293                             ;;
294                     esac
295         esac
296     done
297
298     shift $((OPTIND - 1))
299
300     # Color echo
301     #
302     # Text Color
303     # 30 => Black
304     # 31 => Red
305     # 32 => Green
306     # 33 => Yellow
307     # 34 => Blue
308     # 35 => Magenta
309     # 36 => Cyan
310     # 37 => White
311     #
312     # Background color
313     # 40 => Black
314     # 41 => Red
315     # 42 => Green
316     # 43 => Yellow
317     # 44 => Blue
318     # 45 => Magenta
319     # 46 => Cyan
320     # 47 => White
321     #
322     # Text decoration
323     # You can specify multiple decorations with ;.
324     # 0 => All attributs off (ノーマル)
325     # 1 => Bold on (太字)
326     # 4 => Underscore (下線)
327     # 5 => Blink on (点滅)
328     # 7 => Reverse video on (色反転)
329     # 8 => Concealed on
330
331     case ${1} in
332         "info")
333             _msg_type="type"
334             _output="stdout"
335             [[ "${_customized_label_color}" = false ]] && _labelcolor="32"
336             [[ "${_customized_label}"       = false ]] && _msg_label="Info"
337             shift 1
338             ;;
339         "warn")
340             _msg_type="warn"
341             _output="stdout"
342             [[ "${_customized_label_color}" = false ]] && _labelcolor="33"
343             [[ "${_customized_label}"       = false ]] && _msg_label="Warning"
344             shift 1
345             ;;
346         "debug")
347             _msg_type="debug"
348             _output="stdout"
349             [[ "${_customized_label_color}" = false ]] && _labelcolor="35"
350             [[ "${_customized_label}"       = false ]] && _msg_label="Debug"
351             shift 1
352             ;;
353         "error")
354             _msg_type="error"
355             _output="stderr"
356             [[ "${_customized_label_color}" = false ]] && _labelcolor="31"
357             [[ "${_customized_label}"       = false ]] && _msg_label="Error"
358             shift 1
359             ;;
360         "")
361             echo "Please specify the message type" >&2
362             exit 1
363             ;;
364         *)
365             echo "Unknown message type" >&2
366             exit 1
367             ;;
368     esac
369
370     _word_count="${#_msg_label}"
371     _message="${@}"
372
373     echo_type() {
374         local __time
375         if [[ "${_nolabel}" = false ]]; then
376             if [[ "${_noadjust}" = false ]]; then
377                 for __time in $( seq 1 $(( ${_label_space} - ${_word_count})) ); do
378                     echo -ne "${_adjust_chr}"
379                 done
380             fi
381             if [[ "${_nocolor}" = false ]]; then
382                 echo -ne "\e[$([[ -v _backcolor ]] && echo -n "${_backcolor}"; [[ -v _labelcolor ]] && echo -n ";${_labelcolor}"; [[ -v _decotypes ]] && echo -n ";${_decotypes}")m${_msg_label}\e[m "
383             else
384                 echo -ne "${_msg_label} "
385             fi
386         fi
387     }
388
389     echo_appname() {
390         if [[ "${_noappname}" = false ]]; then
391             if [[ "${_nocolor}" = false ]]; then
392                 echo -ne "\e[36m[${_appname}]\e[m "
393             else
394                 echo -ne "[${_appname}] "
395             fi
396         fi
397     }
398
399     for _count in $(seq "1" "$(echo -ne "${_message}\n" | wc -l)"); do
400         _echo_message=$(echo -ne "${_message}\n" |head -n "${_count}" | tail -n 1 )
401         _full_message="$(echo_appname)$(echo_type)${_echo_message}"
402         case "${_output}" in
403             "stdout")
404                 echo ${_echo_opts} "${_full_message}" >&1
405                 ;;
406             "stderr")
407                 echo ${_echo_opts} "${_full_message}" >&2
408                 ;;
409             *)
410                 echo ${_echo_opts} "${_full_message}" > ${_output}
411                 ;;
412         esac
413     done
414 }
415
416 # テキストの翻訳
417 #set -xv
418 translate() {
419     local _msg_translate
420     _msg_translate() {
421         local _get_text
422         local _locale="$(echo "${LANG}" | cut -d "." -f 1)"
423
424         _get_text() {
425             set +eu
426             local _translated_text="$(eval echo '$'{${_locale}[\"${*}\"]})"
427             set -eu
428             if [[ -z "${_translated_text}" ]]; then
429                 if [[ ! "${_locale}" = "C" ]] && [[ ! "${_locale}" = "en_US" ]]; then
430                     echo "$(text -nc cyan "[WFA]") $(text -nc yellow "Warning") No translation data was found" 1>&2
431                 fi
432                 echo "${*}"
433             else
434                 echo "${_translated_text}"
435             fi
436         }
437
438         local _text _fulltext=() _main
439
440         if declare -p "${_locale}" 2> /dev/null 1>/dev/null; then
441             _main="$(_get_text ${1})"
442         else
443             _main="${1}"
444         fi
445         shift 1
446         echo "$(printf "${_main}" "${@}")"
447     }
448     _msg_translate "${@}"
449 }
450
451
452
453 # Show an INFO message
454 # $1: message string
455 msg_info() {
456     if [[ "${msgdebug}" = false ]]; then
457         set +xv
458     fi
459     local _msg_opts="-a ${wfa_name}"
460     if [[ "${1}" = "-n" ]]; then
461         _msg_opts="${_msg_opts} -o -n"
462         shift 1
463     fi
464     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
465     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
466     msg ${_msg_opts} info "$(translate "${@}")"
467     if [[ "${bash_debug}" = true ]]; then
468         set -xv
469     fi
470 }
471
472 # Show an Warning message
473 # $1: message string
474 msg_warn() {
475     if [[ "${msgdebug}" = false ]]; then
476         set +xv
477     fi
478     local _msg_opts="-a ${wfa_name}"
479     if [[ "${1}" = "-n" ]]; then
480         _msg_opts="${_msg_opts} -o -n"
481         shift 1
482     fi
483     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
484     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
485     msg ${_msg_opts} warn "$(translate "${@}")"
486     if [[ "${bash_debug}" = true ]]; then
487         set -xv
488     fi
489 }
490
491 # Show an debug message
492 # $1: message string
493 msg_debug() {
494     if [[ "${msgdebug}" = false ]]; then
495         set +xv
496     fi
497     if [[ "${debug}" = true ]]; then
498         local _msg_opts="-a ${wfa_name}"
499         if [[ "${1}" = "-n" ]]; then
500             _msg_opts="${_msg_opts} -o -n"
501             shift 1
502         fi
503         [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
504         [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
505         msg ${_msg_opts} debug "$(translate "${@}")"
506     fi
507     if [[ "${bash_debug}" = true ]]; then
508         set -xv
509     fi
510 }
511
512 # Show an ERROR message then exit with status
513 # $1: message string
514 # $2: exit code number (with 0 does not exit)
515 msg_error() {
516     if [[ "${msgdebug}" = false ]]; then
517         set +xv
518     fi
519     local _msg_opts="-a ${wfa_name}"
520     if [[ "${1}" = "-n" ]]; then
521         _msg_opts="${_msg_opts} -o -n"
522         shift 1
523     fi
524     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
525     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
526     msg ${_msg_opts} error "$(translate "${@}")"
527     if [[ "${bash_debug}" = true ]]; then
528         set -xv
529     fi
530 }
531
532 text() {
533     local OPTIND OPTARG arg _textcolor _decotypes=() _message _notranslate=false
534     while getopts "c:bn" arg; do
535         case ${arg} in
536             c)
537                 case "${OPTARG}" in
538                     "black")
539                         _textcolor="30"
540                         ;;
541                     "red")
542                         _textcolor="31"
543                         ;;
544                     "green")
545                         _textcolor="32"
546                         ;;
547                     "yellow")
548                         _textcolor="33"
549                         ;;
550                     "blue")
551                         _textcolor="34"
552                         ;;
553                     "magenta")
554                         _textcolor="35"
555                         ;;
556                     "cyan")
557                         _textcolor="36"
558                         ;;
559                     "white")
560                         _textcolor="37"
561                         ;;
562                     *)
563                         return 1
564                         ;;
565                 esac
566                 ;;
567             b)
568                 _decotypes+=(1)
569                 ;;
570             n)
571                 _notranslate=true
572                 ;;
573         esac
574     done
575     shift $((OPTIND - 1))
576
577     _message="${@}"
578     if [[ "${_notranslate}" = false ]]; then
579         _message="$(translate "${@}")"
580     fi
581     if [[ "${nocolor}" = true ]]; then
582         echo -ne "${@}"
583     else
584         echo -ne "\e[$([[ -v _textcolor ]] && echo -n ";${_textcolor}"; [[ -v _decotypes ]] && echo -n ";${_decotypes}")m${_message}\e[m"
585     fi
586 }
587
588 ######################################################################################
589 # ここから実際の処理開始
590 # ここから下のメッセージは翻訳可能です
591
592 # rm helper
593 # Delete the file if it exists.
594 # For directories, rm -rf is used.
595 # If the file does not exist, skip it.
596 # remove <file> <file> ...
597 remove() {
598     local _list=($(echo "$@")) _file
599     for _file in "${_list[@]}"; do
600         msg_debug "Removing ${_file}"
601         if [[ -f "${_file}" ]]; then    
602             rm -f "${_file}"
603         elif [[ -d "${_file}" ]]; then
604             rm -rf "${_file}"
605         fi
606     done
607 }
608
609 usage (){
610     local _pacman_help=false
611
612     local _wfa_usage
613     _wfa_usage() {
614         echo "Usage:"
615         echo "${wfa_command}"
616         echo "${wfa_command} <operation> [...]"
617         echo
618         echo "operations:"
619         echo "    ${wfa_command} {-h --help}"
620         echo "    ${wfa_command} {-A --vote}"
621         echo "    ${wfa_command} {-V --version}"
622        #echo "    ${wfa_command} {-D --database}    <options> <package(s)>"
623        #echo "    ${wfa_command} {-F --files}       [options] [package(s)]"
624         echo "    ${wfa_command} {-Q --query}       [options] [package(s)]"
625         echo "    ${wfa_command} {-R --remove}      [options] <package(s)>"
626         echo "    ${wfa_command} {-S --sync}        [options] [package(s)]"
627        #echo "    ${wfa_command} {-T --deptest}     [options] [package(s)]"
628        #echo "    ${wfa_command} {-U --upgrade}     [options] <file(s)>"
629        #echo
630        #echo "New operations:"
631        #echo "    ${wfa_command} {-P --show}        [options]"
632        #echo "    ${wfa_command} {-G --getpkgbuild} [package(s)]"
633         echo
634         echo "New options:"
635         echo "       --repo             Assume targets are from the repositories"
636         echo "    -a --aur              Assume targets are from the AUR"
637         echo
638         echo "Permanent configuration options:"
639         echo "    --aururl      <url>   Set an alternative AUR URL"
640         echo "    --makepkg     <file>  makepkg command to use"
641         echo "    --mflags      <flags> Pass arguments to makepkg"
642         echo "    --pacman      <file>  pacman command to use"
643         echo "    --git         <file>  git command to use"
644         echo "    --gitflags    <flags> Pass arguments to git"
645         echo "    --gpg         <file>  gpg command to use"
646         echo "    --gpgflags    <flags> Pass arguments to gpg"
647         echo "    --config      <file>  pacman.conf file to use"
648         echo "    --makepkgconf <file>  makepkg.conf file to use"
649         echo "    --nomakepkgconf       Use the default makepkg.conf"
650         echo
651         echo "wfa specific options:"
652         echo "    -c --clean            Remove unneeded dependencies"
653     }
654
655     local _wfa_usage_sync
656     _wfa_usage_sync() {
657         echo "usage:  ${wfa_command} {-S --sync} [options] [package(s)]"
658         echo "options:"
659         echo "  -b, --dbpath <path>  set an alternate database location"
660         echo "  -c, --clean          remove old packages from cache directory (-cc for all)"
661         echo "  -d, --nodeps         skip dependency version checks (-dd to skip all checks)"
662         echo "  -s, --search <regex> search remote repositories for matching strings"
663         echo "  -u, --sysupgrade     upgrade installed packages (-uu enables downgrades)"
664         echo "  -y, --refresh        download fresh package databases from the server"
665         echo "                       (-yy to force a refresh even if up to date)"
666         echo "      --arch <arch>    set an alternate architecture"
667         echo "      --color <when>   colorize the output"
668         echo "      --config <path>  set an alternate configuration file"
669         echo "      --confirm        always ask for confirmation"
670         echo "      --debug          display debug messages"
671         echo "      --disable-download-timeout"
672         echo "                       use relaxed timeouts for download"
673         echo "      --noconfirm      do not ask for any confirmation"
674
675     }
676
677     if [[ "${operation}" = "none" ]]; then
678         _wfa_usage
679     elif [[ "${_pacman_help}" = true ]]; then
680         "${pacman_command}" -h --${operation}
681     elif [[ "$(type -t "_wfa_usage_${operation}" )" = "function" ]]; then
682         _wfa_usage_${operation}
683     else
684         msg_error "Help for this operation is not implemented"
685         exit 1
686     fi
687 }
688
689 set_operation() {
690     if [[ "${operation}" = "none" ]]; then
691         operation="${1}"
692         add_args pacman "--${operation}"
693     else
694         msg_error "only one operation may be used at a time"
695         exit 1
696     fi
697 }
698
699 run_sudo() {
700     if (( ${UID} == 0 )); then
701         ${@}
702     else
703         sudo ${@}
704     fi
705 }
706
707 run_pacman() {
708     run_sudo "${pacman_command}" ${@}
709 }
710
711 wfa() {
712     "${wfa_path}" ${@}
713 }
714
715 # pacmanの引数を追加する
716 # https://github.com/FascodeNet/aptpac/blob/master/aptpac のADD_OPTION関数を参考
717 # Usage: add_args [pacman/makepkg/git/gpg/sudo/curl] <args1> <args2>...
718 add_args() {
719     local _target="${1}"
720     local _args_array
721     shift 1
722
723     case "${_target}" in
724         "makepkg")
725             _args_array=(${makepkg_args})
726             _args_array+=(${@})
727             makepkg_args=${_args_array[@]}
728             msg_debug "makepkg ARGS: ${makepkg_args}"
729             ;;
730
731         "pacman")
732             _args_array=(${pacman_args})
733             _args_array+=(${@})
734             pacman_args=${_args_array[@]}
735             msg_debug "pacman ARGS: ${pacman_args}"
736             ;;
737         "git")
738             _args_array=(${mpg_args})
739             _args_array+=(${@})
740             git_args=${_args_array[@]}
741             msg_debug "git ARGS: ${git_args}"
742             ;;
743         "gpg")
744             _args_array=(${gpg_args})
745             _args_array+=(${@})
746             gpg_args=${_args_array[@]}
747             msg_debug "gpg ARGS: ${gpg_args}"
748             ;;
749         "sudo")
750             _args_array=(${sudo_args})
751             _args_array+=(${@})
752             sudo_args=${_args_array[@]}
753             msg_debug "sudo ARGS: ${sudo_args}"
754             ;;
755         "curl")
756             _args_array=(${curl_args})
757             _args_array+="${@}"
758             curl_args=${_args_array[@]}
759             msg_debug "curl ARGS: ${curl_args}"
760             ;;
761         *)
762             msg_error "Failed to set the argument of %s" "${_target}"
763             msg_error "Setting that command is not currently supported"
764             exit 1
765             ;;
766     esac
767 }
768
769 # 引数で指定されたパッケージがAUR以外の場所に存在しない場合にのみ正常終了します(AURのパッケージの場合に正常終了)
770 check_aur_package() {
771     local _package="${1}"
772     # 参考: https://qiita.com/Hayao0819/items/a8740a17301fafa2fdab
773     if [[ -z "$(pacman -Ssq "${_package}" 2>/dev/null | grep -o ".*${_package}$")" ]]; then
774         #AUR以外のリポジトリに存在しない
775         return 0
776     else
777         return 1
778     fi
779 }
780
781
782 # 引数で指定されたパッケージが既にインストールされている場合は正常終了します。
783 check_installed_package() {
784     local _package="${1}"
785     if "${pacman_command}" -Qq "${_package}" > /dev/null 2>&1; then
786         return 0
787     else
788         return 1
789     fi
790 }
791
792 # ~/.cacheに相当するディレクトリを返します
793 get_cache_dir() {
794     local _user_config_dir _cache_dir
795     if [[ -v XDG_CONFIG_HOME ]]; then
796         _user_config_dir="${XDG_CONFIG_HOME}"
797     else
798         _use_config_dir="${HOME}/.config"
799     fi
800     if [[ -f "${_use_config_dir}/user-dirs.dirs" ]]; then
801         source "${_use_config_dir}/user-dirs.dirs"
802     fi
803     if [[ -v XDG_CACHE_HOME ]]; then
804         _cache_dir="${XDG_CACHE_HOME}"
805     else
806         _cache_dir="${HOME}/.cache"
807     fi
808     echo -n "${_cache_dir}"
809 }
810
811 # Usage: get_srcinfo_data <path> <var>
812 # 参考: https://qiita.com/withelmo/items/b0e1ffba639dd3ae18c0
813 get_srcinfo_data() {
814     local _srcinfo="${1}" _ver="${2}"
815     local _srcinfo_json=$(python << EOF
816 from srcinfo.parse import parse_srcinfo; import json
817 text = """
818 $(cat ${1})
819 """
820 parsed, errors = parse_srcinfo(text)
821 print(json.dumps(parsed))
822 EOF
823 )
824     echo "${_srcinfo_json}" | jq -rc "${2}" | tr '\n' ' '
825 }
826
827
828 # AURからパッケージをビルドしてインストールします
829 # 現在1つのパッケージしか指定できません
830 install_aur_package() {
831     local _package="${1}"
832
833     # Create cache dir
834     if [[ ! -v wfa_cache_dir ]]; then
835         wfa_cache_dir="$(get_cache_dir)/wfa"
836     fi
837     mkdir -p "${wfa_cache_dir}/archive"
838     mkdir -p "${wfa_cache_dir}/build/${_package}"
839
840     # AurJsonから値を取得
841     msg_info "Searching in AUR ..."
842     local _aur_json=$("${curl_command}" ${curl_args} -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name&arg=${_package}" | jq -r)
843     if (( "$(echo "${_aur_json}" | jq -r ".resultcount")" == 0 )); then
844         msg_error "Could not find all required packages: %s" "${_package}"
845         exit 1
846     fi
847
848     local _found_packages="$(echo "${_aur_json}" | jq -r --tab '.results[].Name')"
849     #msg_debug "Found package: $(echo ${_found_packages} | tr '\n' ' ')"
850
851     if [[ -n "$(echo "${_found_packages}" | grep -x "${_package}" )" ]]; then
852         msg_debug "Select a package %s with an exact name match" "${_package}"
853     else
854         msg_error "No package with an exact name match was found"
855         exit 1
856     fi
857
858     # PKGBUILDをダウンロード
859     msg_info "Download PKGBUILD of %s" "${_package}"
860     _aur_json=$(echo "${_aur_json}" | jq -r ".results[] | select(.Name == \"${_package}\")" )
861     local _aur_snapshot_url="${aururl%/}$(echo "${_aur_json}" | jq -r ".URLPath")"
862     local _aur_version="$(echo "${_aur_json}" | jq -r ".Version")"
863     msg_debug "Get PKGBUILD from %s" "${_aur_snapshot_url}"
864
865     local _pkgbuild_archive_path="${wfa_cache_dir}/archive/${_package}-${_aur_version}"
866     local _download_pkgbuild=true
867     if [[ -f "${_pkgbuild_archive_path}" ]]; then
868         msg_warn "PKGBUILD has already been downloaded"
869         msg_warn -n "Do you want to overwrite and download? [n] :"
870         local _yes_or_no
871         if [[ "${noconfirm}" = true ]]; then
872             echo
873             _yes_or_no="No"
874         else
875             read _yes_or_no
876         fi
877         case "${_yes_or_no}" in
878             "y" | "Y" | "yes" | "Yes" | "YES" ) _download_pkgbuild=true  ;;
879             *                                 ) _download_pkgbuild=false ;;
880         esac
881     fi
882     if [[ "${_download_pkgbuild}" = true ]]; then
883         remove "${_pkgbuild_archive_path}"
884         "${curl_command}"  ${curl_args} -L -C - -f -o "${_pkgbuild_archive_path}" "${_aur_snapshot_url}"
885     fi
886
887     # PKGBUILDを展開
888     msg_info "Unpacking the tarball of PKGBUILD ..."
889     tar -xv -f "${_pkgbuild_archive_path}" -C "${wfa_cache_dir}/build/" > /dev/null 2>&1
890
891     # .SRCINFOを解析
892     local _build_dir="${wfa_cache_dir}/build/${_package}"
893     if [[ ! -f "${_build_dir}/.SRCINFO" ]]; then
894         msg_warn ".SRCINFO was not found.\nGenerating it using makepkg"
895         (
896             cd "${_build_dir}"
897             "${makepkg_command}" --printsrcinfo > "${_build_dir}/.SRCINFO"
898         )
899     fi
900
901     local _makedepends="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".makedepends[]?")"
902     local _depends="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".depends[]?")"
903     local _conflicts="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".conflicts[]?")"
904     msg_debug "makedepends: %s" "${_makedepends}"
905     msg_debug "depends: %s" "${_depends}"
906     msg_debug "conflicts: %s " "${_conflicts}"
907
908
909     # 衝突を確認
910     local _pkg _conflicts_found=false
911     for _pkg in ${_conflicts[@]}; do
912         if "${pacman_command}" -Qq "${_pkg}" > /dev/null 2>&1 ; then
913             _conflicts_found=true
914             msg_error "${_package} is colliding with ${_pkg}"
915         fi
916     done
917     if "${pacman_command}" -Qq "${_package}" > /dev/null 2>&1 &&  [[ ! "$("${pacman_command}" -Qq "${_package}" 2> /dev/null)" = "${_package}" ]]; then
918         msg_error "${_package} is colliding with $("${pacman_command}" -Qq "${_package}")"
919         _conflicts_found=true
920     fi
921     if [[ "${_conflicts_found}" = true ]]; then
922         msg_error "Conflict(s) was found"
923         exit 1
924     fi
925
926
927     # 依存パッケージをインストール
928     if [[ "${nodeps}" = false ]]; then
929         msg_info "Install dependent packages..."
930         local _force_aur="${force_aur}"
931         force_aur=false
932         install_package "${_depends}"
933         force_aur="${_force_aur}"
934         unset _force_aur
935     fi
936
937     # ビルド準備
938     # srcdirの確認
939     if [[ -d "${_build_dir}/src" ]]; then
940         msg_info "Found %s" "${_build_dir}/src"
941         msg_info -n "Packages to cleanBuild? [n] :"
942         local _yes_or_no
943         unset _yes_or_no
944         if [[ "${noconfirm}" = true ]]; then
945             echo
946             _yes_or_no="No"
947         else
948             read _yes_or_no
949         fi
950         case "${_yes_or_no}" in
951             "y" | "Y" | "yes" | "Yes" | "YES" ) add_args makepkg "--clean" ;;
952         esac
953     fi
954
955
956     # ビルド
957     add_args "makepkg" "-sf"
958     (
959         cd "${_build_dir}"
960         "${makepkg_command}" "${makepkg_args}"
961     )
962
963
964     # ビルド後のパッケージ一覧を生成
965     (
966         cd "${_build_dir}"
967         "${makepkg_command}" --printsrcinfo > "${_build_dir}/.SRCINFO"
968     )
969     local _pkgnames=($(get_srcinfo_data "${_build_dir}/.SRCINFO" ".packages | keys[]"))
970     local _pkgver="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".pkgver" | sed 's/ //g')"
971     local _pkgrel="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".pkgrel" | sed 's/ //g')"
972     local _arch_array=($(get_srcinfo_data "${_build_dir}/.SRCINFO" ".arch[]"))
973     local _arch _pkgname
974     if [[ "${_arch_array[*]}" = "any" ]]; then
975         _arch="any"
976     else
977         _arch="${arch}"
978     fi
979     local _PKGEXT=$(
980         source "${makepkg_config}"
981         echo "${PKGEXT}"
982     )
983     local _pkgfilelist=()
984     for _pkgname in ${_pkgnames[@]}; do
985         _pkgfilelist+=("${_build_dir}/${_pkgname}-${_pkgver}-${_pkgrel}-${_arch}${_PKGEXT}")
986     done
987
988     # インストール
989     run_pacman -U --noconfirm ${_pkgfilelist[@]}
990 }
991
992 # AURのパッケージを検索
993 search_aur_package() {
994     local _package="${1}"
995     #msg_info "Searching in AUR ..."
996     local _aur_json=$("${curl_command}" ${curl_args} -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name-desc&arg=${_package}" | jq -r )
997     local _found_result_count="$(echo "${_aur_json}" | jq -r ".resultcount")"
998     if (( "${_found_result_count}" == 0 )); then
999         msg_error "Could not find all required packages: %s" "${_package}"
1000         exit 1
1001     fi
1002     _aur_json=$(echo "${_aur_json}" | jq -r ".results[]")
1003
1004     local _found_pkgname=($(echo "${_aur_json}" | jq -r ".Name" ))
1005
1006     if [[ "${quiet}" = true ]]; then
1007         local _IFS="${IFS}"
1008         IFS=$'\n'
1009         echo "${_found_pkgname[*]}"
1010         IFS="${_IFS}"
1011     else
1012         local  _found_package __pkgver __popularity __vote __pkgdesc __orphaned __installed __output_text=()
1013         for _found_package in ${_found_pkgname[@]}; do
1014             __orphaned=false
1015             __installed=false
1016             _found_json="$(echo ${_aur_json} | jq "select(.Name == \"${_found_package}\")")"
1017
1018             #echo "${_found_json}"
1019             __pkgver="$(echo "${_found_json}" | jq -r ".Version" )"
1020             __popularity="$(echo "${_found_json}" | jq -r ".Popularity" )"
1021             __vote="$(echo "${_found_json}" | jq -r ".NumVotes" )"
1022             __pkgdesc="$(echo "${_found_json}" | jq -r ".Description" )"
1023
1024             # 人気度の少数2位以下を四捨五入
1025             # 参考: http://www.rivhiro-weather.com/knowledge/?p=536
1026             msg_debug "Row popularity: %s" "${__popularity}"
1027             __popularity="$(printf "%g\n" "${__popularity}" | awk '{printf("%4.2f", $1)}')"
1028
1029             # 孤児判定
1030             #参考: https://www.366service.com/jp/qa/7c95f46e5236039134ff5b862ae2cd13
1031             if ! echo "${_found_json}" | jq -r --exit-status ".Maintainer" 1> /dev/null 2> /dev/null ; then
1032                 __orphaned=true
1033             fi
1034
1035             # インストール済み判定
1036             if check_installed_package "${_found_package}"; then
1037                 __installed=true
1038             fi
1039
1040             __output_text+=(
1041                 "$(text -c blue -b "aur")/$(text -b "${_found_package}") $(text -c cyan "${__pkgver}") (+$(text -b "${__vote} ${__popularity}"))"
1042             )
1043             
1044             if [[ "${__orphaned}" = true ]]; then
1045                 __output_text+=("$(text -bc red "(Orphaned)")")
1046             fi
1047
1048             if [[ "${__installed}" = true ]]; then
1049                 __output_text+=("$(text -bc cyan "[Installed]")")
1050             fi
1051             echo "${__output_text[*]}"
1052             echo "    ${__pkgdesc}"
1053             unset __pkgver __popularity __vote __pkgdesc _found_json __orphaned __installed __output_text
1054         done
1055     fi
1056 }
1057
1058 # バージョンを表示して終了
1059 operation_version() {
1060     # Pyalpmからlibalpmの値を取得
1061     # 参考: https://pyalpm.readthedocs.io/en/latest/pyalpm/pyalpm.html
1062     local _libalpm_version="$(python3 -c 'import pyalpm; print(pyalpm.alpmversion())')"
1063     local _pacman_version="$("${pacman_command}" -Q pacman | cut -d ' ' -f 2)"
1064     echo "wfa v${wfa_version} - pacman v${_pacman_version} - libalpm v${_libalpm_version}"
1065 }
1066
1067 operation_remove() {
1068     run_pacman ${pacman_args} "${specified_packages[@]}"
1069 }
1070
1071 # Usage: install_package <package1> <package2>...
1072 install_package() {
1073     local _package _repo_packages=() _aur_packages=()
1074     for _package in ${@}; do
1075         if ! check_installed_package "${_package}"; then
1076             if ! check_aur_package "${_package}"; then
1077                 # 公式パッケージなのでpacmanでそのままインストール
1078                 _repo_packages+=("${_package}")
1079             else
1080                 # AUR上のパッケージの場合の処理
1081                 _aur_packages+=("${_package}")
1082             fi
1083         fi
1084     done
1085
1086     if (( "${#_repo_packages[@]}" > 0 )); then
1087         run_pacman --asdeps ${pacman_args} "${_repo_packages[@]}"
1088     fi
1089
1090     if (( "${#_aur_packages[@]}" > 0 )); then
1091         unset _package
1092         for _package in ${_aur_packages[@]}; do
1093             install_aur_package "${_package}"
1094         done
1095     fi
1096 }
1097
1098 upgrade_aur_package() {
1099     #ここまで翻訳
1100     msg_error "This is a feature that has not been implemented yet"
1101 }
1102
1103 operation_sync(){
1104     local _package
1105     if (( "${sync_clean_count}" >= 1 )); then
1106         remove "$(get_cache_dir)/wfa"
1107         run_pacman ${pacman_args} $(
1108             local _count
1109             for _count in $(seq 1 ${sync_clean_count}); do
1110                 echo -n "-c "
1111             done
1112         )
1113     fi
1114
1115
1116     if [[ "${sync_search}" = true ]]; then
1117         for _package in ${specified_packages[@]}; do
1118             search_aur_package "${_package}"
1119         done
1120         "${pacman_command}" ${pacman_args} ${specified_packages[@]} || :
1121     else
1122         if [[ "${sync_upgrade}" = true ]]; then
1123             upgrade_aur_package
1124             run_pacman ${pacman_args} --sysupgrade
1125         fi
1126         for _package in ${specified_packages[@]}; do
1127             if ! check_aur_package "${_package}" && [[ "${force_aur}" = false ]]; then
1128                 # 公式パッケージなのでpacmanでそのままインストール
1129                 run_pacman ${pacman_args} "${_package}"
1130             else
1131                 # AUR上のパッケージの場合の処理
1132                 install_aur_package "${_package}"
1133                 #msg_error "Getting the AUR package has not been implemented yet."
1134                 #exit 1
1135             fi
1136         done
1137     fi
1138 }
1139
1140
1141 operation_vote() {
1142
1143     # aurvoteの確認
1144     if ! type aurvote 1> /dev/null 2> /dev/null; then
1145         msg_error "There is no aurvote"
1146         msg_error "Please install with %s" "\"wfa -S aurvote\""
1147         exit 1
1148     fi
1149
1150     local _package _aur_json _found_result_count _pkgver _before_popularity _before_vote
1151     for _package in ${specified_packages[@]}; do
1152
1153         # 存在するパッケージか確認
1154         _aur_json=$("${curl_command}" ${curl_args} -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name-desc&arg=${_package}" | jq -r)
1155         _found_result_count="$(echo "${_aur_json}" | jq -r ".resultcount")"
1156         _aur_json=$(echo "${_aur_json}" | jq -r ".results[] | select(.Name == \"${_package}\")")
1157         if (( "${_found_result_count}" == 0 )) || [[ -z "${_aur_json}" ]]; then
1158             msg_error "Package not found on AUR: %s" "${_package}"
1159             exit 1
1160         fi
1161
1162         # jsonから値を取り出して整形
1163         _pkgver="$(echo "${_aur_json}" | jq -r ".Version" )"
1164         _before_popularity="$(printf "%g\n" "$(echo "${_aur_json}" | jq -r ".Popularity" )" | awk '{printf("%4.2f", $1)}')"
1165         _before_vote="$(echo "${_aur_json}" | jq -r ".NumVotes" )"
1166
1167         # 投票を操作
1168         if [[ "$(aurvote --check "${_package}")" = "not voted" ]]; then
1169             msg_info "Voted for %s" "${_package}"
1170             aurvote --vote "${_package}" 1> /dev/null
1171         else
1172             msg_info "Unvoted for %s" "${_package}"
1173             aurvote --unvote "${_package}" 1> /dev/null
1174         fi
1175
1176         # 投票後の値を取得
1177         _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}\")")
1178         _after_popularity="$(printf "%g\n" "$(echo "${_aur_json}" | jq -r ".Popularity" )" | awk '{printf("%4.2f", $1)}')"
1179         _after_vote="$(echo "${_aur_json}" | jq -r ".NumVotes" )"
1180
1181         # 結果を出力
1182         msg_info "%s %s (+%s) → (+%s)" "$(text -b "${_package}")" "$(text -c cyan "${_pkgver}")" "$(text -b "${_before_vote} ${_before_popularity}")" "$(text -b "${_after_vote} ${_after_popularity}")"
1183     done
1184 }
1185
1186 # Parse options
1187 ARGUMENT="${@}"
1188 _opt_short="AQRShVdb:aysuc"q
1189 _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:"
1190
1191 OPT=$(getopt -o ${_opt_short} -l ${_opt_long} -- ${ARGUMENT})
1192 [[ ${?} != 0 ]] && exit 1
1193 unset _opt_short _opt_long
1194
1195 eval set -- "${OPT}"
1196 msg_debug "Argument: ${OPT}"
1197
1198 while :; do
1199     case ${1} in
1200         -A | --vote)
1201             set_operation "vote"
1202             shift 1
1203             ;;
1204         -Q | --query)
1205             set_operation "query"
1206             shift 1
1207             ;;
1208         -R | --remove)
1209             set_operation "remove"
1210             shift 1
1211             ;;
1212         -S | --sync)
1213             set_operation "sync"
1214             shift 1
1215             ;;
1216         -V | --version)
1217             set_operation "version"
1218             shift 1
1219             ;;
1220         --)
1221             shift
1222             break
1223             ;;
1224         *)
1225             shift 1
1226             ;;
1227     esac
1228 done
1229
1230 eval set -- "${OPT}"
1231
1232 while :; do
1233     case ${1} in
1234         -a | --aur)
1235             force_aur=true
1236             msg_debug "Assume targets are from the AUR"
1237             shift 1
1238             ;;
1239         --debug)
1240             debug=true
1241             add_args pacman "--debug"
1242             shift 1
1243             ;;
1244         -d | --nodeps)
1245             nodeps=true
1246             add_args pacman "--nodeps"
1247             shift 1
1248             ;;
1249         -b | --dbpath)
1250             add_args pacman "--dbpath '${2}'"
1251             shift 2
1252             ;;
1253         -y | --refresh)
1254             option_y_count=$(( option_y_count + 1 ))
1255             shift 1
1256             ;;
1257         -s | --search)
1258             add_args pacman "--search"
1259             sync_search=true
1260             shift 1
1261             ;;
1262         -u | --sysupgrade)
1263             sync_upgrade=true
1264             shift 1
1265             ;;
1266         -c | --clean)
1267             sync_clean_count=$(( sync_clean_count + 1 ))
1268             shift 1
1269             ;;
1270         -q | --quiet)
1271             quiet=true
1272             add_args pacman "--quiet"
1273             shift 1
1274             ;;
1275         --arch)
1276             arch="${2}"
1277             add_args pacman "--arch ${2}"
1278             shift 2
1279             ;;
1280         --aururl)
1281             aururl="${2}"
1282             shift 2
1283             ;;
1284         --noconfirm)
1285             add_args pacman "--noconfirm"
1286             noconfirm=true
1287             shift 1
1288             ;;
1289         --config)
1290             pacman_config="${2}"
1291             add_args pacman "--config ${2}"
1292             shift 2
1293             ;;
1294         --makepkg)
1295             makepkg_command="${2}"
1296             shift 2
1297             ;;
1298         --mflags)
1299             #makepkg_args="${2}"
1300             add_args makepkg "${2}"
1301             shift 2
1302             ;;
1303         --pacman)
1304             pacman_command="${2}"
1305             shift 2
1306             ;;
1307         --git)
1308             git_command="${2}"
1309             shift 2
1310             ;;
1311         --gitflags)
1312             #git_args="${2}"
1313             add_args git "${2}"
1314             shift 2
1315             ;;
1316         --makepkgconfig)
1317             if [[ "${nomakepkgconf}" = false ]]; then
1318                 makepkg_config="${2}"
1319             else
1320                 msg_warn "--nomakepkgconf is specified.\n--makepkgconf has been ignored."
1321             fi
1322             shift 2
1323             ;;
1324         --nomakepkgconf)
1325             makepkg_config="/etc/makepkg.conf"
1326             nomakepkgconf=true
1327             shift 1
1328         ;;
1329         --bash-debug)
1330             bash_debug=true
1331             set -xv
1332             shift 1
1333             ;;
1334         --msg-debug)
1335             msgdebug=true
1336             shift 1
1337             ;;
1338         --color)
1339             case "${2}" in
1340                 "never")
1341                     nocolor=true
1342                     add_args pacman "--color never"
1343                     ;;
1344                 "always")
1345                     nocolor=false
1346                     add_args pacman "--color always"
1347                     ;;
1348                 "auto")
1349                     msg_error "auto is not currently supported."
1350                     add_args pacman "--color auto"
1351                     ;;
1352             esac
1353             ;;
1354         --nocolor)
1355             nocolor=true
1356             add_args pacman "--color never"
1357             shift 1
1358             ;;
1359         --confirm)
1360             noconfirm=false
1361             shift 1
1362             ;;
1363         --disable-download-timeout)
1364             add_args curl "--max-time 0"
1365             add_args pacman "--disable-download-timeout"
1366             shift 1
1367             ;;
1368         --curl)
1369             curl_command="${2}"
1370             shift 2
1371             ;;
1372         --curlflags)
1373             add_args curl "${2}"
1374             shift 2
1375             ;;
1376         -h | --help)
1377             usage
1378             shift 1
1379             exit 0
1380             ;;
1381         --)
1382             shift
1383             break
1384             ;;
1385         *)
1386             shift 1
1387             ;;
1388     esac
1389 done
1390
1391 specified_packages=(${@})
1392
1393 # Run database update
1394 if (( "${option_y_count}" == 1 )); then
1395     run_pacman -Sy
1396 elif (( "${option_y_count}" >= 2 )); then
1397     run_pacman -Syy
1398 fi
1399
1400 # set_operationで設定された操作を実行
1401 case "${operation}" in
1402     "version")
1403         operation_version
1404         ;;
1405     "sync")
1406         operation_sync
1407         ;;
1408     "remove")
1409         operation_remove
1410         ;;
1411     "vote")
1412         operation_vote
1413         ;;
1414     "none")
1415         exit 0
1416         ;;
1417     *)
1418         msg_error "Undefined operation"
1419         exit 1
1420         ;;
1421 esac