527 lines
17 KiB
Text
527 lines
17 KiB
Text
#!/dev/null
|
|
|
|
|
|
|
|
|
|
::// deploy / ...
|
|
|
|
|
|
|
|
|
|
--<<.. deploy / list / variant
|
|
linux--x86_64
|
|
linux--x86_64--seccomp
|
|
linux--aarch64
|
|
linux--armv6
|
|
darwin--x86_64
|
|
darwin--aarch64
|
|
freebsd--x86_64
|
|
freebsd--aarch64
|
|
openbsd--x86_64
|
|
openbsd--aarch64
|
|
android--x86_64
|
|
android--aarch64
|
|
!!
|
|
|
|
|
|
--<<.. deploy / list / main
|
|
kawipiko-wrapper
|
|
kawipiko-archiver
|
|
kawipiko-server
|
|
kawipiko-server-dummy
|
|
!!
|
|
|
|
|
|
|
|
|
|
--<< deploy / rsync / *
|
|
|
|
test "${#}" -eq 3 ; _main="${1}" ; _variant="${2}" ; _destination="${3}" ; shift -- 3
|
|
|
|
"${ZRUN}" ':: deploy / release' "${_main}" "${_variant}"
|
|
|
|
_outputs="$( exec -- "${ZRUN}" ':: workbench / outputs' )"
|
|
test -d "${_outputs}"
|
|
|
|
_output="${_outputs}/binaries/${_main}--release--${_variant}"
|
|
test -f "${_output}"
|
|
|
|
printf -- '[ii] deploying `%s` for `%s` to `%s`...\n' "${_main}" "${_variant}" "${_destination}" >&2
|
|
|
|
exec -- rsync -i -t -p --chmod=0555 -- "${_output}" "${_destination}"
|
|
!!
|
|
|
|
|
|
|
|
|
|
<< deploy / publish / no-github
|
|
|
|
export -- __DEPLOY_NOGITHUB=true
|
|
|
|
exec -- "${ZRUN}" ':: deploy / publish' "${@}"
|
|
!!
|
|
|
|
|
|
|
|
|
|
<< deploy / publish
|
|
|
|
|
|
if test "${#}" -eq 0 ; then
|
|
_main_0=all
|
|
else
|
|
_main_0="${1}"
|
|
shift -- 1
|
|
fi
|
|
|
|
if test "${#}" -ge 1 ; then
|
|
_variant_0="${1}"
|
|
shift -- 1
|
|
else
|
|
_variant_0=all
|
|
fi
|
|
|
|
test "${#}" -eq 0
|
|
|
|
|
|
_outputs="$( exec -- "${ZRUN}" ':: workbench / outputs' )"
|
|
test -d "${_outputs}"
|
|
|
|
_publish="$( exec -- "${ZRUN}" ':: workbench / publish' )"
|
|
test -d "${_publish}"
|
|
|
|
_embedded="${__EMBEDDED}"
|
|
test -d "${_embedded}"
|
|
|
|
_minisign='./documentation/releases/minisign'
|
|
test -d "${_minisign}"
|
|
if test ! -e "${_minisign}/signatures" ; then
|
|
mkdir -- "${_minisign}/signatures"
|
|
fi
|
|
|
|
_gpg='./documentation/releases/pgp'
|
|
test -d "${_gpg}"
|
|
if test ! -e "${_gpg}/signatures" ; then
|
|
mkdir -- "${_gpg}/signatures"
|
|
fi
|
|
|
|
_gpg_sign_key="$( exec -- cat -- "${_gpg}/keys/public.txt" )"
|
|
|
|
|
|
"${ZRUN}" ':: documentation / all / render / forced'
|
|
#! "${ZRUN}" ':: sources / generate / sbom'
|
|
"${ZRUN}" ':: sources / embedded / bundle'
|
|
export -- __SOURCES__PREPARED=true
|
|
|
|
|
|
if test "${__DEPLOY_NOGITHUB:-}" == true ; then
|
|
_github_publish=false
|
|
else
|
|
_github_publish=true
|
|
fi
|
|
|
|
|
|
readarray -t -- _mains < <( exec -- "${ZRUN}" ':: deploy / list / main' )
|
|
readarray -t -- _variants < <( exec -- "${ZRUN}" ':: deploy / list / variant' )
|
|
|
|
|
|
_build_version="$( exec -- cat -- "${_embedded}/build/version.txt" )"
|
|
case "${_build_version}" in
|
|
( 0.0.0 | *.0 )
|
|
_build_release=false
|
|
_build_suffix='--preview'
|
|
;;
|
|
( * )
|
|
_build_release=true
|
|
_build_suffix=''
|
|
_gpg_sign=true
|
|
_minisign_sign=true
|
|
;;
|
|
esac
|
|
|
|
|
|
if test "${__DEPLOY_NOGPGSIGN:-}" == true ; then
|
|
_gpg_sign=false
|
|
else
|
|
_gpg_sign="${_gpg_sign:-false}"
|
|
fi
|
|
|
|
if test "${__DEPLOY_NOMINSIGN:-}" == true ; then
|
|
_minisign_sign=false
|
|
else
|
|
_minisign_sign="${_minisign_sign:-true}"
|
|
fi
|
|
|
|
|
|
if test "${_build_release}" == true ; then
|
|
for _main in "${_mains[@]}" ; do
|
|
if test "${_main_0}" != all -a "${_main_0}" != "${_main}" ; then continue ; fi
|
|
for _variant in "${_variants[@]}" ; do
|
|
if test "${_variant_0}" != all -a "${_variant_0}" != "${_variant}" ; then continue ; fi
|
|
|
|
if test -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}" ; then
|
|
printf -- '[ee] release already exists for `%s` for `%s`!\n' "${_main}" "${_variant}" >&2
|
|
exit -- 1
|
|
fi
|
|
|
|
done
|
|
done
|
|
fi
|
|
|
|
|
|
if test "${_github_publish}" == true ; then
|
|
|
|
if ! git diff --quiet -- "${_embedded}/build" ; then
|
|
printf -- '[--]\n' >&2
|
|
git add -p -- "${_embedded}/build"
|
|
git commit -m '[build] Snapshot build meta-data.' -- "${_embedded}/build"
|
|
printf -- '[--]\n' >&2
|
|
fi
|
|
|
|
if ! git diff --quiet ; then
|
|
printf -- '[ee] dirty repository (before build); aborting!\n' >&2
|
|
exit -- 1
|
|
fi
|
|
if ! git diff --cached --quiet ; then
|
|
printf -- '[ee] dirty repository (before build); aborting!\n' >&2
|
|
exit -- 1
|
|
fi
|
|
fi
|
|
|
|
|
|
printf -- '[--]\n' >&2
|
|
printf -- '[ii] releasing `%s` for `%s` for `%s`...\n' "${_main_0}" "${_variant_0}" "${_build_version}${_build_suffix}" >&2
|
|
printf -- '[--]\n' >&2
|
|
|
|
"${ZRUN}" ':: deploy / release' "${_main_0}" "${_variant_0}"
|
|
|
|
printf -- '[--]\n' >&2
|
|
|
|
|
|
if test "${_github_publish}" == true ; then
|
|
|
|
if ! git diff --quiet ; then
|
|
printf -- '[ee] dirty repository (after build); aborting!\n' >&2
|
|
exit -- 1
|
|
fi
|
|
if ! git diff --cached --quiet ; then
|
|
printf -- '[ee] dirty repository (after build); aborting!\n' >&2
|
|
exit -- 1
|
|
fi
|
|
fi
|
|
|
|
|
|
printf -- '[--]\n' >&2
|
|
printf -- '[ii] publishing `%s` for `%s` for `%s`...\n' "${_main_0}" "${_variant_0}" "${_build_version}${_build_suffix}" >&2
|
|
printf -- '[--]\n' >&2
|
|
|
|
for _main in "${_mains[@]}" ; do
|
|
if test "${_main_0}" != all -a "${_main_0}" != "${_main}" ; then continue ; fi
|
|
for _variant in "${_variants[@]}" ; do
|
|
if test "${_variant_0}" != all -a "${_variant_0}" != "${_variant}" ; then continue ; fi
|
|
|
|
printf -- '[ii] publishing `%s` for `%s` for `%s`...\n' "${_main}" "${_variant}" "${_build_version}${_build_suffix}" >&2
|
|
|
|
rsync -i -t -p --chmod=0555 -- \
|
|
"${_outputs}/binaries/${_main}--release--${_variant}" \
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}" \
|
|
#
|
|
|
|
if test "${_gpg_sign}" == true ; then
|
|
|
|
if test -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" ; then
|
|
if ! \
|
|
gpg --verify -- \
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" \
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}" \
|
|
< /dev/null > /dev/null 2> /dev/null \
|
|
; then
|
|
rm -- "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc"
|
|
fi
|
|
fi
|
|
|
|
if test ! -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" ; then
|
|
printf -- '[ii] signing `%s` for `%s` for `%s` (with GnuPG)...\n' "${_main}" "${_variant}" "${_build_version}${_build_suffix}" >&2
|
|
if test -e "${_gpg}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" ; then
|
|
rm -- "${_gpg}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc"
|
|
fi
|
|
if test ! -e "${_gpg}/signatures/v${_build_version}${_build_suffix}" ; then
|
|
mkdir -- "${_gpg}/signatures/v${_build_version}${_build_suffix}"
|
|
fi
|
|
for _retry in 1 2 3 4 ; do
|
|
if \
|
|
gpg --sign --detach-sign --armor \
|
|
--default-key "${_gpg_sign_key}" \
|
|
--output "${_gpg}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" \
|
|
-- "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}" \
|
|
< /dev/null > /dev/null 2> /dev/null \
|
|
; then break ; fi
|
|
done
|
|
cp -T -- \
|
|
"${_gpg}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" \
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" \
|
|
#
|
|
else
|
|
cp -T -- \
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" \
|
|
"${_gpg}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" \
|
|
#
|
|
fi
|
|
|
|
gpg --verify -- \
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" \
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}" \
|
|
< /dev/null > /dev/null 2> /dev/null \
|
|
#
|
|
|
|
else
|
|
if test -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" ; then
|
|
rm -- "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc"
|
|
fi
|
|
fi
|
|
|
|
if test "${_minisign_sign}" == true ; then
|
|
|
|
if test -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" ; then
|
|
if ! \
|
|
minisign -V \
|
|
-p "${_minisign}/keys/public.pub" \
|
|
-x "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" \
|
|
-m "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}" \
|
|
< /dev/null > /dev/null 2> /dev/null \
|
|
; then
|
|
rm -- "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig"
|
|
fi
|
|
fi
|
|
|
|
if test ! -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" ; then
|
|
printf -- '[ii] signing `%s` for `%s` for `%s` (with minisign)...\n' "${_main}" "${_variant}" "${_build_version}${_build_suffix}" >&2
|
|
if test -e "${_minisign}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" ; then
|
|
rm -- "${_minisign}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig"
|
|
fi
|
|
if test ! -e "${_minisign}/signatures/v${_build_version}${_build_suffix}" ; then
|
|
mkdir -- "${_minisign}/signatures/v${_build_version}${_build_suffix}"
|
|
fi
|
|
for _retry in 1 2 3 4 ; do
|
|
if \
|
|
minisign -S \
|
|
-t "${_main}--${_variant}--v${_build_version}${_build_suffix}" \
|
|
-s <( exec -- gpg --decrypt < "${_minisign}/keys/private.asc" 2> /dev/null ) \
|
|
-x "${_minisign}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" \
|
|
-m "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}" \
|
|
< /dev/null > /dev/null 2> /dev/null \
|
|
; then break ; fi
|
|
done
|
|
cp -T -- \
|
|
"${_minisign}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" \
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" \
|
|
#
|
|
else
|
|
cp -T -- \
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" \
|
|
"${_minisign}/signatures/v${_build_version}${_build_suffix}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" \
|
|
#
|
|
fi
|
|
|
|
minisign -V \
|
|
-p "${_minisign}/keys/public.pub" \
|
|
-x "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" \
|
|
-m "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}" \
|
|
< /dev/null > /dev/null 2> /dev/null \
|
|
#
|
|
|
|
else
|
|
if test -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" ; then
|
|
rm -- "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig"
|
|
fi
|
|
fi
|
|
|
|
if test "${_build_release}" == true ; then
|
|
|
|
ln -s -T -f -- "./${_main}--${_variant}--v${_build_version}${_build_suffix}" "${_publish}/${_variant}/${_main}${_build_suffix}"
|
|
|
|
if test -e "${_publish}/${_variant}/${_main}${_build_suffix}.asc" ; then
|
|
rm -- "${_publish}/${_variant}/${_main}${_build_suffix}.asc"
|
|
fi
|
|
if test -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" ; then
|
|
ln -s -T -f -- "./${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" "${_publish}/${_variant}/${_main}${_build_suffix}.asc"
|
|
fi
|
|
|
|
if test -e "${_publish}/${_variant}/${_main}${_build_suffix}.sig" ; then
|
|
rm -- "${_publish}/${_variant}/${_main}${_build_suffix}.sig"
|
|
fi
|
|
if test -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" ; then
|
|
ln -s -T -f -- "./${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" "${_publish}/${_variant}/${_main}${_build_suffix}.sig"
|
|
fi
|
|
fi
|
|
|
|
done
|
|
done
|
|
|
|
printf -- '[--]\n' >&2
|
|
|
|
|
|
if test "${_github_publish}" == true ; then
|
|
|
|
printf -- '[--]\n' >&2
|
|
printf -- '[ii] tagging and pushing for `%s` (on GitHub)...\n' "${_build_version}${_build_suffix}" >&2
|
|
|
|
if test -e "${_gpg}/signatures/v${_build_version}${_build_suffix}" ; then
|
|
git add --all -- "${_gpg}/signatures/v${_build_version}${_build_suffix}"
|
|
if ! git diff --cached --quiet -- "${_gpg}/signatures/v${_build_version}${_build_suffix}" ; then
|
|
printf -- '[--]\n' >&2
|
|
git commit -m '[release] Import release PGP signatures.' -- "${_gpg}/signatures/v${_build_version}${_build_suffix}"
|
|
printf -- '[--]\n' >&2
|
|
fi
|
|
fi
|
|
|
|
if test -e "${_minisign}/signatures/v${_build_version}${_build_suffix}" ; then
|
|
git add --all -- "${_minisign}/signatures/v${_build_version}${_build_suffix}"
|
|
if ! git diff --cached --quiet -- "${_minisign}/signatures/v${_build_version}${_build_suffix}" ; then
|
|
printf -- '[--]\n' >&2
|
|
git commit -m '[release] Import release `minisign` signatures.' -- "${_minisign}/signatures/v${_build_version}${_build_suffix}"
|
|
printf -- '[--]\n' >&2
|
|
fi
|
|
fi
|
|
|
|
if ! git diff --quiet ; then
|
|
printf -- '[ee] dirty repository (after build); aborting!\n' >&2
|
|
exit -- 1
|
|
fi
|
|
if ! git diff --cached --quiet ; then
|
|
printf -- '[ee] dirty repository (after build); aborting!\n' >&2
|
|
exit -- 1
|
|
fi
|
|
|
|
if test "${_build_release}" == true ; then
|
|
git tag --sign -m "[release] Release \`v${_build_version}\`." -- "v${_build_version}" HEAD
|
|
else
|
|
git tag --sign -m "[preview] Preview \`v${_build_version}\`." --force -- preview HEAD
|
|
fi
|
|
|
|
"${ZRUN}" ':: github / push'
|
|
|
|
printf -- '[--]\n' >&2
|
|
fi
|
|
|
|
|
|
if test "${_github_publish}" == true ; then
|
|
|
|
printf -- '[--]\n' >&2
|
|
printf -- '[ii] publishing `%s` for `%s` for `%s` (on GitHub)...\n' "${_main_0}" "${_variant_0}" "${_build_version}${_build_suffix}" >&2
|
|
printf -- '[--]\n' >&2
|
|
|
|
_gh_release_files=()
|
|
|
|
for _main in "${_mains[@]}" ; do
|
|
if test "${_main_0}" != all -a "${_main_0}" != "${_main}" ; then continue ; fi
|
|
for _variant in "${_variants[@]}" ; do
|
|
if test "${_variant_0}" != all -a "${_variant_0}" != "${_variant}" ; then continue ; fi
|
|
|
|
printf -- '[ii] publishing `%s` for `%s` for `%s` (on GitHub)...\n' "${_main}" "${_variant}" "${_build_version}${_build_suffix}" >&2
|
|
|
|
_gh_release_files+=(
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}"
|
|
)
|
|
|
|
if test -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc" ; then
|
|
_gh_release_files+=(
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.asc"
|
|
)
|
|
fi
|
|
|
|
if test -e "${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig" ; then
|
|
_gh_release_files+=(
|
|
"${_publish}/${_variant}/${_main}--${_variant}--v${_build_version}${_build_suffix}.sig"
|
|
)
|
|
fi
|
|
|
|
done
|
|
done
|
|
|
|
if test "${_build_release}" == true ; then
|
|
gh release upload --clobber -- "v${_build_version}" \
|
|
"${_gh_release_files[@]}" \
|
|
#
|
|
else
|
|
gh release upload --clobber -- preview \
|
|
"${_gh_release_files[@]}" \
|
|
#
|
|
fi
|
|
|
|
printf -- '[--]\n' >&2
|
|
fi
|
|
!!
|
|
|
|
|
|
|
|
|
|
<< deploy / release
|
|
|
|
if test "${#}" -ge 1 ; then
|
|
_main_0="${1}"
|
|
shift -- 1
|
|
else
|
|
_main_0=all
|
|
fi
|
|
|
|
if test "${#}" -ge 1 ; then
|
|
_variant_0="${1}"
|
|
shift -- 1
|
|
else
|
|
_variant_0='all'
|
|
fi
|
|
|
|
test "${#}" -eq 0
|
|
|
|
if test "${__DEPLOY_NORELEASE:-}" == true ; then
|
|
exit -- 0
|
|
fi
|
|
|
|
if test -z "${__SOURCES__PREPARED:-}" ; then
|
|
"${ZRUN}" ':: sources / embedded / bundle'
|
|
export -- __SOURCES__PREPARED=true
|
|
fi
|
|
|
|
readarray -t -- _mains < <( exec -- "${ZRUN}" ':: deploy / list / main' )
|
|
readarray -t -- _variants < <( exec -- "${ZRUN}" ':: deploy / list / variant' )
|
|
|
|
for _main in "${_mains[@]}" ; do
|
|
if test "${_main_0}" != all -a "${_main_0}" != "${_main}" ; then continue ; fi
|
|
for _variant in "${_variants[@]}" ; do
|
|
if test "${_variant_0}" != all -a "${_variant_0}" != "${_variant}" ; then continue ; fi
|
|
|
|
printf -- '[ii] releasing `%s` for `%s`...\n' "${_main}" "${_variant}" >&2
|
|
|
|
"${ZRUN}" ":: go / build / * / release / ${_variant%%--*} / ${_variant#*--}" "${_main}"
|
|
|
|
done
|
|
done
|
|
!!
|
|
|
|
|
|
|
|
|
|
<<== deploy / generate
|
|
|
|
test "${#}" -eq 0
|
|
|
|
readarray -t -- _mains < <( exec -- "${ZRUN}" ':: deploy / list / main' )
|
|
readarray -t -- _variants < <( exec -- "${ZRUN}" ':: deploy / list / variant' )
|
|
|
|
for _main in "${_mains[@]}" ; do
|
|
|
|
printf -- ':: deploy / publish / %s / all :: exec -- "${ZRUN}" ":: deploy / publish" %q "${@}"\n' "${_main}" "${_main}"
|
|
printf -- ':: deploy / publish / %s / all / no-github :: exec -- "${ZRUN}" ":: deploy / publish / no-github" %q "${@}"\n' "${_main}" "${_main}"
|
|
|
|
printf -- ':: deploy / release / %s / all :: exec -- "${ZRUN}" ":: deploy / release" %q %q "${@}"\n' "${_main}" all "${_main}"
|
|
|
|
for _variant in "${_variants[@]}" ; do
|
|
printf -- ':: deploy / rsync / %s / %s :: exec -- "${ZRUN}" ":: deploy / rsync / *" %q %q "${@}"\n' "${_main}" "${_variant}" "${_main}" "${_variant}"
|
|
printf -- ':: deploy / release / %s / %s :: exec -- "${ZRUN}" ":: deploy / release" %q %q "${@}"\n' "${_main}" "${_variant}" "${_main}" "${_variant}"
|
|
done
|
|
|
|
done
|
|
!!
|
|
|
|
|