Adds requirements, streamlines CLI helper procedures
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
update_cache: true
|
||||
name:
|
||||
- python3-virtualenv
|
||||
- cpulimit
|
||||
- ffmpeg
|
||||
- git
|
||||
- screen
|
||||
@@ -21,6 +22,7 @@
|
||||
ansible.builtin.pacman:
|
||||
update_cache: true
|
||||
name:
|
||||
- cpulimit
|
||||
- ffmpeg
|
||||
- git
|
||||
- screen
|
||||
|
||||
444
tools/prepare.sh
Executable file
444
tools/prepare.sh
Executable file
@@ -0,0 +1,444 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -u
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
CONFIG_DIR="${FFX_CONFIG_DIR:-${HOME}/.local/etc}"
|
||||
CONFIG_FILE="${FFX_CONFIG_FILE:-${CONFIG_DIR}/ffx.json}"
|
||||
VAR_DIR="${FFX_VAR_DIR:-${HOME}/.local/var/ffx}"
|
||||
LOG_DIR="${FFX_LOG_DIR:-${HOME}/.local/var/log}"
|
||||
DATABASE_FILE="${FFX_DATABASE_FILE:-${VAR_DIR}/ffx.db}"
|
||||
|
||||
CHECK_ONLY=0
|
||||
|
||||
MUTATIONS=0
|
||||
INSTALL_FAILURES=0
|
||||
READINESS_FAILURES=0
|
||||
|
||||
MISSING_REQUIRED_SYSTEM=()
|
||||
MISSING_OPTIONAL_SYSTEM=()
|
||||
|
||||
COLOR_RESET=""
|
||||
COLOR_GREEN=""
|
||||
COLOR_YELLOW=""
|
||||
COLOR_RED=""
|
||||
|
||||
if [ -t 1 ]; then
|
||||
COLOR_RESET="$(printf '\033[0m')"
|
||||
COLOR_GREEN="$(printf '\033[32m')"
|
||||
COLOR_YELLOW="$(printf '\033[33m')"
|
||||
COLOR_RED="$(printf '\033[31m')"
|
||||
fi
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [--check] [--help]
|
||||
|
||||
Prepare the local FFX development environment for this repository.
|
||||
|
||||
Options:
|
||||
--check Report readiness only. Do not create, install, or modify.
|
||||
--help Show this help text.
|
||||
|
||||
Environment overrides:
|
||||
FFX_CONFIG_DIR Override the parent directory for the seeded ffx.json file.
|
||||
FFX_CONFIG_FILE Override the seeded config file path directly.
|
||||
FFX_VAR_DIR Override the default data directory.
|
||||
FFX_LOG_DIR Override the default log directory.
|
||||
FFX_DATABASE_FILE Override the database path written into a newly seeded config.
|
||||
EOF
|
||||
}
|
||||
|
||||
status_ok() {
|
||||
printf '%sok%s' "${COLOR_GREEN}" "${COLOR_RESET}"
|
||||
}
|
||||
|
||||
status_warn() {
|
||||
printf '%swarn%s' "${COLOR_YELLOW}" "${COLOR_RESET}"
|
||||
}
|
||||
|
||||
status_fail() {
|
||||
printf '%sfailed%s' "${COLOR_RED}" "${COLOR_RESET}"
|
||||
}
|
||||
|
||||
report_component() {
|
||||
local level="$1"
|
||||
local label="$2"
|
||||
local detail="$3"
|
||||
local rendered_status=""
|
||||
|
||||
case "${level}" in
|
||||
ok)
|
||||
rendered_status="$(status_ok)"
|
||||
;;
|
||||
warn)
|
||||
rendered_status="$(status_warn)"
|
||||
;;
|
||||
*)
|
||||
rendered_status="$(status_fail)"
|
||||
;;
|
||||
esac
|
||||
|
||||
printf '[%s] %s%s\n' "${rendered_status}" "${label}" "${detail:+: $detail}"
|
||||
}
|
||||
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
check_command_component() {
|
||||
command_exists "$2"
|
||||
}
|
||||
|
||||
check_tmdb_key() {
|
||||
[ -n "${TMDB_API_KEY:-}" ]
|
||||
}
|
||||
|
||||
check_seeded_dir() {
|
||||
[ -d "$1" ]
|
||||
}
|
||||
|
||||
check_seeded_file() {
|
||||
[ -f "$1" ]
|
||||
}
|
||||
|
||||
component_detail() {
|
||||
case "$1" in
|
||||
git|python3|ffmpeg|ffprobe|cpulimit)
|
||||
command -v "$1" || printf "command '%s' not found" "$1"
|
||||
;;
|
||||
tmdb-key)
|
||||
if check_tmdb_key; then
|
||||
printf 'TMDB_API_KEY is set'
|
||||
else
|
||||
printf 'TMDB_API_KEY is unset; TMDB-backed flows will be skipped or fail'
|
||||
fi
|
||||
;;
|
||||
config-dir)
|
||||
if check_seeded_dir "${CONFIG_DIR}"; then
|
||||
printf '%s' "${CONFIG_DIR}"
|
||||
else
|
||||
printf 'missing; prep can create it'
|
||||
fi
|
||||
;;
|
||||
var-dir)
|
||||
if check_seeded_dir "${VAR_DIR}"; then
|
||||
printf '%s' "${VAR_DIR}"
|
||||
else
|
||||
printf 'missing; prep can create it'
|
||||
fi
|
||||
;;
|
||||
log-dir)
|
||||
if check_seeded_dir "${LOG_DIR}"; then
|
||||
printf '%s' "${LOG_DIR}"
|
||||
else
|
||||
printf 'missing; prep can create it'
|
||||
fi
|
||||
;;
|
||||
ffx-config)
|
||||
if check_seeded_file "${CONFIG_FILE}"; then
|
||||
printf '%s' "${CONFIG_FILE}"
|
||||
else
|
||||
printf 'missing; prep can seed a default non-destructively'
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
report_toolchain_component() {
|
||||
local label="$1"
|
||||
local command_name="$2"
|
||||
local required="$3"
|
||||
|
||||
if check_command_component "${label}" "${command_name}" "${required}"; then
|
||||
report_component ok "${label}" "$(component_detail "${command_name}")"
|
||||
else
|
||||
if [ "${required}" = "required" ]; then
|
||||
report_component failed "${label}" "$(component_detail "${command_name}")"
|
||||
MISSING_REQUIRED_SYSTEM+=("${command_name}")
|
||||
READINESS_FAILURES=$((READINESS_FAILURES + 1))
|
||||
else
|
||||
report_component warn "${label}" "$(component_detail "${command_name}")"
|
||||
MISSING_OPTIONAL_SYSTEM+=("${command_name}")
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
report_tmdb_component() {
|
||||
if check_tmdb_key; then
|
||||
report_component ok "TMDB API key" "$(component_detail tmdb-key)"
|
||||
else
|
||||
report_component warn "TMDB API key" "$(component_detail tmdb-key)"
|
||||
fi
|
||||
}
|
||||
|
||||
report_seeded_component() {
|
||||
local label="$1"
|
||||
local key="$2"
|
||||
local required="$3"
|
||||
local ok=1
|
||||
|
||||
case "${key}" in
|
||||
config-dir)
|
||||
check_seeded_dir "${CONFIG_DIR}" || ok=0
|
||||
;;
|
||||
var-dir)
|
||||
check_seeded_dir "${VAR_DIR}" || ok=0
|
||||
;;
|
||||
log-dir)
|
||||
check_seeded_dir "${LOG_DIR}" || ok=0
|
||||
;;
|
||||
ffx-config)
|
||||
check_seeded_file "${CONFIG_FILE}" || ok=0
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "${ok}" -eq 1 ]; then
|
||||
report_component ok "${label}" "$(component_detail "${key}")"
|
||||
else
|
||||
if [ "${required}" = "required" ]; then
|
||||
report_component failed "${label}" "$(component_detail "${key}")"
|
||||
READINESS_FAILURES=$((READINESS_FAILURES + 1))
|
||||
else
|
||||
report_component warn "${label}" "$(component_detail "${key}")"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
print_dependency_status() {
|
||||
READINESS_FAILURES=0
|
||||
MISSING_REQUIRED_SYSTEM=()
|
||||
MISSING_OPTIONAL_SYSTEM=()
|
||||
|
||||
echo "Dependency status:"
|
||||
report_toolchain_component "git" "git" "required"
|
||||
report_toolchain_component "python3" "python3" "required"
|
||||
report_toolchain_component "ffmpeg" "ffmpeg" "required"
|
||||
report_toolchain_component "ffprobe" "ffprobe" "required"
|
||||
report_toolchain_component "cpulimit" "cpulimit" "required"
|
||||
report_tmdb_component
|
||||
}
|
||||
|
||||
print_seeded_file_status() {
|
||||
echo "Seeded local files:"
|
||||
report_seeded_component "Config dir" "config-dir" "optional"
|
||||
report_seeded_component "Var dir" "var-dir" "optional"
|
||||
report_seeded_component "Log dir" "log-dir" "optional"
|
||||
report_seeded_component "ffx config" "ffx-config" "optional"
|
||||
}
|
||||
|
||||
detect_package_manager() {
|
||||
if command_exists apt-get; then
|
||||
printf 'apt-get\n'
|
||||
return 0
|
||||
fi
|
||||
if command_exists pacman; then
|
||||
printf 'pacman\n'
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
run_root_command() {
|
||||
if [ "${EUID}" -eq 0 ]; then
|
||||
"$@"
|
||||
elif command_exists sudo; then
|
||||
sudo "$@"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_system_requirements() {
|
||||
local package_manager
|
||||
|
||||
if ! package_manager="$(detect_package_manager)"; then
|
||||
printf 'No supported package manager found for automatic preparation.\n' >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
|
||||
case "${package_manager}" in
|
||||
apt-get)
|
||||
printf 'Installing missing system dependencies via apt-get...\n'
|
||||
if ! run_root_command apt-get update; then
|
||||
printf 'apt-get update failed.\n' >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
if ! run_root_command apt-get install -y git python3 ffmpeg cpulimit; then
|
||||
printf 'apt-get install failed.\n' >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
pacman)
|
||||
printf 'Installing missing system dependencies via pacman...\n'
|
||||
if ! run_root_command pacman -Sy --noconfirm git python ffmpeg cpulimit; then
|
||||
printf 'pacman install failed.\n' >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
MUTATIONS=$((MUTATIONS + 1))
|
||||
return 0
|
||||
}
|
||||
|
||||
seed_default_config() {
|
||||
if [ "${CHECK_ONLY}" -eq 1 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local created_any=0
|
||||
|
||||
if [ ! -d "${CONFIG_DIR}" ]; then
|
||||
printf 'Creating config dir at %s...\n' "${CONFIG_DIR}"
|
||||
if ! mkdir -p "${CONFIG_DIR}"; then
|
||||
printf 'Failed to create config dir at %s.\n' "${CONFIG_DIR}" >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
created_any=1
|
||||
fi
|
||||
|
||||
if [ ! -d "${VAR_DIR}" ]; then
|
||||
printf 'Creating var dir at %s...\n' "${VAR_DIR}"
|
||||
if ! mkdir -p "${VAR_DIR}"; then
|
||||
printf 'Failed to create var dir at %s.\n' "${VAR_DIR}" >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
created_any=1
|
||||
fi
|
||||
|
||||
if [ ! -d "${LOG_DIR}" ]; then
|
||||
printf 'Creating log dir at %s...\n' "${LOG_DIR}"
|
||||
if ! mkdir -p "${LOG_DIR}"; then
|
||||
printf 'Failed to create log dir at %s.\n' "${LOG_DIR}" >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
created_any=1
|
||||
fi
|
||||
|
||||
if [ ! -f "${CONFIG_FILE}" ]; then
|
||||
printf 'Seeding ffx config at %s...\n' "${CONFIG_FILE}"
|
||||
if ! cat >"${CONFIG_FILE}" <<EOF
|
||||
{
|
||||
"databasePath": "${DATABASE_FILE}",
|
||||
"logDirectory": "${LOG_DIR}",
|
||||
"metadata": {
|
||||
"signature": {
|
||||
"RECODED_WITH": "FFX"
|
||||
},
|
||||
"remove": [
|
||||
"VERSION-eng",
|
||||
"creation_time",
|
||||
"NAME"
|
||||
],
|
||||
"streams": {
|
||||
"remove": [
|
||||
"BPS",
|
||||
"NUMBER_OF_FRAMES",
|
||||
"NUMBER_OF_BYTES",
|
||||
"_STATISTICS_WRITING_APP",
|
||||
"_STATISTICS_WRITING_DATE_UTC",
|
||||
"_STATISTICS_TAGS",
|
||||
"BPS-eng",
|
||||
"DURATION-eng",
|
||||
"NUMBER_OF_FRAMES-eng",
|
||||
"NUMBER_OF_BYTES-eng",
|
||||
"_STATISTICS_WRITING_APP-eng",
|
||||
"_STATISTICS_WRITING_DATE_UTC-eng",
|
||||
"_STATISTICS_TAGS-eng"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
then
|
||||
printf 'Failed to write ffx config at %s.\n' "${CONFIG_FILE}" >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
created_any=1
|
||||
fi
|
||||
|
||||
if [ "${created_any}" -eq 1 ]; then
|
||||
MUTATIONS=$((MUTATIONS + 1))
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--check)
|
||||
CHECK_ONLY=1
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
printf 'Unknown option: %s\n\n' "$1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
print_dependency_status
|
||||
|
||||
if [ "${CHECK_ONLY}" -eq 0 ] && [ "${#MISSING_REQUIRED_SYSTEM[@]}" -gt 0 ]; then
|
||||
install_system_requirements
|
||||
|
||||
echo
|
||||
print_dependency_status
|
||||
fi
|
||||
|
||||
echo
|
||||
print_seeded_file_status
|
||||
|
||||
if [ "${CHECK_ONLY}" -eq 0 ]; then
|
||||
seed_default_config
|
||||
echo
|
||||
print_seeded_file_status
|
||||
fi
|
||||
|
||||
echo
|
||||
if [ "${INSTALL_FAILURES}" -gt 0 ]; then
|
||||
echo "One or more install steps failed; see the status checks above." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "${READINESS_FAILURES}" -gt 0 ]; then
|
||||
if [ "${CHECK_ONLY}" -eq 1 ]; then
|
||||
echo "Required system prerequisites are incomplete." >&2
|
||||
else
|
||||
echo "Required components are still missing after preparation." >&2
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "${CHECK_ONLY}" -eq 1 ]; then
|
||||
echo "The FFX preparation environment is ready."
|
||||
elif [ "${MUTATIONS}" -gt 0 ]; then
|
||||
echo "The FFX preparation environment is ready."
|
||||
else
|
||||
echo "The FFX preparation environment is already prepared."
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
350
tools/setup.sh
Executable file
350
tools/setup.sh
Executable file
@@ -0,0 +1,350 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -u
|
||||
|
||||
ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
VENV_DIR="${HOME}/.local/share/ffx.venv"
|
||||
VENV_BIN_DIR="${VENV_DIR}/bin"
|
||||
VENV_PYTHON="${VENV_BIN_DIR}/python"
|
||||
VENV_PIP="${VENV_BIN_DIR}/pip"
|
||||
VENV_FFX="${VENV_BIN_DIR}/ffx"
|
||||
BASHRC_FILE="${HOME}/.bashrc"
|
||||
ALIAS_BLOCK_BEGIN="# >>> ffx alias >>>"
|
||||
ALIAS_BLOCK_END="# <<< ffx alias <<<"
|
||||
ALIAS_LINE="alias ffx=\"${VENV_FFX}\""
|
||||
|
||||
CHECK_ONLY=0
|
||||
READINESS_FAILURES=0
|
||||
INSTALL_FAILURES=0
|
||||
|
||||
COLOR_RESET=""
|
||||
COLOR_GREEN=""
|
||||
COLOR_YELLOW=""
|
||||
COLOR_RED=""
|
||||
|
||||
if [ -t 1 ]; then
|
||||
COLOR_RESET="$(printf '\033[0m')"
|
||||
COLOR_GREEN="$(printf '\033[32m')"
|
||||
COLOR_YELLOW="$(printf '\033[33m')"
|
||||
COLOR_RED="$(printf '\033[31m')"
|
||||
fi
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [--check] [--help]
|
||||
|
||||
Prepare the persistent FFX bundle virtualenv at:
|
||||
${VENV_DIR}
|
||||
|
||||
Actions:
|
||||
- create or reuse ${VENV_DIR}
|
||||
- install this repository into the venv with pip --editable
|
||||
- ensure ${BASHRC_FILE} exposes alias ffx -> ${VENV_FFX}
|
||||
|
||||
Options:
|
||||
--check Report readiness only. Do not create or modify anything.
|
||||
--help Show this help text.
|
||||
EOF
|
||||
}
|
||||
|
||||
status_ok() {
|
||||
printf '%sok%s' "${COLOR_GREEN}" "${COLOR_RESET}"
|
||||
}
|
||||
|
||||
status_warn() {
|
||||
printf '%swarn%s' "${COLOR_YELLOW}" "${COLOR_RESET}"
|
||||
}
|
||||
|
||||
status_fail() {
|
||||
printf '%sfailed%s' "${COLOR_RED}" "${COLOR_RESET}"
|
||||
}
|
||||
|
||||
report_component() {
|
||||
local level="$1"
|
||||
local label="$2"
|
||||
local detail="$3"
|
||||
local rendered_status=""
|
||||
|
||||
case "${level}" in
|
||||
ok)
|
||||
rendered_status="$(status_ok)"
|
||||
;;
|
||||
warn)
|
||||
rendered_status="$(status_warn)"
|
||||
;;
|
||||
*)
|
||||
rendered_status="$(status_fail)"
|
||||
;;
|
||||
esac
|
||||
|
||||
printf '[%s] %s%s\n' "${rendered_status}" "${label}" "${detail:+: $detail}"
|
||||
}
|
||||
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
check_python3() {
|
||||
command_exists python3
|
||||
}
|
||||
|
||||
check_venv_dir() {
|
||||
[ -x "${VENV_PYTHON}" ]
|
||||
}
|
||||
|
||||
check_venv_pip() {
|
||||
check_venv_dir && "${VENV_PIP}" --version >/dev/null 2>&1
|
||||
}
|
||||
|
||||
check_venv_ffx() {
|
||||
[ -x "${VENV_FFX}" ]
|
||||
}
|
||||
|
||||
check_bashrc_file() {
|
||||
[ -f "${BASHRC_FILE}" ]
|
||||
}
|
||||
|
||||
check_bashrc_alias() {
|
||||
check_bashrc_file && grep -Fqx "${ALIAS_LINE}" "${BASHRC_FILE}"
|
||||
}
|
||||
|
||||
detail_python3() {
|
||||
command -v python3 || printf "command 'python3' not found"
|
||||
}
|
||||
|
||||
detail_venv_dir() {
|
||||
if check_venv_dir; then
|
||||
printf '%s' "${VENV_DIR}"
|
||||
else
|
||||
printf 'missing %s' "${VENV_DIR}"
|
||||
fi
|
||||
}
|
||||
|
||||
detail_venv_pip() {
|
||||
if check_venv_pip; then
|
||||
"${VENV_PIP}" --version
|
||||
else
|
||||
printf 'missing pip in %s' "${VENV_DIR}"
|
||||
fi
|
||||
}
|
||||
|
||||
detail_venv_ffx() {
|
||||
if check_venv_ffx; then
|
||||
printf '%s' "${VENV_FFX}"
|
||||
else
|
||||
printf 'missing %s' "${VENV_FFX}"
|
||||
fi
|
||||
}
|
||||
|
||||
detail_bashrc_file() {
|
||||
if check_bashrc_file; then
|
||||
printf '%s' "${BASHRC_FILE}"
|
||||
else
|
||||
printf 'missing %s; prep can create it' "${BASHRC_FILE}"
|
||||
fi
|
||||
}
|
||||
|
||||
detail_bashrc_alias() {
|
||||
if check_bashrc_alias; then
|
||||
printf '%s' "${ALIAS_LINE}"
|
||||
else
|
||||
printf 'missing alias line for %s' "${VENV_FFX}"
|
||||
fi
|
||||
}
|
||||
|
||||
print_status_report() {
|
||||
READINESS_FAILURES=0
|
||||
|
||||
echo "Dependency status:"
|
||||
if check_python3; then
|
||||
report_component ok "python3" "$(detail_python3)"
|
||||
else
|
||||
report_component failed "python3" "$(detail_python3)"
|
||||
READINESS_FAILURES=$((READINESS_FAILURES + 1))
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Bundle venv status:"
|
||||
if check_venv_dir; then
|
||||
report_component ok "bundle virtualenv" "$(detail_venv_dir)"
|
||||
else
|
||||
report_component failed "bundle virtualenv" "$(detail_venv_dir)"
|
||||
READINESS_FAILURES=$((READINESS_FAILURES + 1))
|
||||
fi
|
||||
|
||||
if check_venv_pip; then
|
||||
report_component ok "bundle pip" "$(detail_venv_pip)"
|
||||
else
|
||||
report_component failed "bundle pip" "$(detail_venv_pip)"
|
||||
READINESS_FAILURES=$((READINESS_FAILURES + 1))
|
||||
fi
|
||||
|
||||
if check_venv_ffx; then
|
||||
report_component ok "bundle ffx" "$(detail_venv_ffx)"
|
||||
else
|
||||
report_component failed "bundle ffx" "$(detail_venv_ffx)"
|
||||
READINESS_FAILURES=$((READINESS_FAILURES + 1))
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Shell exposure status:"
|
||||
if check_bashrc_file; then
|
||||
report_component ok ".bashrc" "$(detail_bashrc_file)"
|
||||
else
|
||||
report_component warn ".bashrc" "$(detail_bashrc_file)"
|
||||
fi
|
||||
|
||||
if check_bashrc_alias; then
|
||||
report_component ok "ffx alias" "$(detail_bashrc_alias)"
|
||||
else
|
||||
report_component failed "ffx alias" "$(detail_bashrc_alias)"
|
||||
READINESS_FAILURES=$((READINESS_FAILURES + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_bundle_venv() {
|
||||
mkdir -p "${HOME}/.local/share"
|
||||
|
||||
if ! check_venv_dir; then
|
||||
printf 'Creating bundle virtualenv at %s...\n' "${VENV_DIR}"
|
||||
if ! python3 -m venv "${VENV_DIR}"; then
|
||||
printf 'Failed to create virtualenv at %s.\n' "${VENV_DIR}" >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! check_venv_pip; then
|
||||
printf 'Missing pip in %s.\n' "${VENV_DIR}" >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf 'Installing FFX package into %s...\n' "${VENV_DIR}"
|
||||
if ! "${VENV_PIP}" install --editable "${ROOT_DIR}"; then
|
||||
printf 'Failed to install FFX package into %s.\n' "${VENV_DIR}" >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
write_alias_block() {
|
||||
local bashrc_dir
|
||||
bashrc_dir="$(dirname "${BASHRC_FILE}")"
|
||||
mkdir -p "${bashrc_dir}"
|
||||
touch "${BASHRC_FILE}"
|
||||
|
||||
if grep -Fq "${ALIAS_BLOCK_BEGIN}" "${BASHRC_FILE}" || grep -Fq "${ALIAS_BLOCK_END}" "${BASHRC_FILE}"; then
|
||||
if ! python3 - "${BASHRC_FILE}" "${ALIAS_BLOCK_BEGIN}" "${ALIAS_BLOCK_END}" "${ALIAS_LINE}" <<'PY'
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
path = pathlib.Path(sys.argv[1])
|
||||
begin = sys.argv[2]
|
||||
end = sys.argv[3]
|
||||
alias_line = sys.argv[4]
|
||||
|
||||
content = path.read_text()
|
||||
block = f"{begin}\n{alias_line}\n{end}\n"
|
||||
|
||||
start = content.find(begin)
|
||||
stop = content.find(end)
|
||||
|
||||
if start != -1 and stop != -1 and stop >= start:
|
||||
stop += len(end)
|
||||
if stop < len(content) and content[stop] == "\n":
|
||||
stop += 1
|
||||
content = content[:start] + block + content[stop:]
|
||||
else:
|
||||
if content and not content.endswith("\n"):
|
||||
content += "\n"
|
||||
content += block
|
||||
|
||||
path.write_text(content)
|
||||
PY
|
||||
then
|
||||
printf 'Failed to update managed alias block in %s.\n' "${BASHRC_FILE}" >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
fi
|
||||
elif check_bashrc_alias; then
|
||||
:
|
||||
else
|
||||
{
|
||||
if [ -s "${BASHRC_FILE}" ] && [ "$(tail -c 1 "${BASHRC_FILE}" 2>/dev/null || true)" != "" ]; then
|
||||
printf '\n'
|
||||
fi
|
||||
printf '%s\n' "${ALIAS_BLOCK_BEGIN}"
|
||||
printf '%s\n' "${ALIAS_LINE}"
|
||||
printf '%s\n' "${ALIAS_BLOCK_END}"
|
||||
} >>"${BASHRC_FILE}" || {
|
||||
printf 'Failed to append alias block to %s.\n' "${BASHRC_FILE}" >&2
|
||||
INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
ensure_bashrc_alias() {
|
||||
printf 'Ensuring ffx alias in %s...\n' "${BASHRC_FILE}"
|
||||
write_alias_block
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--check)
|
||||
CHECK_ONLY=1
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
printf 'Unknown option: %s\n\n' "$1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
print_status_report
|
||||
|
||||
if [ "${CHECK_ONLY}" -eq 0 ]; then
|
||||
if ! check_python3; then
|
||||
printf '\npython3 is required before the bundle venv can be prepared.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
ensure_bundle_venv
|
||||
ensure_bashrc_alias
|
||||
|
||||
echo
|
||||
print_status_report
|
||||
fi
|
||||
|
||||
echo
|
||||
if [ "${INSTALL_FAILURES}" -gt 0 ]; then
|
||||
echo "One or more bundle preparation steps failed; see the status checks above." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${READINESS_FAILURES}" -gt 0 ]; then
|
||||
echo "The FFX bundle virtualenv and/or alias setup is incomplete." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "The FFX bundle virtualenv is ready."
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user