#!/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 </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 </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