diff --git a/check-branding.sh b/check-branding.sh index a5b4253..eeaf98b 100644 --- a/check-branding.sh +++ b/check-branding.sh @@ -2,9 +2,14 @@ # check-branding.sh - verify the plugin's branding/identity strings agree everywhere. # # Plugin branding is duplicated across the build manifest, the bundler manifest, -# the deploy script and the source. 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. +# the source, the docs and 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. +# +# Kept in sync with musiikki/nih-plug-template's copy - fixes belong there +# first, then come back here. The differences are structural, not stylistic: +# this repo keeps its params in src/params.rs and wraps CLAP_DESCRIPTION. # # Usage: sh check-branding.sh (exit 0 = consistent, 1 = drift found) # @@ -13,23 +18,43 @@ # run this script; every failure it prints is a place still holding the old name. # --------------------------------------------------------------------------- -PKG="codename_206" # Cargo package name == bundler.toml table key -DISPLAY="Codename 206" # bundle name -> ".vst3" / ".clap" -PLUGIN_NAME="206 prototype" # Plugin::NAME - what the DAW displays -CLAP_ID="com.mikkeli.codename-206" # CLAP_ID - stable plugin identity -VST3_CLASS_ID="Codename206Maxi!" # VST3_CLASS_ID - stable identity, MUST be 16 bytes +PKG="codename_206" # Cargo package name == bundler.toml table key +DISPLAY="Codename 206" # bundle name -> ".vst3" / ".clap" +PLUGIN_NAME="206 prototype" # Plugin::NAME - what the DAW displays +VENDOR="Novoyuuparosk" # Plugin::VENDOR +EMAIL="mikkeli@novoyuuparosk.org" # Plugin::EMAIL +HOMEPAGE="https://github.com/mikkeli/codename-206" # Cargo homepage -> Plugin::URL +CLAP_ID="com.mikkeli.codename-206" # CLAP_ID - stable plugin identity +VST3_CLASS_ID="Codename206Maxi!" # VST3_CLASS_ID - stable identity, MUST be 16 bytes +DESCRIPTION="A VST3/CLAP multiband compressor/limiter with a custom gain-curve display" +CLAP_DESCRIPTION="Multiband compressor/limiter (stage 3: 3-band + 'All' channel)" -# Spellings that must no longer appear anywhere in tracked files. Populate this -# with the OLD names after a rename to catch leftovers; keep empty otherwise. -# Space-separated; use a form with no spaces, or quote carefully. -STALE="" +# Rust type names. Cosmetic - they never reach a host - but a rename that leaves +# half of them behind is the residue that says nobody read the file. +STRUCT="Codename206" # the Plugin impl target (src/lib.rs) +PARAMS_STRUCT="Codename206Params" # the Params impl target (src/params.rs) +# Seeded with this repo's CURRENT names, which is the point: each entry is +# skipped while it is still canonical above, and arms itself the moment you +# change that value. So the planned "codename 206" -> "206" rename is +# self-checking - every spelling you miss turns into a FAIL here on the next run. +STALE="codename_206 +codename-206 +Codename 206 +Codename206 +Codename206Params +Codename206Maxi! +206 prototype +com.mikkeli.codename-206" set -u cd "$(dirname "$0")" || exit 1 -pass=0; fail=0 +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; } @@ -39,38 +64,137 @@ check() { # check LABEL FILE LITERAL 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" printf 'build manifests\n' check "Cargo.toml package name" Cargo.toml "name = \"$PKG\"" +check "Cargo.toml homepage" Cargo.toml "homepage = \"$HOMEPAGE\"" +check "Cargo.toml description" Cargo.toml "description = \"$DESCRIPTION\"" check "bundler.toml table key" bundler.toml "[$PKG]" check "bundler.toml display name" bundler.toml "name = \"$DISPLAY\"" printf '\nsource identity (src/lib.rs)\n' check "Plugin::NAME" src/lib.rs "const NAME: &'static str = \"$PLUGIN_NAME\"" +check "Plugin::VENDOR" src/lib.rs "const VENDOR: &'static str = \"$VENDOR\"" +check "Plugin::EMAIL" src/lib.rs "const EMAIL: &'static str = \"$EMAIL\"" check "CLAP_ID" src/lib.rs "const CLAP_ID: &'static str = \"$CLAP_ID\"" +# CLAP_DESCRIPTION wraps onto a second line here, so the const name and its +# value are never on one line. Match the value alone. +check "CLAP_DESCRIPTION" src/lib.rs "Some(\"$CLAP_DESCRIPTION\")" check "VST3_CLASS_ID" src/lib.rs "const VST3_CLASS_ID: [u8; 16] = *b\"$VST3_CLASS_ID\"" +# Plugin::URL is env!("CARGO_PKG_HOMEPAGE"), so the manifest is the only place +# it is spelled. Assert the indirection is still in place rather than hardcoded. +check "Plugin::URL from manifest" src/lib.rs "const URL: &'static str = env!(\"CARGO_PKG_HOMEPAGE\")" + # VST3 class IDs are a fixed 16-byte array. A shorter or longer literal is a # compile error, but it is far clearer to say so here than to read 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 are 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 + +printf '\nstructural names (src/lib.rs)\n' +# Every site the type names appear. A rename that misses one is a compile error +# rather than silent drift, but naming the site is faster than reading rustc, +# and the Vst3Plugin impl sits behind a cfg so a default build never reports it. +check "struct $STRUCT" src/lib.rs "struct $STRUCT {" +check "impl Plugin" src/lib.rs "impl Plugin for $STRUCT {" +check "impl ClapPlugin" src/lib.rs "impl ClapPlugin for $STRUCT {" +check "impl Vst3Plugin" src/lib.rs "impl Vst3Plugin for $STRUCT {" +check "nih_export_clap!" src/lib.rs "nih_export_clap!($STRUCT);" +check "nih_export_vst3!" src/lib.rs "nih_export_vst3!($STRUCT);" +check "struct $PARAMS_STRUCT" src/params.rs "struct $PARAMS_STRUCT {" +check "impl Default for params" src/params.rs "impl Default for $PARAMS_STRUCT {" +check "params field type" src/lib.rs "params: Arc<$PARAMS_STRUCT>," + +printf '\ndocs\n' +opt_check "README bundle command" README.md "cargo xtask bundle $PKG" + printf '\ndeploy script\n' -check "deploy.ps1 default package" deploy.ps1 "\$Package = \"$PKG\"" -check "deploy.ps1 VST3 bundle" deploy.ps1 "\$vst3Name = \"$DISPLAY.vst3\"" -check "deploy.ps1 CLAP bundle" deploy.ps1 "\$clapName = \"$DISPLAY.clap\"" +opt_check "deploy.ps1 default package" deploy.ps1 "\$Package = \"$PKG\"" +opt_check "deploy.ps1 VST3 bundle" deploy.ps1 "\$vst3Name = \"$DISPLAY.vst3\"" +opt_check "deploy.ps1 CLAP bundle" deploy.ps1 "\$clapName = \"$DISPLAY.clap\"" -if [ -n "$STALE" ]; then - printf '\nstale spellings\n' - for s in $STALE; do - hits=$(git ls-files 2>/dev/null | while read -r f; do - [ -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 +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" +# 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" +# 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 -printf '\n%d passed, %d failed\n' "$pass" "$fail" + # 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 + + # This script names every placeholder by definition, so it can never be a hit. + hits=$(file_list 2>/dev/null | while read -r f; do + [ "$f" = "check-branding.sh" ] || { [ -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