OSDN Git Service

03544efb9f6d5fcc79c925fc546c34c532768afb
[alterlinux/wfa.git] / wfa
1 #!/usr/bin/env bash
2
3 set -eu
4
5 ######################################################################################
6
7 #-- wfa configs --#
8 wfa_version="0.1"
9 wfa_name="WFA"
10 wfa_command="wfa"
11
12 #-- options (int) --#
13 option_y_count=0
14
15 #-- options (str) --#
16 aururl="https://aur.archlinux.org/"
17 operation="none"
18
19 #-- options (bool) --#
20 debug=false
21 force_aur=false
22 msgdebug=false
23 nocolor=false
24 noconfirm=false
25 nodeps=false
26 nomakepkgconf=false
27
28 #-- makepkg --#
29 # 実行ファイル
30 makepkg_command="/usr/bin/makepkg" 
31 # 設定ファイル
32 makepkg_config="/etc/makepkg.conf"
33 # 引数
34 makepkg_args=""
35
36 #-- pacman --#
37 # 実行ファイル
38 pacman_command="/usr/bin/pacman"
39 # 設定ファイル
40 pacman_config="/etc/pacman.conf"
41 # 引数
42 pacman_args=""
43
44 #-- git --#
45 # 実行ファイル
46 git_command="/usr/bin/git"
47 # 引数
48 git_args=""
49
50 #-- gpg --#
51 # 実行ファイル
52 gpg_command="/usr/bin/gpg"
53 # 引数
54 gpg_args=""
55
56 #-- sudo --#
57 # 実行ファイル
58 sudo_command="/usr/bin/sudo"
59 # 引数
60 sudo_args=""
61
62
63 ######################################################################################
64
65
66 # メッセージ出力の制御
67 # https://github.com/FascodeNet/alterlinux/blob/dev/tools/msg.sh の変数名にアンダーバーを追加し関数化
68 msg() {
69     local OPTIND OPTARG arg
70
71     local _appname="msg.sh"
72     local _bash_debug=false
73     local _nocolor=false
74     local _echo_opts=""
75     local _message=""
76     local _msg_type="info"
77     local _msg_label=""
78     local _label_space="7"
79     local _adjust_chr=" "
80     local _customized_label=false
81     local _customized_label_color=false
82     local _nolabel=false
83     local _noappname=false
84     local _noadjust=false
85     local _output="stdout"
86
87     _help() {
88         echo "usage ${0} [option] [type] [message]"
89         echo
90         echo "Display a message with a colored app name and message type label"
91         echo
92         echo " General type:"
93         echo "    info                      General message"
94         echo "    warn                      Warning message"
95         echo "    error                     Error message"
96         echo "    debug                     Debug message"
97         echo
98         echo " General options:"
99         echo "    -a [name]                 Specify the app name"
100         echo "    -c [character]            Specify the character to adjust the label"
101         echo "    -l [label]                Specify the label."
102         echo "    -n | --nocolor            No output colored output"
103         echo "    -o [option]               Specify echo options"
104         echo "    -r [color]                Specify the color of label"
105         echo "    -s [number]               Specifies the label space."
106         echo "    -x | --bash-debug         Enables output bash debugging"
107         echo "    -h | --help               This help message"
108         echo
109         echo "         --nolabel            Do not output label"
110         echo "         --noappname          Do not output app name"
111         echo "         --noadjust           Do not adjust the width of the label"
112     }
113
114     while getopts "a:c:l:no:r:s:xh-:" arg; do
115         case ${arg} in
116                 a) 
117                     _appname="${OPTARG}"
118                     ;;
119                 c) 
120                     _adjust_chr="${OPTARG}"
121                     ;;
122                 l) 
123                     _customized_label=true
124                     _msg_label="${OPTARG}"
125                     ;;
126                 n)
127                     _nocolor=true
128                     ;;
129                 o)
130                     _echo_opts="${OPTARG}"
131                     ;;
132                 r)
133                     _customized_label_color=true
134                     case ${OPTARG} in
135                         "black")
136                             _labelcolor="30"
137                             ;;
138                         "red")
139                             _labelcolor="31"
140                             ;;
141                         "green")
142                             _labelcolor="32"
143                             ;;
144                         "yellow")
145                             _labelcolor="33"
146                             ;;
147                         "blue")
148                             _labelcolor="34"
149                             ;;
150                         "magenta")
151                             _labelcolor="35"
152                             ;;
153                         "cyan")
154                             _labelcolor="36"
155                             ;;
156                         "white")
157                             _labelcolor="37"
158                             ;;
159                         *)
160                             return 1
161                             ;;
162                     esac
163                     ;;
164                 s)
165                     _label_space="${OPTARG}"
166                     ;;
167                 x)
168                     _bash_debug=true
169                     set -xv
170                     ;;
171                 h)
172                     _help
173                     shift 1
174                     exit 0
175                     ;;
176                 -)
177                     case "${OPTARG}" in
178                         "nocolor")
179                             _nocolor=true
180                             ;;
181                         "bash-debug")
182                             _bash_debug=true
183                             set -xv
184                             ;;
185                         "help") 
186                             _help
187                             exit 0
188                             ;;
189                         "nolabel")
190                             _nolabel=true
191                             ;;
192                         "noappname")
193                             _noappname=true
194                             ;;
195                         "noadjust")
196                             _noadjust=true 
197                             ;;
198                         *)
199                             _help
200                             exit 1
201                             ;;
202                     esac
203         esac
204     done
205
206     shift $((OPTIND - 1))
207
208     # Color echo
209     #
210     # Text Color
211     # 30 => Black
212     # 31 => Red
213     # 32 => Green
214     # 33 => Yellow
215     # 34 => Blue
216     # 35 => Magenta
217     # 36 => Cyan
218     # 37 => White
219     #
220     # Background color
221     # 40 => Black
222     # 41 => Red
223     # 42 => Green
224     # 43 => Yellow
225     # 44 => Blue
226     # 45 => Magenta
227     # 46 => Cyan
228     # 47 => White
229     #
230     # Text decoration
231     # You can specify multiple decorations with ;.
232     # 0 => All attributs off (ノーマル)
233     # 1 => Bold on (太字)
234     # 4 => Underscore (下線)
235     # 5 => Blink on (点滅)
236     # 7 => Reverse video on (色反転)
237     # 8 => Concealed on
238
239     case ${1} in
240         "info")
241             _msg_type="type"
242             _output="stdout"
243             [[ "${_customized_label_color}" = false ]] && _labelcolor="32"
244             [[ "${_customized_label}"       = false ]] && _msg_label="Info"
245             shift 1
246             ;;
247         "warn")
248             _msg_type="warn"
249             _output="stdout"
250             [[ "${_customized_label_color}" = false ]] && _labelcolor="33"
251             [[ "${_customized_label}"       = false ]] && _msg_label="Warning"
252             shift 1
253             ;;
254         "debug")
255             _msg_type="debug"
256             _output="stdout"
257             [[ "${_customized_label_color}" = false ]] && _labelcolor="35"
258             [[ "${_customized_label}"       = false ]] && _msg_label="Debug"
259             shift 1
260             ;;
261         "error")
262             _msg_type="error"
263             _output="stderr"
264             [[ "${_customized_label_color}" = false ]] && _labelcolor="31"
265             [[ "${_customized_label}"       = false ]] && _msg_label="Error"
266             shift 1
267             ;;
268         "")
269             echo "Please specify the message type" >&2
270             exit 1
271             ;;
272         *)
273             echo "Unknown message type" >&2
274             exit 1
275             ;;
276     esac
277
278     _word_count="${#_msg_label}"
279     _message="${@}"
280
281     echo_type() {
282         local __time
283         if [[ "${_nolabel}" = false ]]; then
284             if [[ "${_noadjust}" = false ]]; then
285                 for __time in $( seq 1 $(( ${_label_space} - ${_word_count})) ); do
286                     echo -ne "${_adjust_chr}"
287                 done
288             fi
289             if [[ "${_nocolor}" = false ]]; then
290                 echo -ne "\e[$([[ -v _backcolor ]] && echo -n "${_backcolor}"; [[ -v _labelcolor ]] && echo -n ";${_labelcolor}"; [[ -v _decotypes ]] && echo -n ";${_decotypes}")m${_msg_label}\e[m "
291             else
292                 echo -ne "${_msg_label} "
293             fi
294         fi
295     }
296
297     echo_appname() {
298         if [[ "${_noappname}" = false ]]; then
299             if [[ "${_nocolor}" = false ]]; then
300                 echo -ne "\e[36m[${_appname}]\e[m "
301             else
302                 echo -ne "[${_appname}] "
303             fi
304         fi
305     }
306
307     for _count in $(seq "1" "$(echo -ne "${_message}\n" | wc -l)"); do
308         _echo_message=$(echo -ne "${_message}\n" |head -n "${_count}" | tail -n 1 )
309         _full_message="$(echo_appname)$(echo_type)${_echo_message}"
310         case "${_output}" in
311             "stdout")
312                 echo ${_echo_opts} "${_full_message}" >&1
313                 ;;
314             "stderr")
315                 echo ${_echo_opts} "${_full_message}" >&2
316                 ;;
317             *)
318                 echo ${_echo_opts} "${_full_message}" > ${_output}
319                 ;;
320         esac
321     done
322 }
323
324 # Show an INFO message
325 # $1: message string
326 msg_info() {
327     local _msg_opts="-a ${wfa_name}"
328     if [[ "${1}" = "-n" ]]; then
329         _msg_opts="${_msg_opts} -o -n"
330         shift 1
331     fi
332     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
333     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
334     msg ${_msg_opts} info "${1}"
335 }
336
337 # Show an Warning message
338 # $1: message string
339 msg_warn() {
340     local _msg_opts="-a ${wfa_name}"
341     if [[ "${1}" = "-n" ]]; then
342         _msg_opts="${_msg_opts} -o -n"
343         shift 1
344     fi
345     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
346     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
347     msg ${_msg_opts} warn "${1}"
348 }
349
350 # Show an debug message
351 # $1: message string
352 msg_debug() {
353     if [[ "${debug}" = true ]]; then
354         local _msg_opts="-a ${wfa_name}"
355         if [[ "${1}" = "-n" ]]; then
356             _msg_opts="${_msg_opts} -o -n"
357             shift 1
358         fi
359         [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
360         [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
361         msg ${_msg_opts} debug "${1}"
362     fi
363 }
364
365 # Show an ERROR message then exit with status
366 # $1: message string
367 # $2: exit code number (with 0 does not exit)
368 msg_error() {
369     local _msg_opts="-a ${wfa_name}"
370     if [[ "${1}" = "-n" ]]; then
371         _msg_opts="${_msg_opts} -o -n"
372         shift 1
373     fi
374     [[ "${msgdebug}" = true ]] && _msg_opts="${_msg_opts} -x"
375     [[ "${nocolor}"  = true ]] && _msg_opts="${_msg_opts} -n"
376     msg ${_msg_opts} error "${1}"
377     if [[ -n "${2:-}" ]]; then
378         exit ${2}
379     fi
380 }
381
382 # rm helper
383 # Delete the file if it exists.
384 # For directories, rm -rf is used.
385 # If the file does not exist, skip it.
386 # remove <file> <file> ...
387 remove() {
388     local _list=($(echo "$@")) _file
389     for _file in "${_list[@]}"; do
390         msg_debug "Removing ${_file}"
391         if [[ -f "${_file}" ]]; then    
392             rm -f "${_file}"
393         elif [[ -d "${_file}" ]]; then
394             rm -rf "${_file}"
395         fi
396     done
397 }
398
399 usage (){
400     local _pacman_help=false
401
402     local _wfa_usage
403     _wfa_usage() {
404         echo "Usage:"
405         echo "${wfa_command}"
406         echo "${wfa_command} <operation> [...]"
407         echo
408         echo "operations:"
409         echo "    ${wfa_command} {-h --help}"
410         echo "    ${wfa_command} {-V --version}"
411        #echo "    ${wfa_command} {-D --database}    <options> <package(s)>"
412        #echo "    ${wfa_command} {-F --files}       [options] [package(s)]"
413         echo "    ${wfa_command} {-Q --query}       [options] [package(s)]"
414         echo "    ${wfa_command} {-R --remove}      [options] <package(s)>"
415         echo "    ${wfa_command} {-S --sync}        [options] [package(s)]"
416        #echo "    ${wfa_command} {-T --deptest}     [options] [package(s)]"
417        #echo "    ${wfa_command} {-U --upgrade}     [options] <file(s)>"
418        #echo
419        #echo "New operations:"
420        #echo "    ${wfa_command} {-P --show}        [options]"
421        #echo "    ${wfa_command} {-G --getpkgbuild} [package(s)]"
422         echo
423         echo "New options:"
424         echo "       --repo             Assume targets are from the repositories"
425         echo "    -a --aur              Assume targets are from the AUR"
426         echo
427         echo "Permanent configuration options:"
428         echo "    --aururl      <url>   Set an alternative AUR URL"
429         echo "    --makepkg     <file>  makepkg command to use"
430         echo "    --mflags      <flags> Pass arguments to makepkg"
431         echo "    --pacman      <file>  pacman command to use"
432         echo "    --git         <file>  git command to use"
433         echo "    --gitflags    <flags> Pass arguments to git"
434         echo "    --gpg         <file>  gpg command to use"
435         echo "    --gpgflags    <flags> Pass arguments to gpg"
436         echo "    --config      <file>  pacman.conf file to use"
437         echo "    --makepkgconf <file>  makepkg.conf file to use"
438         echo "    --nomakepkgconf       Use the default makepkg.conf"
439         echo
440     }
441
442     local _wfa_usage_sync
443     _wfa_usage_sync() {
444         echo "usage:  ${wfa_command} {-S --sync} [options] [package(s)]"
445         echo "options:"
446         echo "  -b, --dbpath <path>  set an alternate database location"
447         echo "      --config <path>  set an alternate configuration file"
448         echo "      --noconfirm      do not ask for any confirmation"
449
450     }
451
452     if [[ "${operation}" = "none" ]]; then
453         _wfa_usage
454     elif [[ "${_pacman_help}" = true ]]; then
455         "${pacman_command}" -h --${operation}
456     elif [[ "$(type -t "_wfa_usage_${operation}" )" = "function" ]]; then
457         _wfa_usage_${operation}
458     else
459         msg_error "Undefined operation." 1
460     fi
461 }
462
463 set_operation() {
464     if [[ "${operation}" = "none" ]]; then
465         operation="${1}"
466         add_args pacman "--${operation}"
467     else
468         msg_error "only one operation may be used at a time" 1
469     fi
470 }
471
472 run_sudo() {
473     if (( ${UID} == 0 )); then
474         ${@}
475     else
476         sudo ${@}
477     fi
478 }
479
480 run_pacman() {
481     run_sudo "${pacman_command}" ${@}
482 }
483
484 # pacmanの引数を追加する
485 # https://github.com/FascodeNet/aptpac/blob/master/aptpac のADD_OPTION関数を参考
486 # Usage: add_args [pacman/makepkg] <args1> <args2>...
487 add_args() {
488     local _target="${1}"
489     local _args_array
490     shift 1
491
492     case "${_target}" in
493         "makepkg")
494             _args_array=(${makepkg_args})
495             _args_array+=(${@})
496             makepkg_args=${_args_array[@]}
497             msg_debug "makepkg ARGS: ${makepkg_args}"
498             ;;
499
500         "pacman")
501             _args_array=(${pacman_args})
502             _args_array+=(${@})
503             pacman_args=${_args_array[@]}
504             msg_debug "pacman ARGS: ${pacman_args}"
505             ;;
506         "git")
507             _args_array=(${mpg_args})
508             _args_array+=(${@})
509             git_args=${_args_array[@]}
510             msg_debug "git ARGS: ${git_args}"
511             ;;
512         "gpg")
513             _args_array=(${gpg_args})
514             _args_array+=(${@})
515             gpg_args=${_args_array[@]}
516             msg_debug "gpg ARGS: ${gpg_args}"
517             ;;
518         "sudo")
519             _args_array=(${sudo_args})
520             _args_array+=(${@})
521             sudo_args=${_args_array[@]}
522             msg_debug "sudo ARGS: ${sudo_args}"
523             ;;
524         *)
525             msg_error "Failed to set the argument of ${_target}\nSetting that command is not currently supported." 1
526             ;;
527     esac
528 }
529
530 # 引数で指定されたパッケージがAUR以外の場所に存在しない場合にのみ正常終了します(AURのパッケージの場合に正常終了)
531 check_aur_package() {
532     local _package="${1}"
533     # 参考: https://qiita.com/Hayao0819/items/a8740a17301fafa2fdab
534     if [[ -z "$(pacman -Ssq "${_package}" 2>/dev/null | grep -o ".*${_package}$")" ]]; then
535         #AUR以外のリポジトリに存在しない
536         return 0
537     else
538         return 1
539     fi
540 }
541
542
543 # 引数で指定されたパッケージが既にインストールされている場合は正常終了します。
544 check_installed_package() {
545     local _package="${1}"
546     if "${pacman_command}" -Qq "${_package}" > /dev/null 2>&1; then
547         return 0
548     else
549         return 1
550     fi
551 }
552
553 get_cache_dir() {
554     local _user_config_dir
555     if [[ -v XDG_CONFIG_HOME ]]; then
556         _user_config_dir="${XDG_CONFIG_HOME}"
557     else
558         _use_config_dir="${HOME}/.config"
559     fi
560     if [[ -f "${_use_config_dir}/user-dirs.dirs" ]]; then
561         source "${_use_config_dir}/user-dirs.dirs"
562     fi
563     if [[ -v XDG_CACHE_HOME ]]; then
564         echo -n "${XDG_CACHE_HOME}"
565         return 0
566     else
567         echo -n "${HOME}/.cache"
568         return 0
569     fi
570 }
571
572 # Usage: get_srcinfo_data <path> <var>
573 # 参考: https://qiita.com/withelmo/items/b0e1ffba639dd3ae18c0
574 get_srcinfo_data() {
575     local _srcinfo="${1}" _ver="${2}"
576     local _srcinfo_json=$(python << EOF
577 from srcinfo.parse import parse_srcinfo; import json
578 text = """
579 $(cat ${1})
580 """
581 parsed, errors = parse_srcinfo(text)
582 print(json.dumps(parsed))
583 EOF
584 )
585     echo "${_srcinfo_json}" | jq -rc "${2}" | tr '\n' ' '
586 }
587
588
589 # AURからパッケージをビルドしてインストールします
590 # 現在1つのパッケージしか指定できません
591 install_aur_package() {
592     local _package="${1}"
593
594     # Create cache dir
595     if [[ ! -v wfa_cache_dir ]]; then
596         wfa_cache_dir="$(get_cache_dir)/wfa"
597     fi
598     mkdir -p "${wfa_cache_dir}/archive"
599     mkdir -p "${wfa_cache_dir}/build/${_package}"
600
601     # AurJsonから値を取得
602     local _aur_json=$(curl -sL "https://aur.archlinux.org/rpc/?v=5&type=search&by=name&arg=${_package}" | jq -r)
603     if (( "$(echo "${_aur_json}" | jq -r ".resultcount")" == 0 )); then
604         msg_error "Could not find all required packages:\n      ${_package}" 1
605     fi
606
607     local _found_packages="$(echo "${_aur_json}" | jq -r --tab '.results[].Name')"
608     #msg_debug "Found package: $(echo ${_found_packages} | tr '\n' ' ')"
609
610     if [[ -n "$(echo "${_found_packages}" | grep -x "${_package}" )" ]]; then
611         msg_debug "Select a package ${_package} with an exact name match"
612     else
613         msg_error "No package with an exact name match was found." 1
614     fi
615
616     # PKGBUILDをダウンロード
617     msg_info "Download PKGBUILD of ${_package}"
618     _aur_json=$(echo "${_aur_json}" | jq -r ".results[] | select(.Name == \"${_package}\")" )
619     local _aur_snapshot_url="${aururl%/}$(echo "${_aur_json}" | jq -r ".URLPath")"
620     local _aur_version="$(echo "${_aur_json}" | jq -r ".Version")"
621     msg_debug "Get PKGBUILD from ${_aur_snapshot_url}"
622
623     local _pkgbuild_archive_path="${wfa_cache_dir}/archive/${_package}-${_aur_version}"
624     local _download_pkgbuild=true
625     if [[ -f "${_pkgbuild_archive_path}" ]]; then
626         msg_warn "PKGBUILD has already been downloaded."
627         msg_warn -n "Do you want to overwrite and download? [n] :"
628         local _yes_or_no
629         if [[ "${noconfirm}" = true ]]; then
630             echo
631             _yes_or_no="No"
632         else
633             read _yes_or_no
634         fi
635         case "${_yes_or_no}" in
636             "y" | "Y" | "yes" | "Yes" | "YES" ) _download_pkgbuild=true  ;;
637             *                                 ) _download_pkgbuild=false ;;
638         esac
639     fi
640     if [[ "${_download_pkgbuild}" = true ]]; then
641         remove "${_pkgbuild_archive_path}"
642         curl -L -C - -f -o "${_pkgbuild_archive_path}" "${_aur_snapshot_url}"
643     fi
644
645     # PKGBUILDを展開
646     msg_info "Unpacking the tarball of PKGBUILD ..."
647     tar -xv -f "${_pkgbuild_archive_path}" -C "${wfa_cache_dir}/build/" > /dev/null 2>&1
648
649     # .SRCINFOを解析
650     local _build_dir="${wfa_cache_dir}/build/${_package}"
651     if [[ ! -f "${_build_dir}/.SRCINFO" ]]; then
652         msg_warn ".SRCINFO was not found.\nGenerate it using makepkg."
653         (
654             cd "${_build_dir}"
655             "${makepkg_command}" --printsrcinfo > "${_build_dir}/.SRCINFO"
656         )
657     fi
658
659     local _makedepends="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".makedepends[]?")"
660     local _depends="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".depends[]?")"
661     local _conflicts="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".conflicts[]?")"
662     msg_debug "makedepends: ${_makedepends}"
663     msg_debug "depends: ${_depends}"
664     msg_debug "conflicts: ${_conflicts}"
665
666
667     # 衝突を確認
668     local _pkg _conflicts_found=false
669     for _pkg in ${_conflicts[@]}; do
670         if "${pacman_command}" -Qq "${_pkg}" > /dev/null 2>&1 ; then
671             _conflicts_found=true
672             msg_error "${_package} is colliding with ${_pkg}"
673         fi
674     done
675     if "${pacman_command}" -Qq "${_package}" > /dev/null 2>&1 &&  [[ ! "$("${pacman_command}" -Qq "${_package}" 2> /dev/null)" = "${_package}" ]]; then
676         msg_error "${_package} is colliding with $("${pacman_command}" -Qq "${_package}")"
677         _conflicts_found=true
678     fi
679     if [[ "${_conflicts_found}" = true ]]; then
680         msg_error "A conflict was found." 1
681     fi
682
683
684     # 依存パッケージをインストール
685     if [[ "${nodeps}" = false ]]; then
686         msg_info "Install dependent packages..."
687         local _force_aur="${force_aur}"
688         force_aur=false
689         install_package "${_depends}"
690         force_aur="${_force_aur}"
691         unset _force_aur
692     fi
693
694     # ビルド準備
695     # srcdirの確認
696     if [[ -d "${_build_dir}/src" ]]; then
697         msg_info "Found ${_build_dir}/src"
698         msg_info "Packages to cleanBuild? [n] :"
699         local _yes_or_no
700         unset _yes_or_no
701         if [[ "${noconfirm}" = true ]]; then
702             echo
703             _yes_or_no="No"
704         else
705             read _yes_or_no
706         fi
707         case "${_yes_or_no}" in
708             "y" | "Y" | "yes" | "Yes" | "YES" ) add_args makepkg "--clean" ;;
709         esac
710     fi
711
712
713     # ビルド
714     add_args "makepkg" "-sf"
715     (
716         cd "${_build_dir}"
717         "${makepkg_command}" "${makepkg_args}"
718     )
719
720
721     # ビルド後のパッケージ一覧を生成
722     (
723         cd "${_build_dir}"
724         "${makepkg_command}" --printsrcinfo > "${_build_dir}/.SRCINFO"
725     )
726     local _pkgnames=($(get_srcinfo_data "${_build_dir}/.SRCINFO" ".packages | keys[]" | sed 's/ //g'))
727     local _pkgver="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".pkgver" | sed 's/ //g')"
728     local _pkgrel="$(get_srcinfo_data "${_build_dir}/.SRCINFO" ".pkgrel" | sed 's/ //g')"
729     local _arch_array=($(get_srcinfo_data "${_build_dir}/.SRCINFO" ".arch[]"))
730     local _arch _pkgname
731     if [[ "${_arch_array[*]}" = "any" ]]; then
732         _arch="any"
733     else
734         _arch="$(uname -m)"
735     fi
736     local _PKGEXT=$(
737         source "${makepkg_config}"
738         echo "${PKGEXT}"
739     )
740     local _pkgfilelist=()
741     for _pkgname in ${_pkgnames[@]}; do
742         _pkgfilelist+=("${_build_dir}/${_pkgname}-${_pkgver}-${_pkgrel}-${_arch}${_PKGEXT}")
743     done
744
745     # インストール
746     run_pacman -U --noconfirm ${_pkgfilelist[@]}
747 }
748
749 # バージョンを表示して終了
750 operation_version() {
751     # Pyalpmからlibalpmの値を取得
752     # 参考: https://pyalpm.readthedocs.io/en/latest/pyalpm/pyalpm.html
753     local _libalpm_version="$(python3 -c 'import pyalpm; print(pyalpm.alpmversion())')"
754     local _pacman_version="$("${pacman_command}" -Q pacman | cut -d ' ' -f 2)"
755     echo "wfa v${wfa_version} - pacman v${_pacman_version} - libalpm v${_libalpm_version}"
756 }
757
758 operation_remove() {
759     run_pacman ${pacman_args} "${specified_packages[@]}"
760 }
761
762 # Usage: install_package <package1> <package2>...
763 install_package() {
764     local _package
765     for _package in ${@}; do
766         if ! check_installed_package "${_package}"; then
767             if ! check_aur_package "${_package}"; then
768                 # 公式パッケージなのでpacmanでそのままインストール
769                 run_pacman ${pacman_args} "${_package}"
770             else
771                 # AUR上のパッケージの場合の処理
772                 install_aur_package "${_package}"
773                 #msg_error "Getting the AUR package has not been implemented yet." 1
774             fi
775         fi
776     done
777 }
778
779 operation_sync(){
780     local _package
781     for _package in ${specified_packages[@]}; do
782         if ! check_aur_package "${_package}" && [[ "${force_aur}" = false ]]; then
783             # 公式パッケージなのでpacmanでそのままインストール
784             run_pacman ${pacman_args} "${_package}"
785         else
786             # AUR上のパッケージの場合の処理
787             install_aur_package "${_package}"
788             #msg_error "Getting the AUR package has not been implemented yet." 1
789         fi
790     done
791 }
792
793
794 # Parse options
795 ARGUMENT="${@}"
796 _opt_short="QRShVdb:ay"
797 _opt_long="query,remove,sync,help,version,debug,dbpath:,aururl,aur,noconfirm,config:,makepkg:,mflags:,pacman:,git:,gitflags:,gpg:,gpgflags:,makepkgconf:,nomakepkgconf,nodeps,refresh"
798
799 OPT=$(getopt -o ${_opt_short} -l ${_opt_long} -- ${ARGUMENT})
800 [[ ${?} != 0 ]] && exit 1
801 unset _opt_short _opt_long
802
803 eval set -- "${OPT}"
804 msg_debug "Argument: ${OPT}"
805
806 while :; do
807     case ${1} in
808         -Q | --query)
809             set_operation "query"
810             shift 1
811             ;;
812         -R | --remove)
813             set_operation "remove"
814             shift 1
815             ;;
816         -S | --sync)
817             set_operation "sync"
818             shift 1
819             ;;
820         -V | --version)
821             set_operation "version"
822             shift 1
823             ;;
824         --)
825             shift
826             break
827             ;;
828         *)
829             shift 1
830             ;;
831     esac
832 done
833
834 eval set -- "${OPT}"
835
836 while :; do
837     case ${1} in
838         -a | --aur)
839             force_aur=true
840             msg_debug "Assume targets are from the AUR"
841             shift 1
842             ;;
843         --debug)
844             debug=true
845             add_args pacman "--debug"
846             shift 1
847             ;;
848         -d | --nodeps)
849             nodeps=true
850             add_args pacman "--nodeps"
851             shift 1
852             ;;
853         -b | --dbpath)
854             add_args pacman "--dbpath '${2}'"
855             shift 2
856             ;;
857         -y | --refresh)
858             option_y_count=$(( option_y_count + 1 ))
859             shift 1
860             ;;
861         --aururl)
862             aururl="${2}"
863             shift 2
864             ;;
865         --noconfirm)
866             add_args pacman "--noconfirm"
867             noconfirm=true
868             shift 1
869             ;;
870         --config)
871             pacman_config="${2}"
872             add_args pacman "--config \"${2}\""
873             shift 2
874             ;;
875         --makepkg)
876             makepkg_command="${2}"
877             shift 2
878             ;;
879         --mflags)
880             makepkg_args="${2}"
881             shift 2
882             ;;
883         --pacman)
884             pacman_command="${2}"
885             shift 2
886             ;;
887         --git)
888             git_command="${2}"
889             shift 2
890             ;;
891         --gitflags)
892             git_args="${2}"
893             shift 2
894             ;;
895         --makepkgconfig)
896             if [[ "${nomakepkgconf}" = false ]]; then
897                 makepkg_config="${2}"
898             else
899                 msg_warn "--nomakepkgconf is specified.\n--makepkgconf has been ignored."
900             fi
901             shift 2
902             ;;
903         --nomakepkgconf)
904             makepkg_config="/etc/makepkg.conf"
905             nomakepkgconf=true
906             shift 1
907         ;;
908         -h | --help)
909             usage
910             shift 1
911             exit 0
912             ;;
913         --)
914             shift
915             break
916             ;;
917         *)
918             shift 1
919             ;;
920     esac
921 done
922
923 specified_packages=(${@})
924
925 # Run database update
926 if (( "${option_y_count}" == 1 )); then
927     run_pacman -Sy
928 elif (( "${option_y_count}" >= 2 )); then
929     run_pacman -Syy
930 fi
931
932 case "${operation}" in
933     "version")
934         operation_version
935         ;;
936     "sync")
937         operation_sync
938         ;;
939     "remove")
940         operation_remove
941         ;;
942     "none")
943         exit 0
944         ;;
945     *)
946         msg_error "Undefined operation." 1
947         ;;
948 esac