From 3def30741b7a27f861a1890ea35c3d0bfdbd7b0e Mon Sep 17 00:00:00 2001 From: pvincent Date: Sat, 6 Jun 2026 11:06:23 +0400 Subject: [PATCH] ghostty aware --- tools/miaou-create | 208 ++++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 99 deletions(-) diff --git a/tools/miaou-create b/tools/miaou-create index 00a5b44..2eb97a3 100755 --- a/tools/miaou-create +++ b/tools/miaou-create @@ -14,143 +14,153 @@ CONTAINER= # FUNCTIONS function usage { - echo "$(basename "$0") " + echo "$(basename "$0") " } function humanize_ago { - local seconds=$(($(date +%s) - $(date -d "$1" +%s))) - - local days=$((seconds / 86400)) - local hours=$(((seconds % 86400) / 3600)) - local minutes=$(((seconds % 3600) / 60)) - - if ((days > 365)); then - echo "$((days / 365)) year(s) ago" - elif ((days > 30)); then - echo "$((days / 30)) month(s) ago" - elif ((days > 0)); then - echo "$days day(s) ago" - elif ((hours > 0)); then - echo "$hours hour(s) ago" - elif ((minutes > 0)); then - echo "$minutes minute(s) ago" - else - echo "$seconds second(s) ago" - fi + local seconds=$(($(date +%s) - $(date -d "$1" +%s))) + + local days=$((seconds / 86400)) + local hours=$(((seconds % 86400) / 3600)) + local minutes=$(((seconds % 3600) / 60)) + + if ((days > 365)); then + echo "$((days / 365)) year(s) ago" + elif ((days > 30)); then + echo "$((days / 30)) month(s) ago" + elif ((days > 0)); then + echo "$days day(s) ago" + elif ((hours > 0)); then + echo "$hours hour(s) ago" + elif ((minutes > 0)); then + echo "$minutes minute(s) ago" + else + echo "$seconds second(s) ago" + fi } function parse_options { - while [[ $# -gt 0 ]]; do - case "$1" in - --help | -h) - usage && exit 0 - ;; - *) - if [[ -z $CONTAINER ]]; then - CONTAINER=$1 - else - echo >&2 "Unknown option: $1" && usage && exit 2 - fi - ;; - esac - - shift 1 # Move to the next argument - done - [[ -n $CONTAINER ]] || (usage && exit 1) + while [[ $# -gt 0 ]]; do + case "$1" in + --help | -h) + usage && exit 0 + ;; + *) + if [[ -z $CONTAINER ]]; then + CONTAINER=$1 + else + echo >&2 "Unknown option: $1" && usage && exit 2 + fi + ;; + esac + + shift 1 # Move to the next argument + done + [[ -n $CONTAINER ]] || (usage && exit 1) } function mount_miaou_bash { - printenv MIAOU_BASH_DIR > /dev/null || (echo >&2 "Warn: environment variable MIAOU_BASH_DIR is missing!" && return) + printenv MIAOU_BASH_DIR >/dev/null || (echo >&2 "Warn: environment variable MIAOU_BASH_DIR is missing!" && return) - local target="$1" - local optional_project=${2:-} - [[ -n $optional_project ]] && optional_project="--project $optional_project" + local target="$1" + local optional_project=${2:-} + [[ -n $optional_project ]] && optional_project="--project $optional_project" - incus $optional_project config device add $target MIAOU-BASH disk source=$MIAOU_BASH_DIR path=/opt/miaou-bash readonly=true | grep -q 'Device MIAOU-BASH added' + incus $optional_project config device add $target MIAOU-BASH disk source=$MIAOU_BASH_DIR path=/opt/miaou-bash readonly=true | grep -q 'Device MIAOU-BASH added' +} + +function infocmp_xterm_ghostty { + local target="$1" + local optional_project=${2:-} + [[ -n $optional_project ]] && optional_project="--project $optional_project" + + echo "export GHOSTTY infocmp from host to container" + infocmp -x xterm-ghostty | incus exec $optional_project $target -- tic -x - 2>/dev/null } function build_sandbox_project { - if ! incus project show $PROJECT_SANDBOX > /dev/null; then - incus project create $PROJECT_SANDBOX - incus --project $PROJECT_SANDBOX profile device add default root disk path=/ pool=default - incus --project $PROJECT_SANDBOX profile device add default eth0 nic name=eth0 network=incusbr0 - fi + if ! incus project show $PROJECT_SANDBOX >/dev/null; then + incus project create $PROJECT_SANDBOX + incus --project $PROJECT_SANDBOX profile device add default root disk path=/ pool=default + incus --project $PROJECT_SANDBOX profile device add default eth0 nic name=eth0 network=incusbr0 + fi } function refresh_template { - if incus --project "$PROJECT_SANDBOX" info "$TEMPLATE_SANDBOX" | grep '^Status: STOPPED'; then - incus --project "$PROJECT_SANDBOX" start "$TEMPLATE_SANDBOX" - fi - incus --project "$PROJECT_SANDBOX" exec "$TEMPLATE_SANDBOX" -- bash << EOF - apt-get update - apt-get dist-upgrade -y - apt-get install -y curl - /opt/miaou-bash/install.sh + if incus --project "$PROJECT_SANDBOX" info "$TEMPLATE_SANDBOX" | grep '^Status: STOPPED'; then + incus --project "$PROJECT_SANDBOX" start "$TEMPLATE_SANDBOX" + fi + incus --project "$PROJECT_SANDBOX" exec "$TEMPLATE_SANDBOX" -- bash </dev/null EOF - incus --project "$PROJECT_SANDBOX" stop "$TEMPLATE_SANDBOX" - local image_date=$(incus --project "$PROJECT_SANDBOX" list "$TEMPLATE_SANDBOX" -f compact,noheader -cl) - echo "template refreshed at: $image_date" + incus --project "$PROJECT_SANDBOX" stop "$TEMPLATE_SANDBOX" + local image_date=$(incus --project "$PROJECT_SANDBOX" list "$TEMPLATE_SANDBOX" -f compact,noheader -cl) + echo "template refreshed at: $image_date" } function build_template_from_scratch { - build_sandbox_project - echo "building template from scratch..." - incus --project "$PROJECT_SANDBOX" launch "$MIAOU_IMAGE" "$TEMPLATE_SANDBOX" - incus --project "$PROJECT_SANDBOX" file delete "$TEMPLATE_SANDBOX"/etc/apt/sources.list - incus --project "$PROJECT_SANDBOX" file push --uid 0 --gid 0 --mode 644 --create-dirs /etc/apt/sources.list.d/debian.sources "$TEMPLATE_SANDBOX"/etc/apt/sources.list.d/debian.sources - cat << EOF | incus --project "$PROJECT_SANDBOX" file push --uid 0 --gid 0 --mode 644 --create-dirs - "$TEMPLATE_SANDBOX"/etc/systemd/resolved.conf.d/10-disable-ipv4-listener.conf + build_sandbox_project + echo "building template from scratch..." + incus --project "$PROJECT_SANDBOX" launch "$MIAOU_IMAGE" "$TEMPLATE_SANDBOX" + incus --project "$PROJECT_SANDBOX" file delete "$TEMPLATE_SANDBOX"/etc/apt/sources.list + incus --project "$PROJECT_SANDBOX" file push --uid 0 --gid 0 --mode 644 --create-dirs /etc/apt/sources.list.d/debian.sources "$TEMPLATE_SANDBOX"/etc/apt/sources.list.d/debian.sources + cat </dev/null && infocmp_xterm_ghostty "$TEMPLATE_SANDBOX" "$PROJECT_SANDBOX" + refresh_template + echo "template:"$TEMPLATE_SANDBOX" from project:$PROJECT_SANDBOX built successfully!" } function prepare_template_for_quick_creation { - local image_date=$(incus list "$TEMPLATE_SANDBOX" -f compact,noheader -cl --project "$PROJECT_SANDBOX") - if [[ -z $image_date ]]; then - build_template_from_scratch - else - local true_date=$(date -d "$image_date" +%s) - local expiration_date=$(date -d "$TEMPLATE_REFRESH_DELAY ago" +%s) - if ((true_date < expiration_date)); then - echo "template exists $(humanize_ago "$image_date"), needs a refresh..." - refresh_template - else - : - # echo "template already exists $(humanize_ago "$image_date")!" - fi - fi + local image_date=$(incus list "$TEMPLATE_SANDBOX" -f compact,noheader -cl --project "$PROJECT_SANDBOX") + if [[ -z $image_date ]]; then + build_template_from_scratch + else + local true_date=$(date -d "$image_date" +%s) + local expiration_date=$(date -d "$TEMPLATE_REFRESH_DELAY ago" +%s) + if ((true_date < expiration_date)); then + echo "template exists $(humanize_ago "$image_date"), needs a refresh..." + refresh_template + else + : + # echo "template already exists $(humanize_ago "$image_date")!" + fi + fi } function customize_host { - local target domain - target="$1" - domain=$(incus network get incusbr0 dns.domain) - domain=${domain:-incus} + local target domain + target="$1" + domain=$(incus network get incusbr0 dns.domain) + domain=${domain:-incus} - printf "127.0.1.1\t$target.$domain $target\n127.0.0.1\tlocalhost\n" | incus file push - $target/etc/hosts - echo "$target.$domain" | incus file push - $target/etc/hostname + printf "127.0.1.1\t$target.$domain $target\n127.0.0.1\tlocalhost\n" | incus file push - $target/etc/hosts + echo "$target.$domain" | incus file push - $target/etc/hostname } function assert_not_sandboxing { - [[ $(incus project get-current) == "$PROJECT_SANDBOX" ]] \ - && echo ERROR: actual sandboxing project, please switch back to your 'default' project >&2 \ - && exit 30 \ - || true + [[ $(incus project get-current) == "$PROJECT_SANDBOX" ]] && + echo ERROR: actual sandboxing project, please switch back to your 'default' project >&2 && + exit 30 || + true } function create { - if incus --project "$PROJECT_SANDBOX" info "$TEMPLATE_SANDBOX" | grep '^Status: RUNNING'; then - incus --project "$PROJECT_SANDBOX" stop "$TEMPLATE_SANDBOX" - fi - incus --project "$PROJECT_SANDBOX" copy --instance-only "$TEMPLATE_SANDBOX" "$CONTAINER" --target-project $(incus project get-current) - incus file delete "$CONTAINER/etc/machine-id" - incus config unset "$CONTAINER" volatile.eth0.hwaddr - incus start "$CONTAINER" - customize_host "$CONTAINER" + if incus --project "$PROJECT_SANDBOX" info "$TEMPLATE_SANDBOX" | grep '^Status: RUNNING'; then + incus --project "$PROJECT_SANDBOX" stop "$TEMPLATE_SANDBOX" + fi + incus --project "$PROJECT_SANDBOX" copy --instance-only "$TEMPLATE_SANDBOX" "$CONTAINER" --target-project $(incus project get-current) + incus file delete "$CONTAINER/etc/machine-id" + incus config unset "$CONTAINER" volatile.eth0.hwaddr + incus start "$CONTAINER" + customize_host "$CONTAINER" } # MAIN