#!/bin/sh # 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 check-branding.sh (exit 0 = consistent, 1 = drift found) # # --------------------------------------------------------------------------- # CANONICAL IDENTITY - the single source of truth. Edit these to rename, then # run this script; every failure it prints is a place still holding the old name. # --------------------------------------------------------------------------- PKG="nih_plug_template" # Cargo package name == bundler.toml table key DISPLAY="Plugin Name" # bundle name -> ".vst3" / ".clap" PLUGIN_NAME="Plugin Name" # Plugin::NAME - what the DAW displays VENDOR="Your Name" # Plugin::VENDOR EMAIL="your@email.com" # Plugin::EMAIL HOMEPAGE="https://github.com/YOUR-USERNAME/YOUR-PLUGIN-NAME" # Cargo homepage -> Plugin::URL CLAP_ID="com.your-domain.plugin-name" # CLAP_ID - stable plugin identity VST3_CLASS_ID="Unique16CharId!!" # VST3_CLASS_ID - stable identity, MUST be 16 bytes # Spellings that must no longer appear anywhere in tracked files. Seeded with # this template's own placeholders, so that renaming is self-checking: each entry # is skipped while it is still one of the canonical values above, and becomes a # live check the moment you change that value. Add your own old names here after # a later rename. STALE="nih_plug_template Plugin Name Your Name your@email.com com.your-domain.plugin-name Unique16CharId!! YOUR-USERNAME YOUR-PLUGIN-NAME your-domain" set -u cd "$(dirname "$0")" || exit 1 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"; } # 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" printf 'build manifests\n' check "Cargo.toml package name" Cargo.toml "name = \"$PKG\"" check "Cargo.toml homepage" Cargo.toml "homepage = \"$HOMEPAGE\"" 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\"" 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 '\ndocs\n' opt_check "README bundle command" README.md "cargo xtask bundle $PKG" printf '\ndeploy script\n' 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\"" printf '\nstale spellings\n' # Every canonical spelling concatenated, for the substring test below. CANONICAL_BLOB="$PKG $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 # 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=$(git ls-files 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 <