OSDN Git Service

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