8c24b83ea3
Three changes that only make sense together. **tools/**. check-branding.sh, brand-plugin.sh and branding.conf were accumulating in the repo root, and a deploy.sh/bat/ps1 set would land there too. They now live in tools/ and resolve the repo root explicitly rather than assuming their own directory is it, so they behave the same however they are invoked. **One name drives the rest.** branding.conf now derives the package name, the Rust types and the display name from PLUGIN_NAME, each overridable. Derivation-by-default removes a class of drift; the override matters because the derivation is sometimes invalid — "206 Prototype" derives to "206_prototype", which cargo rejects outright — and because PLUGIN_NAME is cosmetic while the package name is structural. A display tweak should not silently rename the crate, its bundle lookup, the CI command and the lockfile. This template overrides three of them, which a real plugin normally will not: its names are the template's own rather than derived from a product name. An overridden PKG that no longer matches the derivation is reported at info level, never failed. The override is usually deliberate; a display rename that forgot the package looks identical from here, and is not. **The site table is data.** branding-sites.tsv lists every place a name must appear and in what form; check-branding.sh iterates it instead of carrying 29 check calls in shell. The scripts are now identical across every plugin built from this template, with only the table and conf differing — which matters because the template and codename-206 had already diverged by two checks, so every sync was a shell merge. brand-plugin.sh regenerates the rows it owns and preserves the rest, so a hand-added row for a file this template does not ship survives a rename. Custom rows are value-substituted like any other tracked file, so they track the rename rather than going stale — the first cut excluded the whole table from substitution and got that wrong. brand-plugin.sh also gained an interactive mode: run it with no arguments and it prompts for each value with the current one as the default, so Enter keeps it and a run that answers nothing changes nothing. It only engages when there is a terminal to ask at, so CI gets the usage message and exit 2 rather than a hang. Verified by applying a full rename to a sandboxed copy: 8 files rewritten, 29 owned rows regenerated, 1 custom row preserved and substituted, checker green at 48/0/7, and the result compiles as bari_206. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WHt4DykxXaQnyaJfyS8KCn
189 lines
8.0 KiB
Bash
Executable File
189 lines
8.0 KiB
Bash
Executable File
#!/bin/sh
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
# check-branding.sh - verify the plugin's branding/identity strings agree everywhere.
|
|
#
|
|
# Plugin branding is duplicated across the build manifest, the bundler manifest,
|
|
# the source, the docs and (once you add one) the deploy script. Nothing makes
|
|
# them agree, so a rename drifts silently: the bundle builds under one name and
|
|
# the deploy script looks for another. This asserts they match, and that the
|
|
# identity constants are legal.
|
|
#
|
|
# In a template this matters more than usual: renaming is the first thing you do
|
|
# with this repo, and it touches every file below. Run this immediately after,
|
|
# and the STALE machinery will list whatever you missed.
|
|
#
|
|
# Usage: sh tools/check-branding.sh (exit 0 = consistent, 1 = drift found)
|
|
#
|
|
# The canonical identity lives in branding.conf, shared with brand-plugin.sh.
|
|
# Edit it there, then run this to find every copy that still holds the old value.
|
|
|
|
set -u
|
|
# Resolve the repo root: these live in tools/, every path they touch is
|
|
# repo-relative, and they must behave the same wherever they are invoked from.
|
|
cd "$(dirname "$0")/.." || exit 1
|
|
|
|
if [ ! -f tools/branding.conf ]; then
|
|
printf 'tools/branding.conf not found\n' >&2
|
|
exit 1
|
|
fi
|
|
# shellcheck disable=SC1091
|
|
. ./tools/branding.conf
|
|
|
|
# Every canonical spelling concatenated, for the substring test below.
|
|
CANONICAL_BLOB="$PKG
|
|
$DESCRIPTION
|
|
$CLAP_DESCRIPTION
|
|
$STRUCT
|
|
$PARAMS_STRUCT
|
|
$DISPLAY
|
|
$PLUGIN_NAME
|
|
$VENDOR
|
|
$EMAIL
|
|
$HOMEPAGE
|
|
$CLAP_ID
|
|
$VST3_CLASS_ID"
|
|
|
|
pass=0; fail=0; skip=0
|
|
ok() { pass=$((pass+1)); printf ' ok %s\n' "$1"; }
|
|
bad() { fail=$((fail+1)); printf ' FAIL %s\n' "$1"; [ $# -gt 1 ] && printf ' %s\n' "$2"; return 0; }
|
|
note() { skip=$((skip+1)); printf ' skip %s\n' "$1"; }
|
|
# Reported for awareness only - never counted, never fails the run.
|
|
info() { printf ' -- %s\n' "$1"; }
|
|
|
|
# has FILE PATTERN -> fixed-string search
|
|
has() { grep -qF "$2" "$1" 2>/dev/null; }
|
|
|
|
check() { # check LABEL FILE LITERAL
|
|
if [ ! -f "$2" ]; then bad "$1" "missing file: $2"; return; fi
|
|
if has "$2" "$3"; then ok "$1"; else bad "$1" "$2 does not contain: $3"; fi
|
|
}
|
|
|
|
# Same as check, but a missing file is "not applicable yet" rather than drift.
|
|
# The template ships without a deploy script; this starts checking once you add one.
|
|
opt_check() { # opt_check LABEL FILE LITERAL
|
|
if [ ! -f "$2" ]; then note "$1 ($2 not present)"; return; fi
|
|
if has "$2" "$3"; then ok "$1"; else bad "$1" "$2 does not contain: $3"; fi
|
|
}
|
|
|
|
printf 'branding check (canonical: %s / "%s")\n\n' "$PKG" "$DISPLAY"
|
|
|
|
# --- consistency: every site in the table holds its resolved literal ----------
|
|
# The table is data, so adding a site is a row rather than a shell edit, and the
|
|
# same script runs unmodified across every plugin built from this template.
|
|
SITES="tools/branding-sites.tsv"
|
|
if [ ! -f "$SITES" ]; then
|
|
bad "site table" "$SITES not found - run tools/brand-plugin.sh to generate it"
|
|
else
|
|
printf 'sites\n'
|
|
while IFS="$(printf '\t')" read -r kind owner file pattern; do
|
|
case "$kind" in ''|\#*) continue ;; esac
|
|
[ -n "$pattern" ] || continue
|
|
label="$owner"
|
|
if [ ! -f "$file" ]; then
|
|
case "$kind" in
|
|
opt) note "$label ($file not present)" ;;
|
|
*) bad "$label" "missing file: $file" ;;
|
|
esac
|
|
continue
|
|
fi
|
|
if has "$file" "$pattern"; then ok "$label"
|
|
else bad "$label" "$file does not contain: $pattern"; fi
|
|
done < "$SITES"
|
|
fi
|
|
|
|
# --- validity: rules the table cannot express --------------------------------
|
|
printf '\nvalidity\n'
|
|
|
|
# VST3 class IDs are a fixed 16-byte array. A wrong length is a compile error,
|
|
# but saying so here is clearer than reading rustc on it.
|
|
n=$(printf '%s' "$VST3_CLASS_ID" | wc -c | tr -d ' ')
|
|
if [ "$n" -eq 16 ]; then ok "VST3_CLASS_ID is 16 bytes"
|
|
else bad "VST3_CLASS_ID is 16 bytes" "got $n bytes: \"$VST3_CLASS_ID\""; fi
|
|
|
|
# CLAP IDs are reverse-DNS by convention and compared verbatim by hosts, so a
|
|
# stray space or capital is a silent identity change between machines.
|
|
case "$CLAP_ID" in
|
|
*\ *|*[A-Z]*) bad "CLAP_ID is reverse-DNS safe" "no spaces or capitals allowed: \"$CLAP_ID\"" ;;
|
|
*.*) ok "CLAP_ID is reverse-DNS safe" ;;
|
|
*) bad "CLAP_ID is reverse-DNS safe" "expected dotted reverse-DNS, got: \"$CLAP_ID\"" ;;
|
|
esac
|
|
|
|
# An overridden package name is legitimate - the derivation is sometimes invalid
|
|
# - but a display rename that forgot the package is not, and looks identical
|
|
# from here. Reported, never failed.
|
|
derived_pkg=$(_derive_pkg "$PLUGIN_NAME")
|
|
[ "$PKG" = "$derived_pkg" ] || info "PKG \"$PKG\" differs from the derivation of PLUGIN_NAME (\"$derived_pkg\") - fine if deliberate"
|
|
|
|
# CLAP_DESCRIPTION is shown to users in a host's plugin browser. "Free of
|
|
# development history" is a judgement a script cannot make, but the failure it
|
|
# produces is mechanical: a retired name or the repo codename surviving in it.
|
|
hygiene_hits=""
|
|
while IFS= read -r s_entry; do
|
|
[ -n "$s_entry" ] || continue
|
|
case "$CANONICAL_BLOB" in *"$s_entry"*) continue ;; esac
|
|
case "$CLAP_DESCRIPTION" in *"$s_entry"*) hygiene_hits="$hygiene_hits \"$s_entry\"" ;; esac
|
|
done <<HYGIENE_LIST
|
|
$STALE
|
|
$CODENAME
|
|
HYGIENE_LIST
|
|
if [ -z "$hygiene_hits" ]; then ok "CLAP_DESCRIPTION carries no retired name or codename"
|
|
else bad "CLAP_DESCRIPTION carries no retired name or codename" "found:$hygiene_hits"; fi
|
|
|
|
printf '\nstale spellings\n'
|
|
# File list for the scan below. Prefer git, so build output and any vendored
|
|
# tree stay out of it. Fall back to find when this is not a checkout - an
|
|
# exported tarball, or a CI step that fetched without git metadata - because
|
|
# `git ls-files` there returns nothing, and an empty list would report every
|
|
# stale spelling as absent. A check that passes hardest when it can see least
|
|
# is worse than no check.
|
|
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
file_list() { git ls-files; }
|
|
scan_source="git"
|
|
else
|
|
file_list() { find . -path ./.git -prune -o -path ./target -prune -o -type f -print | sed 's|^\./||'; }
|
|
scan_source="find (not a git checkout)"
|
|
fi
|
|
info "scanning tracked files via $scan_source"
|
|
# Fed by here-doc rather than a pipe on purpose: a piped `while` runs in a
|
|
# subshell, and the pass/fail counters it increments would be discarded.
|
|
while IFS= read -r s; do
|
|
[ -n "$s" ] || continue
|
|
|
|
# Still part of a canonical value? Then it is current branding, not a leftover.
|
|
# This is what lets the list ship pre-seeded: entries arm themselves as you
|
|
# rename. Substring, not equality, because placeholders nest - "your-domain"
|
|
# lives inside the canonical CLAP_ID, and "YOUR-USERNAME" inside the homepage.
|
|
# Over-skipping is the safe direction: a false FAIL on a name you still use
|
|
# would train you to ignore this section.
|
|
case "$CANONICAL_BLOB" in
|
|
*"$s"*) note "\"$s\" (still canonical)"; continue ;;
|
|
esac
|
|
|
|
# These two name every retired spelling by definition - the STALE list lives in
|
|
# branding.conf and this script reads it - so neither can ever be a real hit.
|
|
hits=$(file_list 2>/dev/null | while read -r f; do
|
|
case "$f" in tools/check-branding.sh|tools/branding.conf) continue ;; esac
|
|
[ -f "$f" ] && grep -lF "$s" "$f" 2>/dev/null
|
|
done)
|
|
if [ -z "$hits" ]; then ok "no occurrences of \"$s\""
|
|
else bad "no occurrences of \"$s\"" "still present in: $(echo "$hits" | tr '\n' ' ')"; fi
|
|
done <<STALE_LIST
|
|
$STALE
|
|
STALE_LIST
|
|
|
|
# Template scaffolding, not drift: TODOs are legitimate while you are still
|
|
# building. Reported so a finished plugin does not quietly ship with them.
|
|
# `grep -c` prints 0 AND exits 1 when there are no matches, so `|| echo 0`
|
|
# would append a second zero and make the count unparseable. Swallow the
|
|
# status instead, and default an empty result (missing file) to zero.
|
|
todos=$(grep -c 'TODO' src/lib.rs 2>/dev/null || :)
|
|
[ -n "$todos" ] || todos=0
|
|
printf '\nscaffolding\n'
|
|
if [ "$todos" -eq 0 ]; then ok "no TODO markers left in src/lib.rs"
|
|
else info "$todos TODO marker(s) still in src/lib.rs (not a failure)"; fi
|
|
|
|
printf '\n%d passed, %d failed' "$pass" "$fail"
|
|
[ "$skip" -gt 0 ] && printf ', %d skipped' "$skip"
|
|
printf '\n'
|
|
[ "$fail" -eq 0 ] || exit 1
|