Files
IQ.Pilot/iqpilot/tools/iq.sh
2026-08-12 02:48:02 -05:00

241 lines
7.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
set -euo pipefail
IQ_RESET='\033[0m'
IQ_BOLD='\033[1m'
IQ_MUTED='\033[38;5;245m'
IQ_RED='\033[38;5;204m'
IQ_GREEN='\033[38;5;120m'
IQ_CYAN='\033[38;2;38;145;184m'
IQ_BLUE='\033[38;2;51;112;176m'
IQ_PURPLE='\033[38;5;141m'
IQ_PINK='\033[38;5;211m'
IQ_ROOT=''
IQ_DRY=0
IQ_NO_VERIFY=0
IQ_LOG_FILE=''
if [[ ! -t 1 || "${NO_COLOR:-}" != '' ]]; then
IQ_RESET='' IQ_BOLD='' IQ_MUTED='' IQ_RED='' IQ_GREEN='' IQ_CYAN='' IQ_BLUE='' IQ_PURPLE='' IQ_PINK=''
fi
iq_line() {
printf '%b%s%b\n' "$IQ_CYAN" '━━━━━━━━━━━━' "$IQ_RESET"
}
iq_title() {
printf '%bI%b%bQ%b%b.%b%bP%b%bilot%b %b%s%b\n' "$IQ_CYAN" "$IQ_RESET" "$IQ_BLUE" "$IQ_RESET" "$IQ_PURPLE" "$IQ_RESET" "$IQ_PINK" "$IQ_RESET" "$IQ_BOLD" "$IQ_RESET" "$IQ_MUTED" "$1" "$IQ_RESET"
}
iq_ok() {
printf ' %b●%b %s\n' "$IQ_GREEN" "$IQ_RESET" "$1"
}
iq_fail() {
printf ' %b●%b %s\n' "$IQ_RED" "$IQ_RESET" "$1" >&2
}
iq_note() {
printf ' %b●%b %s\n' "$IQ_CYAN" "$IQ_RESET" "$1"
}
iq_find_root() {
local candidate="${IQ_ROOT:-$PWD}"
while [[ "$candidate" != / ]]; do
if [[ -f "$candidate/launch_openpilot.sh" && -d "$candidate/iqpilot" ]]; then
IQ_ROOT="$candidate"
return 0
fi
candidate="$(cd "$candidate/.." && pwd)"
done
for candidate in "$HOME/openpilot" /data/openpilot; do
if [[ -f "$candidate/launch_openpilot.sh" && -d "$candidate/iqpilot" ]]; then
IQ_ROOT="$candidate"
return 0
fi
done
return 1
}
iq_require_root() {
if ! iq_find_root; then
iq_fail 'IQ.Pilot checkout not found. Run this inside the checkout or use --dir PATH.'
return 1
fi
}
iq_run() {
local rendered
printf -v rendered '%q ' "$@"
rendered="${rendered% }"
printf '%b%b %b%s%b\n' "$IQ_PINK" "$IQ_RESET" "$IQ_MUTED" "$rendered" "$IQ_RESET"
[[ "$IQ_DRY" = 1 ]] || "$@"
}
iq_check() {
iq_title 'environment check'
iq_require_root
iq_ok "checkout $IQ_ROOT"
command -v git >/dev/null 2>&1 || { iq_fail 'git is not installed'; return 1; }
iq_ok "git $(git --version | sed 's/git version //')"
command -v python3 >/dev/null 2>&1 || { iq_fail 'python3 is not installed'; return 1; }
iq_ok "python $(python3 --version | sed 's/Python //')"
if [[ -x "$IQ_ROOT/.venv/bin/python3" ]]; then
iq_ok 'venv ready'
else
iq_note 'venv not created yet — run iq setup'
fi
}
iq_install() {
local shell_name rc_file iq_script command
shell_name="$(basename "${SHELL:-bash}")"
rc_file="$HOME/.${shell_name}rc"
[[ "$(uname)" = Darwin && "$shell_name" = bash ]] && rc_file="$HOME/.bash_profile"
iq_script="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/iq.sh"
command="alias iq='${iq_script} \"\$@\"'"
touch "$rc_file"
grep -Fqx "$command" "$rc_file" 2>/dev/null || printf '\n%s\n' "$command" >> "$rc_file"
iq_title 'command installed'
iq_ok "restart your shell, then use iq ${rc_file}"
}
iq_setup() {
local script
iq_require_root
if [[ -f /AGNOS ]]; then
iq_title 'setup'
iq_note 'IQ.OS manages system dependencies and the base Python runtime'
iq_note 'use iq pkg to synchronize private packages when needed'
iq_check
return 0
fi
case "$OSTYPE" in
linux-gnu*) script="$IQ_ROOT/iqpilot/tools/ubuntu_setup.sh" ;;
darwin*) script="$IQ_ROOT/iqpilot/tools/mac_setup.sh" ;;
*) iq_fail "unsupported platform: $OSTYPE"; return 1 ;;
esac
iq_title 'setup'
iq_run "$script"
if command -v git-lfs >/dev/null 2>&1; then
iq_run git -C "$IQ_ROOT" lfs pull
fi
iq_ok 'setup complete'
}
iq_venv() {
iq_require_root
[[ -f "$IQ_ROOT/.venv/bin/activate" ]] || { iq_fail 'venv not found — run iq setup first'; return 1; }
case "$(basename "${SHELL:-bash}")" in
zsh) ZDOTDIR="$(mktemp -d)"; printf 'source %q\nsource %q\n' "$HOME/.zshrc" "$IQ_ROOT/.venv/bin/activate" > "$ZDOTDIR/.zshrc"; exec zsh ;;
*) exec bash --rcfile <(printf 'source %q\nsource %q\n' "$HOME/.bashrc" "$IQ_ROOT/.venv/bin/activate") ;;
esac
}
iq_build() {
iq_require_root
if [[ -f /AGNOS ]]; then
iq_run "$IQ_ROOT/iqpilot/system/manager/build.py"
else
(cd "$IQ_ROOT" && iq_run scons "$@")
fi
}
iq_quality() {
iq_require_root
(cd "$IQ_ROOT" && iq_run scripts/lint/lint.sh "$@")
}
iq_pkg() {
iq_require_root
(cd "$IQ_ROOT" && iq_run python3 iqpilot/tools/scripts/setup_private_packages.py "$@")
if [[ -f "$IQ_ROOT/artifacts/runtime/ensure_private_installed.sh" ]]; then
(cd "$IQ_ROOT" && iq_run bash artifacts/runtime/ensure_private_installed.sh)
fi
}
iq_status() {
local branch commit tree
iq_require_root
branch="$(git -C "$IQ_ROOT" branch --show-current 2>/dev/null || printf detached)"
commit="$(git -C "$IQ_ROOT" rev-parse --short HEAD 2>/dev/null || printf unknown)"
tree=clean
[[ -n "$(git -C "$IQ_ROOT" status --porcelain 2>/dev/null)" ]] && tree=modified
iq_title 'status'
iq_note "root $IQ_ROOT"
iq_note "branch $branch"
iq_note "commit $commit"
[[ "$tree" = clean ]] && iq_ok "tree $tree" || iq_note "tree $tree"
}
iq_switch() {
local remote=origin branch
iq_require_root
[[ $# -ge 1 ]] || { iq_fail 'usage: iq switch [REMOTE] BRANCH'; return 1; }
[[ $# -ge 2 ]] && { remote="$1"; shift; }
branch="$1"
iq_title "switching to $remote/$branch"
iq_note 'this discards uncommitted changes and untracked files'
iq_run git -C "$IQ_ROOT" fetch "$remote" "$branch:refs/remotes/$remote/$branch"
iq_run git -C "$IQ_ROOT" checkout -B "$branch" --track "$remote/$branch"
iq_run git -C "$IQ_ROOT" reset --hard "$remote/$branch"
iq_run git -C "$IQ_ROOT" clean -df
}
iq_service() {
local action="$1"
[[ -f /AGNOS ]] || { iq_note "${action} is available on IQ.OS devices only"; return 0; }
iq_run sudo systemctl "$action" comma
}
iq_help() {
iq_title 'command center'
printf '%bUsage%b iq [--dir PATH] [--dry] COMMAND\n\n' "$IQ_BOLD" "$IQ_RESET"
printf '%bCOMMAND%b\n' "$IQ_PURPLE" "$IQ_RESET"
printf ' %bsetup%b install development dependencies\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %bcheck%b verify checkout, Git, Python, and venv\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %bbuild%b build IQ.Pilot\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %bquality%b run code-quality checks\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %bpkg%b authenticate and synchronize private packages\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %bstatus%b show checkout, branch, commit, and tree state\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %bswitch%b replace the checkout with another branch\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %bvenv%b open a shell with the project venv active\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %bstart%b restart IQ.Pilot on IQ.OS\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %bstop%b stop IQ.Pilot on IQ.OS\n' "$IQ_CYAN" "$IQ_RESET"
printf ' %binstall%b install the iq shell command\n' "$IQ_CYAN" "$IQ_RESET"
printf '\n%bExamples%b\n' "$IQ_PURPLE" "$IQ_RESET"
printf ' iq setup iq build -j4 iq pkg\n'
iq_line
}
while [[ $# -gt 0 ]]; do
case "$1" in
-d|--dir) [[ $# -ge 2 ]] || { iq_fail 'missing path after --dir'; exit 2; }; IQ_ROOT="$2"; shift 2 ;;
--dry) IQ_DRY=1; shift ;;
-n|--no-verify) IQ_NO_VERIFY=1; shift ;;
-l|--log) [[ $# -ge 2 ]] || { iq_fail 'missing file after --log'; exit 2; }; IQ_LOG_FILE="$2"; shift 2 ;;
-h|--help|help) iq_help; exit 0 ;;
*) break ;;
esac
done
command="${1:-help}"
[[ $# -gt 0 ]] && shift
case "$command" in
help) iq_help ;;
setup) iq_setup "$@" ;;
check) iq_check "$@" ;;
build) iq_build "$@" ;;
quality) iq_quality "$@" ;;
pkg) iq_pkg "$@" ;;
status) iq_status "$@" ;;
switch) iq_switch "$@" ;;
venv) iq_venv "$@" ;;
start) iq_service restart "$@" ;;
stop) iq_service stop "$@" ;;
install) iq_install "$@" ;;
*) iq_fail "unknown command: $command"; iq_help; exit 2 ;;
esac