Files
wp-plugin-starter-template-…/scripts/sync-core.sh
T
marcus 2f91c3e6af WP Plugin Starter 1.0.0: a fresh start
The parts every wpallstars plugin needs: settings screen with search and an empty General tab, Read Me tab, features as classes, replaced plugins, the shared GitHub updater, release and check scripts, CI and the shared rules. scripts/rename-plugin.sh starts a new plugin; scripts/sync-core.sh keeps plugins' core files in step with this starter. Built with aidevops (https://aidevops.sh).
2026-10-03 03:30:42 +01:00

148 lines
4.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Copy the core files (scripts/core-files.txt) from the starter plugin into
# this plugin, with this plugin's names. Core files hold no code for one
# plugin, so after a sync they match the starter apart from the names.
#
# Usage: scripts/sync-core.sh [--check] [--from DIR] [--ref REF]
# --check Change nothing; list core files that differ from the starter's
# and exit 1 if any do (scripts/preflight-release.sh warns).
# --from DIR A checkout of the starter (default: <PREFIX>_STARTER_DIR, then
# wp-plugin-starter-template-for-ai-coding next to this repository).
# --ref REF Starter commit, branch or tag to copy from (default: HEAD of
# that checkout; use origin/main after a git fetch there).
#
# The list of core files and their contents come from the starter at REF;
# the plugin's names come from this repository's main file at HEAD.
# Review the changes with git diff, then commit them.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_DIR
# shellcheck source=scripts/lib/plugin.sh disable=SC1091 # followed only with -x
. "$SCRIPT_DIR/lib/plugin.sh"
readonly STARTER_REPO_DIR="wp-plugin-starter-template-for-ai-coding"
die() {
local message="$1"
printf 'sync-core: %s\n' "$message" >&2
exit 2
}
TMP_FILE=""
cleanup() {
[ -z "$TMP_FILE" ] || rm -f "$TMP_FILE"
return 0
}
usage() {
sed -n '2,17p' "$0" | sed 's/^# \{0,1\}//'
return 0
}
# Core paths at the starter ref, one per line, with directories expanded.
core_paths() {
local from="$1"
local ref="$2"
local line
git -C "$from" show "$ref:scripts/core-files.txt" | sed -e 's/[[:space:]]*$//' -e '/^#/d' -e '/^$/d' | while IFS= read -r line; do
case "$line" in
*/) git -C "$from" ls-tree -r --name-only "$ref" -- "$line" ;;
*) printf '%s\n' "$line" ;;
esac
done
return 0
}
main() {
local check=0 from="" ref="HEAD"
while [ $# -gt 0 ]; do
local arg="$1"
local value="${2:-}"
case "$arg" in
--check) check=1 ;;
--from)
[ $# -ge 2 ] || die "--from needs a value"
from="$value"
shift
;;
--ref)
[ $# -ge 2 ] || die "--ref needs a value"
ref="$value"
shift
;;
-h | --help)
usage
return 0
;;
*) die "unknown argument: $arg" ;;
esac
shift
done
local root
root="$(git rev-parse --show-toplevel)" || die "run this inside a checkout of the plugin"
cd "$root"
plugin_identity HEAD || die "cannot tell which plugin this is"
plugin_names_as TO
if [ -z "$from" ]; then
from="$(plugin_env STARTER_DIR "$(dirname "$root")/$STARTER_REPO_DIR")"
fi
[ -d "$from" ] || die "no starter checkout at $from; clone it there or pass --from DIR"
from="$(cd "$from" && pwd)"
[ "$from" != "$root" ] || die "this is the starter; run it in a plugin made from the starter"
git -C "$from" rev-parse --verify --quiet "$ref^{commit}" >/dev/null || die "not a commit in the starter: $ref"
cd "$from"
plugin_identity "$ref" || die "cannot read the starter's names at $ref"
plugin_names_as FROM
cd "$root"
printf 'Core files from %s (%s) into %s, as %s / %s / %s / %s / %s\n' \
"$FROM_NAME" "$(git -C "$from" rev-parse --short "$ref")" "$TO_NAME" \
"$TO_SLUG" "$TO_PREFIX" "$TO_PACKAGE" "$TO_CONST" "$TO_CSS"
local path target mode differ=0 count=0
trap cleanup EXIT
TMP_FILE="$(mktemp "${TMPDIR:-/tmp}/sync-core.XXXXXX")"
local tmp="$TMP_FILE"
while IFS= read -r path; do
target="$(printf '%s' "$path" | plugin_map)"
git -C "$from" show "$ref:$path" | plugin_map >"$tmp"
count=$((count + 1))
if [ -f "$target" ] && cmp -s "$tmp" "$target"; then
continue
fi
differ=$((differ + 1))
if [ "$check" -eq 1 ]; then
if [ -f "$target" ]; then
printf ' differs %s\n' "$target"
else
printf ' missing %s\n' "$target"
fi
continue
fi
mkdir -p "$(dirname "$target")"
cp "$tmp" "$target"
mode="$(git -C "$from" ls-tree "$ref" -- "$path" | awk '{ print $1 }')"
if [ "$mode" = "100755" ]; then chmod +x "$target"; else chmod -x "$target"; fi
printf ' updated %s\n' "$target"
done < <(core_paths "$from" "$ref")
if [ "$check" -eq 1 ]; then
if [ "$differ" -eq 0 ]; then
printf 'All %d core files match the starter.\n' "$count"
return 0
fi
printf '%d of %d core files differ from the starter. Run scripts/sync-core.sh, or change the starter first.\n' "$differ" "$count"
return 1
fi
printf '%d of %d core files updated. Review with git diff, then commit.\n' "$differ" "$count"
return 0
}
main "$@"