#!/bin/bash # omarchy:summary=Install or remove the OmarchyCN layer on an existing Omarchy # omarchy:args=[--uninstall] # omarchy:examples=omarchy-cn-install-overlay | omarchy-cn-install-overlay --uninstall # Bootstraps onto a foreign OMARCHY_PATH, so it resolves its own checkout root. set -euo pipefail SRC=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd) DEST="${OMARCHY_PATH:?OMARCHY_PATH must point at the target Omarchy install}" MANIFEST="$HOME/.local/state/omarchycn/overlay-manifest" run_in() { local root="$1" shift if [[ -w $root ]]; then "$@" else sudo "$@" fi } valid_entry() { [[ $1 == "cn" || $1 =~ ^bin/(omarchycn|omarchy-cn-[a-z0-9-]+)$ ]] } MENU_EXT="$HOME/.config/omarchy/extensions/omarchy-menu.jsonc" MENU_MARKER="// OmarchyCN overlay menu extension" # Comments-only files (upstream ships such a template) hold no user content menu_ext_has_user_content() { [[ -f $MENU_EXT ]] || return 1 grep -qF "$MENU_MARKER" "$MENU_EXT" && return 1 [[ -n $(grep -vE '^[[:space:]]*(//.*)?$' "$MENU_EXT" | tr -d '[:space:]{}') ]] } install_menu_extension() { if menu_ext_has_user_content; then echo "跳过菜单扩展:$MENU_EXT 已有用户内容,请手动合并 default/omarchy/omarchy-menu.jsonc 的 OmarchyCN 段" return 0 fi mkdir -p "${MENU_EXT%/*}" { echo "$MENU_MARKER" echo "{" sed -n '/^ \/\/ OmarchyCN$/,$p' "$SRC/default/omarchy/omarchy-menu.jsonc" | sed '$d' echo "}" } > "$MENU_EXT" echo "OmarchyCN 菜单扩展已写入 $MENU_EXT" } remove_menu_extension() { if [[ -f $MENU_EXT ]] && grep -qF "$MENU_MARKER" "$MENU_EXT"; then rm -f "$MENU_EXT" fi } uninstall() { if [[ ! -f $MANIFEST ]]; then echo "No overlay manifest at $MANIFEST" >&2 exit 1 fi local dest="" rel="" dest=$(grep -m1 '^dest=' "$MANIFEST" | cut -d= -f2-) if [[ -z $dest || ! -d $dest ]]; then echo "Manifest has no valid dest= record" >&2 exit 1 fi # Validate every entry before deleting anything while IFS= read -r rel; do [[ $rel == source=* || $rel == dest=* ]] && continue if ! valid_entry "$rel"; then echo "Refusing suspicious manifest entry: $rel (nothing deleted)" >&2 exit 1 fi done < "$MANIFEST" while IFS= read -r rel; do [[ $rel == source=* || $rel == dest=* ]] && continue if [[ $rel == "cn" ]]; then run_in "$dest" rm -rf "$dest/cn" else run_in "$dest" rm -f "$dest/$rel" fi done < "$MANIFEST" remove_menu_extension rm -f "$MANIFEST" echo "OmarchyCN overlay removed from $dest" } install() { if [[ ! -f $DEST/version || ! -x $DEST/bin/omarchy ]]; then echo "No Omarchy install found at $DEST" >&2 exit 1 fi if [[ $SRC == "$DEST" ]]; then echo "Source checkout and target are the same tree; nothing to overlay" >&2 exit 1 fi # Reinstall: remove the previous overlay first so upgrades leave no residue if [[ -f $MANIFEST ]]; then uninstall fi if [[ -e $DEST/cn ]]; then echo "Refusing to take over unmanaged $DEST/cn" >&2 exit 1 fi local f rel entries=() for f in "$SRC/bin/omarchycn" "$SRC"/bin/omarchy-cn-*; do rel="bin/${f##*/}" if [[ -e $DEST/$rel ]]; then echo "Refusing to overwrite unmanaged $DEST/$rel" >&2 exit 1 fi entries+=("$rel") done # Manifest is the intent record, published BEFORE copying: if a copy fails # midway, a rerun sees the manifest, uninstalls the partial state, retries. mkdir -p "${MANIFEST%/*}" { echo "source=$SRC" echo "dest=$DEST" echo "cn" printf '%s\n' "${entries[@]}" } > "$MANIFEST" run_in "$DEST" cp -r "$SRC/cn" "$DEST/cn" for rel in "${entries[@]}"; do run_in "$DEST" cp "$SRC/$rel" "$DEST/$rel" done install_menu_extension echo "OmarchyCN overlay installed into $DEST (${#entries[@]} commands)" echo "Verify: omarchy cn version" } if [[ ${1:-} == "--uninstall" ]]; then uninstall else install fi