mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-28 17:01:16 +00:00
223 lines
8.7 KiB
Bash
223 lines
8.7 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -Eeuo pipefail
|
|
|
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
|
|
LOCK_FILE="${1:-${PROJECT_ROOT}/skills-lock.json}"
|
|
OUTPUT_FILE="${2:-${SCRIPT_DIR}/install-global-skills.sh}"
|
|
|
|
die() {
|
|
printf 'Error: %s\n' "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
for command_name in awk chmod mkdir mktemp mv rm sort; do
|
|
if ! command -v "${command_name}" >/dev/null 2>&1; then
|
|
die "Required command not found: ${command_name}"
|
|
fi
|
|
done
|
|
|
|
[[ -f "${LOCK_FILE}" ]] || die "Skills lockfile not found: ${LOCK_FILE}"
|
|
|
|
mapfile -t records < <(
|
|
awk '
|
|
/^ "[^"]+": \{$/ {
|
|
skill = $1
|
|
gsub(/[":]/, "", skill)
|
|
next
|
|
}
|
|
|
|
$1 == "\"source\":" {
|
|
source = $2
|
|
gsub(/[",]/, "", source)
|
|
print source "\t" skill
|
|
skill = ""
|
|
}
|
|
' "${LOCK_FILE}" | LC_ALL=C sort -t $'\t' -k1,1 -k2,2
|
|
)
|
|
|
|
(( ${#records[@]} > 0 )) || die "No skills found in lockfile: ${LOCK_FILE}"
|
|
|
|
temporary_file="$(mktemp "${OUTPUT_FILE}.tmp.XXXXXX")"
|
|
cleanup() {
|
|
rm -f -- "${temporary_file}"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
{
|
|
printf '%s\n' '#!/usr/bin/env bash'
|
|
printf '\n'
|
|
printf '%s\n' '# This file is generated by scripts/generate-global-skills-installer.sh.'
|
|
printf '%s\n' '# Do not edit manually; regenerate it after changing skills-lock.json.'
|
|
printf '%s\n' '# shellcheck shell=bash'
|
|
printf '\n'
|
|
printf '%s\n' 'set -Eeuo pipefail'
|
|
printf '\n'
|
|
printf 'SKILL_COUNT=%q\n' "${#records[@]}"
|
|
printf 'DRY_RUN=0\n'
|
|
printf 'COPY_MODE=0\n'
|
|
printf 'SHARED_SKILLS_DIR="${SKILLS_GLOBAL_DIR:-${HOME:?HOME must be set}/.agents/skills}"\n'
|
|
printf 'CODEX_HOME_DIR="${CODEX_HOME:-${HOME:?HOME must be set}/.codex}"\n'
|
|
printf 'CODEX_SKILLS_DIR="${CODEX_HOME_DIR}/skills"\n'
|
|
printf '\n'
|
|
printf '%s\n' 'usage() {'
|
|
printf '%s\n' ' cat <<'"'"'USAGE'"'"''
|
|
printf '%s\n' 'Usage: scripts/install-global-skills.sh [options]'
|
|
printf '\n'
|
|
printf '%s\n' 'Install the repository skill baseline globally and bridge it into Codex.'
|
|
printf '\n'
|
|
printf '%s\n' 'Options:'
|
|
printf '%s\n' ' --dry-run Show commands and filesystem changes without applying them.'
|
|
printf '%s\n' ' --copy Copy skills into Codex instead of creating symlinks.'
|
|
printf '%s\n' ' --help Show this help text.'
|
|
printf '\n'
|
|
printf '%s\n' 'Environment:'
|
|
printf '%s\n' ' SKILLS_GLOBAL_DIR Shared global skills directory (default: ~/.agents/skills).'
|
|
printf '%s\n' ' CODEX_HOME Codex home directory (default: ~/.codex).'
|
|
printf '%s\n' 'USAGE'
|
|
printf '%s\n' '}'
|
|
printf '\n'
|
|
printf '%s\n' 'die() {'
|
|
printf '%s\n' ' printf '"'"'Error: %s\n'"'"' "$1" >&2'
|
|
printf '%s\n' ' exit 1'
|
|
printf '%s\n' '}'
|
|
printf '\n'
|
|
printf '%s\n' 'print_command() {'
|
|
printf '%s\n' ' printf '"'"'+'"'"''
|
|
printf '%s\n' ' printf '"'"' %q'"'"' "$@"'
|
|
printf '%s\n' ' printf '"'"'\n'"'"''
|
|
printf '%s\n' '}'
|
|
printf '\n'
|
|
printf '%s\n' 'run_command() {'
|
|
printf '%s\n' ' if (( DRY_RUN )); then'
|
|
printf '%s\n' ' print_command "$@"'
|
|
printf '%s\n' ' return 0'
|
|
printf '%s\n' ' fi'
|
|
printf '%s\n' ' "$@"'
|
|
printf '%s\n' '}'
|
|
printf '\n'
|
|
printf '%s\n' 'require_command() {'
|
|
printf '%s\n' ' command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1"'
|
|
printf '%s\n' '}'
|
|
printf '\n'
|
|
printf '%s\n' 'while (( $# > 0 )); do'
|
|
printf '%s\n' ' case "$1" in'
|
|
printf '%s\n' ' --dry-run)'
|
|
printf '%s\n' ' DRY_RUN=1'
|
|
printf '%s\n' ' ;;'
|
|
printf '%s\n' ' --copy)'
|
|
printf '%s\n' ' COPY_MODE=1'
|
|
printf '%s\n' ' ;;'
|
|
printf '%s\n' ' --help|-h)'
|
|
printf '%s\n' ' usage'
|
|
printf '%s\n' ' exit 0'
|
|
printf '%s\n' ' ;;'
|
|
printf '%s\n' ' *)'
|
|
printf '%s\n' ' die "Unknown option: $1 (use --help for usage)"'
|
|
printf '%s\n' ' ;;'
|
|
printf '%s\n' ' esac'
|
|
printf '%s\n' ' shift'
|
|
printf '%s\n' 'done'
|
|
printf '\n'
|
|
printf '%s\n' 'require_command bash'
|
|
printf '%s\n' 'require_command npx'
|
|
printf '%s\n' 'require_command mkdir'
|
|
printf '%s\n' 'require_command ln'
|
|
printf '%s\n' 'require_command readlink'
|
|
printf '%s\n' 'if (( COPY_MODE )); then'
|
|
printf '%s\n' ' require_command cp'
|
|
printf '%s\n' ' require_command diff'
|
|
printf '%s\n' 'fi'
|
|
printf '\n'
|
|
printf '%s\n' 'printf '"'"'Installing %d skills globally...\n'"'"' "$SKILL_COUNT"'
|
|
printf '\n'
|
|
|
|
current_source=""
|
|
source_skill_args=()
|
|
for record in "${records[@]}"; do
|
|
source="${record%%$'\t'*}"
|
|
skill="${record#*$'\t'}"
|
|
|
|
if [[ -n "${current_source}" && "${source}" != "${current_source}" ]]; then
|
|
printf 'run_command npx --yes skills add %q --global --yes' "${current_source}"
|
|
for skill_arg in "${source_skill_args[@]}"; do
|
|
printf ' --skill %q' "${skill_arg}"
|
|
done
|
|
printf '\n\n'
|
|
source_skill_args=()
|
|
fi
|
|
|
|
current_source="${source}"
|
|
source_skill_args+=("${skill}")
|
|
done
|
|
|
|
printf 'run_command npx --yes skills add %q --global --yes' "${current_source}"
|
|
for skill_arg in "${source_skill_args[@]}"; do
|
|
printf ' --skill %q' "${skill_arg}"
|
|
done
|
|
printf '\n\n'
|
|
|
|
printf '%s\n' 'SKILLS=('
|
|
for record in "${records[@]}"; do
|
|
skill="${record#*$'\t'}"
|
|
printf ' %q\n' "${skill}"
|
|
done
|
|
printf '%s\n' ')'
|
|
printf '\n'
|
|
printf '%s\n' 'if (( DRY_RUN )); then'
|
|
printf '%s\n' ' printf '"'"'Would bridge skills from %s to %s\n'"'"' "$SHARED_SKILLS_DIR" "$CODEX_SKILLS_DIR"'
|
|
printf '%s\n' ' for skill in "${SKILLS[@]}"; do'
|
|
printf '%s\n' ' if (( COPY_MODE )); then'
|
|
printf '%s\n' ' printf '"'"'+ copy %s -> %s/%s\n'"'"' "$SHARED_SKILLS_DIR/$skill" "$CODEX_SKILLS_DIR" "$skill"'
|
|
printf '%s\n' ' else'
|
|
printf '%s\n' ' printf '"'"'+ ln -s %s %s/%s\n'"'"' "$SHARED_SKILLS_DIR/$skill" "$CODEX_SKILLS_DIR" "$skill"'
|
|
printf '%s\n' ' fi'
|
|
printf '%s\n' ' done'
|
|
printf '%s\n' ' exit 0'
|
|
printf '%s\n' 'fi'
|
|
printf '\n'
|
|
printf '%s\n' 'run_command mkdir -p "$CODEX_SKILLS_DIR"'
|
|
printf '%s\n' 'conflict_count=0'
|
|
printf '%s\n' 'for skill in "${SKILLS[@]}"; do'
|
|
printf '%s\n' ' source_path="$SHARED_SKILLS_DIR/$skill"'
|
|
printf '%s\n' ' target_path="$CODEX_SKILLS_DIR/$skill"'
|
|
printf '%s\n' ' [[ -d "$source_path" ]] || { printf '"'"'Error: Installed skill is missing: %s\n'"'"' "$source_path" >&2; conflict_count=$((conflict_count + 1)); continue; }'
|
|
printf '%s\n' ' if [[ -L "$target_path" ]]; then'
|
|
printf '%s\n' ' if [[ "$(readlink "$target_path")" == "$source_path" ]]; then'
|
|
printf '%s\n' ' printf '"'"'Already linked: %s\n'"'"' "$skill"'
|
|
printf '%s\n' ' continue'
|
|
printf '%s\n' ' fi'
|
|
printf '%s\n' ' printf '"'"'Error: Refusing to replace unmanaged symlink: %s\n'"'"' "$target_path" >&2'
|
|
printf '%s\n' ' conflict_count=$((conflict_count + 1))'
|
|
printf '%s\n' ' continue'
|
|
printf '%s\n' ' fi'
|
|
printf '%s\n' ' if [[ -e "$target_path" ]]; then'
|
|
printf '%s\n' ' if (( COPY_MODE )) && [[ -d "$target_path" ]] && diff -qr -- "$source_path" "$target_path" >/dev/null; then'
|
|
printf '%s\n' ' printf '"'"'Already copied: %s\n'"'"' "$skill"'
|
|
printf '%s\n' ' continue'
|
|
printf '%s\n' ' fi'
|
|
printf '%s\n' ' printf '"'"'Error: Refusing to overwrite existing path: %s\n'"'"' "$target_path" >&2'
|
|
printf '%s\n' ' conflict_count=$((conflict_count + 1))'
|
|
printf '%s\n' ' continue'
|
|
printf '%s\n' ' fi'
|
|
printf '%s\n' ' if (( COPY_MODE )); then'
|
|
printf '%s\n' ' run_command cp -R -- "$source_path" "$target_path"'
|
|
printf '%s\n' ' printf '"'"'Copied: %s\n'"'"' "$skill"'
|
|
printf '%s\n' ' else'
|
|
printf '%s\n' ' run_command ln -s -- "$source_path" "$target_path"'
|
|
printf '%s\n' ' printf '"'"'Linked: %s\n'"'"' "$skill"'
|
|
printf '%s\n' ' fi'
|
|
printf '%s\n' 'done'
|
|
printf '\n'
|
|
printf '%s\n' '(( conflict_count == 0 )) || die "${conflict_count} skill bridge conflict(s) require manual resolution"'
|
|
printf '%s\n' 'printf '"'"'Global skills installation complete.\n'"'"''
|
|
} >"${temporary_file}"
|
|
|
|
chmod 755 "${temporary_file}"
|
|
mkdir -p -- "$(dirname -- "${OUTPUT_FILE}")"
|
|
mv -- "${temporary_file}" "${OUTPUT_FILE}"
|
|
trap - EXIT
|
|
|
|
printf 'Generated %s from %s (%d skills).\n' "${OUTPUT_FILE}" "${LOCK_FILE}" "${#records[@]}"
|