Compare commits
21 Commits
b05ad27a24
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| ce410b0047 | |||
| 5212b7806b | |||
| 09d98bef06 | |||
| 3abbb06073 | |||
| 8630ba0c5b | |||
| fad8e21b2b | |||
| f8aa3ee888 | |||
| 24c6ee0655 | |||
| de2dbbc218 | |||
| 1dc836dca5 | |||
| 7b7ba69082 | |||
| 689891d01b | |||
| a09b28d5fa | |||
| 62ac2e9d6c | |||
| 4a7dad95b3 | |||
| 454e80bcd5 | |||
| 0500de9eb9 | |||
| 5f612dde57 | |||
| 8c24b83ea3 | |||
| 2dd47b5afd | |||
| a46e7eb961 |
+19
-3
@@ -1,4 +1,20 @@
|
||||
# Shell scripts must keep LF endings. core.autocrlf=true on Windows would
|
||||
# otherwise check them out CRLF, which a strict POSIX sh (dash, CI containers)
|
||||
# rejects at the shebang.
|
||||
# Line endings: LF in the repository and in every working tree, on every OS.
|
||||
#
|
||||
# This file is the policy, not each machine's git config. Git for Windows installs
|
||||
# with core.autocrlf=true, which checks text out as CRLF; an attribute here beats
|
||||
# that setting, so a fresh clone gets LF regardless of how its machine is set up.
|
||||
#
|
||||
# It matters beyond tidiness. tools/branding-sites.tsv is read line by line with
|
||||
# `read`, and under CRLF every row's last field gained a trailing CR byte - so the
|
||||
# branding checker reported all 29 sites as missing on Windows while passing on the
|
||||
# Linux CI runner. text=auto leaves genuinely binary files alone.
|
||||
* text=auto eol=lf
|
||||
|
||||
# Shell scripts are pinned explicitly as well: a strict POSIX sh (dash, CI
|
||||
# containers) rejects a CRLF shebang outright rather than misbehaving quietly.
|
||||
*.sh text eol=lf
|
||||
|
||||
# The exception. cmd.exe misparses LF-only batch files around labels and long
|
||||
# lines, so these alone are checked out CRLF. The repository copy is still LF.
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
|
||||
@@ -9,9 +9,25 @@ on:
|
||||
- 'Cargo.toml'
|
||||
- 'Cargo.lock'
|
||||
- 'bundler.toml'
|
||||
- 'check-branding.sh'
|
||||
- 'tools/**'
|
||||
# This workflow validates itself: a broken step, a moved script path or a
|
||||
# wrong runner label then fails loudly on the commit that caused it, rather
|
||||
# than surfacing later against an unrelated source change. Note the limit -
|
||||
# it checks the job body, not the trigger block above. Break `on:` and the
|
||||
# symptom is silence, which looks like success.
|
||||
- '.github/workflows/**'
|
||||
# Mirrors the push filter. Without it a PR touching only the README would run a
|
||||
# full build - the branch filter alone constrains where, not what.
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'xtask/**'
|
||||
- 'Cargo.toml'
|
||||
- 'Cargo.lock'
|
||||
- 'bundler.toml'
|
||||
- 'tools/**'
|
||||
- '.github/workflows/**'
|
||||
workflow_dispatch:
|
||||
|
||||
# Target the self-hosted Rust/audio runner registered to the `musiikki` org.
|
||||
@@ -41,7 +57,7 @@ jobs:
|
||||
# Cheap and needs no toolchain, so it runs first: a rename that only
|
||||
# landed in half the files is worth catching before spending a build on it.
|
||||
- name: Branding consistency
|
||||
run: sh check-branding.sh
|
||||
run: sh tools/check-branding.sh
|
||||
|
||||
# The default build is CLAP-only; the vst3 feature is opt-in, so both
|
||||
# configurations have to be built to know the cfg gates are still correct.
|
||||
@@ -58,4 +74,4 @@ jobs:
|
||||
# not exercise — the bundle step is where bundler.toml and the crate name
|
||||
# have to agree.
|
||||
- name: Bundle
|
||||
run: cargo xtask bundle nih_plug_template --release --features vst3
|
||||
run: cargo xtask bundle plugin_name --release --features vst3
|
||||
|
||||
Generated
+8
-8
@@ -1102,14 +1102,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nih_plug_template"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nih_plug",
|
||||
"nih_plug_egui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nih_plug_xtask"
|
||||
version = "0.1.0"
|
||||
@@ -1502,6 +1494,14 @@ version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||
|
||||
[[package]]
|
||||
name = "plugin_name"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nih_plug",
|
||||
"nih_plug_egui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "3.11.0"
|
||||
|
||||
+11
-3
@@ -1,9 +1,9 @@
|
||||
[package]
|
||||
name = "nih_plug_template"
|
||||
name = "plugin_name"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["Your Name <your@email.com>"]
|
||||
homepage = "https://github.com/YOUR-USERNAME/YOUR-PLUGIN-NAME"
|
||||
homepage = "https://wiki.novoyuuparosk.org"
|
||||
description = "A minimal NIH-plug audio plugin"
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
@@ -15,7 +15,7 @@ members = ["xtask"]
|
||||
# longer raises a licensing question — the gate now just keeps the default build
|
||||
# light, since `vst3-sys` and its macro machinery are a sizeable dependency a
|
||||
# CLAP-only plugin never needs. Flip `default` to ["vst3"] if you always want it:
|
||||
# cargo xtask bundle nih_plug_template --release --features vst3
|
||||
# cargo xtask bundle plugin_name --release --features vst3
|
||||
default = []
|
||||
vst3 = ["nih_plug/vst3"]
|
||||
|
||||
@@ -23,6 +23,14 @@ vst3 = ["nih_plug/vst3"]
|
||||
# `cdylib` is the plugin binary; `lib` (rlib) lets `cargo test` link the unit tests.
|
||||
crate-type = ["cdylib", "lib"]
|
||||
|
||||
# Future-incompatibility warnings are deferred hard errors: rustc is telling you
|
||||
# this code stops compiling on some later release. Denying the group turns that
|
||||
# into a build failure the day it appears, rather than accumulating unnoticed
|
||||
# until a toolchain bump breaks the build on a day you did not choose. Style and
|
||||
# clippy lints are deliberately untouched - they stay warnings.
|
||||
[lints.rust]
|
||||
future_incompatible = { level = "deny", priority = -1 }
|
||||
|
||||
[dependencies]
|
||||
# Pinned to the same commit as musiikki/codename-206.
|
||||
# Update the `rev` when you want to update NIH-plug.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
nih-plug-template
|
||||
Plugin Name
|
||||
Copyright 2026 Mikkeli Matlock
|
||||
|
||||
This product is licensed under the GNU General Public License v3.0 or later.
|
||||
|
||||
@@ -20,31 +20,53 @@ sh check-branding.sh
|
||||
|
||||
## Renaming
|
||||
|
||||
Branding is duplicated across `Cargo.toml`, `bundler.toml`, `src/lib.rs` and the docs,
|
||||
and nothing makes those agree — so a half-finished rename builds a bundle under one name
|
||||
while the docs and deploy script look for another.
|
||||
Identity is duplicated across `Cargo.toml`, `bundler.toml`, `src/lib.rs`, `NOTICE`,
|
||||
`Cargo.lock`, the CI workflow and the docs. Nothing makes those agree, so a half-finished
|
||||
rename builds a bundle under one name while CI bundles another.
|
||||
|
||||
`check-branding.sh` declares the identity once at the top and asserts every copy matches:
|
||||
Everything for it lives in `tools/`:
|
||||
|
||||
```bash
|
||||
sh check-branding.sh # exit 0 = consistent, 1 = drift found
|
||||
```
|
||||
tools/branding.conf the names, and what derives from what
|
||||
tools/branding-sites.tsv where each name has to appear, and in what form
|
||||
tools/brand-plugin.sh changes names
|
||||
tools/check-branding.sh verifies them
|
||||
```
|
||||
|
||||
It covers the identity a host actually sees (package and bundle names, `Plugin::NAME`,
|
||||
`VENDOR`, `EMAIL`, `CLAP_ID`, `VST3_CLASS_ID`, the descriptions) and the Rust type names
|
||||
(`MyPlugin`, `PluginParams`) at every site they appear. Renaming the types is cosmetic —
|
||||
no host ever sees them — but leaving `MyPlugin` in a shipped plugin is the kind of residue
|
||||
that says nobody read the file. Leave them as-is and those checks simply stay green.
|
||||
```bash
|
||||
sh tools/brand-plugin.sh # interactive; Enter keeps a value
|
||||
sh tools/brand-plugin.sh --display "Fuzz Box" # or non-interactive; dry run
|
||||
sh tools/brand-plugin.sh --display "Fuzz Box" --apply
|
||||
sh tools/check-branding.sh # exit 0 = consistent, 1 = drift
|
||||
```
|
||||
|
||||
To rename: edit the canonical block at the top of the script, run it, and fix everything
|
||||
it reports. The placeholder spellings are pre-seeded into its `STALE` list, and each one
|
||||
arms itself as soon as you change the matching canonical value — so leftovers surface
|
||||
without you having to track them. It also asserts `VST3_CLASS_ID` is exactly 16 bytes and
|
||||
that `CLAP_ID` is reverse-DNS safe, both of which are otherwise a compile error or a
|
||||
silent identity change between machines.
|
||||
**One name drives the rest.** `PLUGIN_NAME` derives the package name (`Fuzz Box` →
|
||||
`fuzz_box`), the Rust types (`FuzzBox`, `FuzzBoxParams`) and the display name. Each is
|
||||
overridable in `branding.conf`, because the derivation is sometimes wrong and sometimes
|
||||
outright invalid — `206 Prototype` derives to `206_prototype`, which Cargo rejects since a
|
||||
package name cannot start with a digit. The helper refuses those, along with Rust keywords
|
||||
and built-in crate names.
|
||||
|
||||
Checks for files the template doesn't ship (e.g. a `deploy.ps1`) report as `skip` and
|
||||
start enforcing once you add them.
|
||||
**The checker does both halves.** Every canonical value is asserted *present* where it
|
||||
belongs, and every retired spelling is swept for. Absence alone is not enough: renaming to
|
||||
the wrong new spelling would pass a stale-sweep and still break CI.
|
||||
|
||||
**Two things it will not do for you.** `CLAP_ID` and `VST3_CLASS_ID` are how hosts recognise
|
||||
saved projects and presets — change either and every existing session silently loses the
|
||||
plugin, with no error. They need `--allow-identity-change`, and the 16-byte class ID is
|
||||
*proposed* rather than derived, because that choice is yours. And `CLAP_DESCRIPTION` is
|
||||
rejected if it carries a retired name or the repo codename: hosts show it to users who never
|
||||
knew your development history.
|
||||
|
||||
**The repo name is deliberately not derived.** It is fixed when the repo is created and keeps
|
||||
its development codename while the plugin gets a product name. `CODENAME` records it so it
|
||||
can be kept out of user-facing text.
|
||||
|
||||
Adding a site the template doesn't ship is one row in `branding-sites.tsv` with owner
|
||||
`custom` — no shell to edit, and it survives regeneration. Rows the helper owns are rewritten
|
||||
on each rename; custom rows are carried through and value-substituted like any other file.
|
||||
Both files can be hand-edited; the helper is what keeps them agreeing, so run the checker
|
||||
after if you do.
|
||||
|
||||
## Build
|
||||
|
||||
@@ -53,10 +75,10 @@ start enforcing once you add them.
|
||||
# No VST3 SDK needed — NIH-plug bundles its own bindings.
|
||||
|
||||
# Build + bundle the CLAP (default)
|
||||
cargo xtask bundle nih_plug_template --release
|
||||
cargo xtask bundle plugin_name --release
|
||||
|
||||
# Add the VST3 as well — see the licensing note below before you do this
|
||||
cargo xtask bundle nih_plug_template --release --features vst3
|
||||
cargo xtask bundle plugin_name --release --features vst3
|
||||
```
|
||||
|
||||
**Output:** `target/bundled/<name>.clap` (and `<name>.vst3` with `--features vst3`), where
|
||||
@@ -105,7 +127,7 @@ bundler.toml # Bundle name for `cargo xtask bundle`
|
||||
src/lib.rs # Plugin skeleton — params, DSP, and egui editor, with one example gain param
|
||||
xtask/ # Bundler xtask (cargo xtask bundle)
|
||||
.cargo/config.toml # xtask alias
|
||||
check-branding.sh # Asserts the plugin's identity strings agree everywhere (see Renaming)
|
||||
tools/ # Branding toolkit — see Renaming
|
||||
.gitattributes # Pins *.sh to LF so Windows checkouts keep a valid shebang
|
||||
.github/workflows/ # CI: branding check, both feature sets build, test, bundle
|
||||
```
|
||||
|
||||
+1
-1
@@ -3,5 +3,5 @@
|
||||
# [package_name]
|
||||
# name = "Human Readable Bundle Name" # defaults to <package_name>
|
||||
|
||||
[nih_plug_template]
|
||||
[plugin_name]
|
||||
name = "Plugin Name"
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
#!/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 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 -> "<DISPLAY>.vst3" / "<DISPLAY>.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
|
||||
DESCRIPTION="A minimal NIH-plug audio plugin" # Cargo package description
|
||||
CLAP_DESCRIPTION="Your plugin description" # CLAP_DESCRIPTION - shown in some host browsers
|
||||
|
||||
# Rust type names. These never reach a host, so renaming them is cosmetic - but
|
||||
# leaving "MyPlugin" in a shipped plugin is the sort of residue that says nobody
|
||||
# read the file. Change these to make the checks below enforce your own names;
|
||||
# leave them alone and they simply stay green.
|
||||
STRUCT="MyPlugin" # the Plugin impl target
|
||||
PARAMS_STRUCT="PluginParams" # the Params impl target
|
||||
|
||||
# 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
|
||||
MyPlugin
|
||||
PluginParams
|
||||
A minimal NIH-plug audio plugin
|
||||
Your plugin description
|
||||
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"; }
|
||||
# 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"
|
||||
|
||||
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\""
|
||||
check "CLAP_DESCRIPTION" src/lib.rs "const CLAP_DESCRIPTION: Option<&'static str> = 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/lib.rs "struct $PARAMS_STRUCT {"
|
||||
check "impl Default for params" src/lib.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'
|
||||
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'
|
||||
# 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
|
||||
|
||||
# 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 <<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
|
||||
+9
-9
@@ -10,7 +10,7 @@ use std::sync::Arc;
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
#[derive(Params)]
|
||||
struct PluginParams {
|
||||
struct PluginNameParams {
|
||||
/// Editor window size, persisted with the plugin state.
|
||||
#[persist = "editor-state"]
|
||||
editor_state: Arc<EguiState>,
|
||||
@@ -21,7 +21,7 @@ struct PluginParams {
|
||||
gain: FloatParam,
|
||||
}
|
||||
|
||||
impl Default for PluginParams {
|
||||
impl Default for PluginNameParams {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
editor_state: EguiState::from_size(320, 160),
|
||||
@@ -47,11 +47,11 @@ impl Default for PluginParams {
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
#[derive(Default)]
|
||||
struct MyPlugin {
|
||||
params: Arc<PluginParams>,
|
||||
struct PluginName {
|
||||
params: Arc<PluginNameParams>,
|
||||
}
|
||||
|
||||
impl Plugin for MyPlugin {
|
||||
impl Plugin for PluginName {
|
||||
// TODO: Replace these placeholder values with your plugin's metadata.
|
||||
const NAME: &'static str = "Plugin Name";
|
||||
const VENDOR: &'static str = "Your Name";
|
||||
@@ -124,7 +124,7 @@ impl Plugin for MyPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
impl ClapPlugin for MyPlugin {
|
||||
impl ClapPlugin for PluginName {
|
||||
// TODO: Replace with a unique CLAP ID in reverse-DNS form, e.g. "com.acme.fuzzbox"
|
||||
const CLAP_ID: &'static str = "com.your-domain.plugin-name";
|
||||
const CLAP_DESCRIPTION: Option<&'static str> = Some("Your plugin description");
|
||||
@@ -134,13 +134,13 @@ impl ClapPlugin for MyPlugin {
|
||||
}
|
||||
|
||||
#[cfg(feature = "vst3")]
|
||||
impl Vst3Plugin for MyPlugin {
|
||||
impl Vst3Plugin for PluginName {
|
||||
// TODO: Replace with a unique 16-byte Class ID.
|
||||
// Must be exactly 16 bytes — padded with '!' if shorter.
|
||||
const VST3_CLASS_ID: [u8; 16] = *b"Unique16CharId!!";
|
||||
const VST3_SUBCATEGORIES: &'static [Vst3SubCategory] = &[Vst3SubCategory::Fx];
|
||||
}
|
||||
|
||||
nih_export_clap!(MyPlugin);
|
||||
nih_export_clap!(PluginName);
|
||||
#[cfg(feature = "vst3")]
|
||||
nih_export_vst3!(MyPlugin);
|
||||
nih_export_vst3!(PluginName);
|
||||
|
||||
Executable
+355
@@ -0,0 +1,355 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# brand-plugin.sh - rename this plugin, everywhere, in one go.
|
||||
#
|
||||
# check-branding.sh tells you what disagrees. This changes it. They share
|
||||
# branding.conf: this script rewrites that file and every copy of the old values
|
||||
# in tracked files, then runs the checker and reports what it says. A run that
|
||||
# ends with the checker green is a rename that landed.
|
||||
#
|
||||
# Dry run by default:
|
||||
# sh brand-plugin.sh --display "Bari 206"
|
||||
# sh brand-plugin.sh --display "Bari 206" --vendor Novoyuuparosk --apply
|
||||
#
|
||||
# Options:
|
||||
# --display NAME the product name, with spaces and capitals. Everything
|
||||
# else that can be derived, is derived from this.
|
||||
# --pkg NAME override the derived Cargo package name.
|
||||
# --vendor NAME --email ADDR --homepage URL
|
||||
# --description D --clap-description D
|
||||
# --struct NAME override the derived Rust type name.
|
||||
# --allow-identity-change permit CLAP_ID / VST3_CLASS_ID to move. See below.
|
||||
# --apply actually write. Without it, nothing is modified.
|
||||
|
||||
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
|
||||
[ -f tools/branding.conf ] || { printf 'tools/branding.conf not found\n' >&2; exit 1; }
|
||||
# shellcheck disable=SC1091
|
||||
. ./tools/branding.conf
|
||||
|
||||
OLD_PKG="$PKG"; OLD_DISPLAY="$DISPLAY"; OLD_PLUGIN_NAME="$PLUGIN_NAME"
|
||||
OLD_VENDOR="$VENDOR"; OLD_EMAIL="$EMAIL"; OLD_HOMEPAGE="$HOMEPAGE"; OLD_AUTHOR="$AUTHOR"
|
||||
OLD_DESCRIPTION="$DESCRIPTION"; OLD_CLAP_DESCRIPTION="$CLAP_DESCRIPTION"
|
||||
OLD_CLAP_ID="$CLAP_ID"; OLD_VST3="$VST3_CLASS_ID"
|
||||
OLD_STRUCT="$STRUCT"; OLD_PARAMS_STRUCT="$PARAMS_STRUCT"
|
||||
|
||||
new_display=""; new_pkg=""; new_vendor=""; new_email=""; new_homepage=""
|
||||
new_description=""; new_clap_description=""; new_struct=""; new_author=""
|
||||
new_clap_id=""; new_vst3=""; apply=0; allow_identity=0
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--display) new_display="${2:?}"; shift 2 ;;
|
||||
--pkg) new_pkg="${2:?}"; shift 2 ;;
|
||||
--vendor) new_vendor="${2:?}"; shift 2 ;;
|
||||
--author) new_author="${2:?}"; shift 2 ;;
|
||||
--email) new_email="${2:?}"; shift 2 ;;
|
||||
--homepage) new_homepage="${2:?}"; shift 2 ;;
|
||||
--description) new_description="${2:?}"; shift 2 ;;
|
||||
--clap-description) new_clap_description="${2:?}"; shift 2 ;;
|
||||
--struct) new_struct="${2:?}"; shift 2 ;;
|
||||
--clap-id) new_clap_id="${2:?}"; shift 2 ;;
|
||||
--vst3-class-id) new_vst3="${2:?}"; shift 2 ;;
|
||||
--allow-identity-change) allow_identity=1; shift ;;
|
||||
--apply) apply=1; shift ;;
|
||||
-h|--help) sed -n '3,25p' "$0"; exit 0 ;;
|
||||
*) printf 'unknown option: %s\n' "$1" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Interactive when nothing was passed and there is a terminal to ask at. Every
|
||||
# prompt offers the current value; Enter keeps it, so a run that answers nothing
|
||||
# is a no-op rather than a surprise. Optional fields additionally accept "-" to
|
||||
# clear them.
|
||||
ask() { # ask VARNAME PROMPT CURRENT
|
||||
printf ' %s [%s]: ' "$2" "$3" > /dev/tty
|
||||
IFS= read -r _reply < /dev/tty || _reply=""
|
||||
[ -n "$_reply" ] || _reply="$3"
|
||||
[ "$_reply" = "-" ] && _reply=""
|
||||
eval "$1=\$_reply"
|
||||
}
|
||||
if [ -z "$new_display" ] && [ -t 0 ] && [ -c /dev/tty ]; then
|
||||
printf 'branding this plugin - Enter keeps the current value, "-" clears an optional one\n\n'
|
||||
ask new_display "display name " "$OLD_DISPLAY"
|
||||
ask new_vendor "vendor (org) " "$OLD_VENDOR"
|
||||
ask new_author "cargo author " "$OLD_AUTHOR"
|
||||
ask new_email "email " "$OLD_EMAIL"
|
||||
ask new_homepage "homepage " "$OLD_HOMEPAGE"
|
||||
ask new_description "cargo description" "$OLD_DESCRIPTION"
|
||||
ask new_clap_description "clap description" "$OLD_CLAP_DESCRIPTION"
|
||||
printf '\n'
|
||||
fi
|
||||
[ -n "$new_display" ] || { printf 'nothing to do: pass --display "New Name" (or run interactively)\n' >&2; exit 2; }
|
||||
|
||||
# --- derivation -------------------------------------------------------------
|
||||
# Package name: lowercase, every run of non-alphanumerics becomes one separator,
|
||||
# ends trimmed. Cargo accepts both hyphens and underscores in a package name and
|
||||
# converts to underscores for the built artifact, which nih_plug_xtask already
|
||||
# accounts for; underscores are used here to match the Rust convention.
|
||||
derive_pkg() {
|
||||
printf '%s' "$1" | tr '[:upper:]' '[:lower:]' \
|
||||
| sed -e 's/[^a-z0-9]\{1,\}/_/g' -e 's/^_//' -e 's/_$//'
|
||||
}
|
||||
# Rust type name: CamelCase, non-alphanumerics dropped entirely.
|
||||
derive_struct() {
|
||||
printf '%s' "$1" | sed -e 's/[^A-Za-z0-9]\{1,\}/ /g' \
|
||||
| awk '{for(i=1;i<=NF;i++) printf "%s%s", toupper(substr($i,1,1)), substr($i,2); print ""}'
|
||||
}
|
||||
[ -n "$new_pkg" ] || new_pkg=$(derive_pkg "$new_display")
|
||||
[ -n "$new_struct" ] || new_struct=$(derive_struct "$new_display")
|
||||
new_params_struct="${new_struct}Params"
|
||||
[ -n "$new_vendor" ] || new_vendor="$OLD_VENDOR"
|
||||
[ -n "$new_author" ] || new_author="$OLD_AUTHOR"
|
||||
[ -n "$new_email" ] || new_email="$OLD_EMAIL"
|
||||
[ -n "$new_homepage" ] || new_homepage="$OLD_HOMEPAGE"
|
||||
[ -n "$new_description" ] || new_description="$OLD_DESCRIPTION"
|
||||
[ -n "$new_clap_description" ] || new_clap_description="$OLD_CLAP_DESCRIPTION"
|
||||
|
||||
# --- validation -------------------------------------------------------------
|
||||
fail=0
|
||||
die() { printf ' INVALID %s\n' "$1"; fail=$((fail+1)); }
|
||||
|
||||
case "$new_pkg" in
|
||||
"") die "derived package name is empty" ;;
|
||||
[0-9]*) die "package name \"$new_pkg\" starts with a digit - cargo rejects this outright" ;;
|
||||
esac
|
||||
case "$new_pkg" in
|
||||
test|core|std|alloc|proc_macro)
|
||||
die "package name \"$new_pkg\" collides with a built-in crate" ;;
|
||||
as|break|const|continue|crate|dyn|else|enum|extern|false|fn|for|if|impl|in|let|loop|match|mod|move|mut|pub|ref|return|self|static|struct|super|trait|true|type|unsafe|use|where|while|async|await|box|do|final|macro|override|priv|typeof|unsized|virtual|yield|try)
|
||||
die "package name \"$new_pkg\" is a Rust keyword - cargo rejects this" ;;
|
||||
esac
|
||||
# bundler.toml uses the package name as a TOML bare key.
|
||||
case "$new_pkg" in *[!a-zA-Z0-9_-]*) die "package name \"$new_pkg\" is not a valid TOML bare key" ;; esac
|
||||
case "$new_struct" in ""|[0-9]*) die "derived type name \"$new_struct\" is not a valid Rust identifier" ;; esac
|
||||
|
||||
# --- frozen identity --------------------------------------------------------
|
||||
identity_note=""
|
||||
if [ -n "$new_clap_id" ] || [ -n "$new_vst3" ]; then
|
||||
if [ "$allow_identity" -eq 0 ]; then
|
||||
die "CLAP_ID / VST3_CLASS_ID are frozen identity; pass --allow-identity-change to move them"
|
||||
fi
|
||||
fi
|
||||
[ -n "$new_clap_id" ] || new_clap_id="$OLD_CLAP_ID"
|
||||
[ -n "$new_vst3" ] || new_vst3="$OLD_VST3"
|
||||
|
||||
# VST3_CLASS_ID is a fixed 16-byte array, so it cannot simply be derived. Propose
|
||||
# one from the new name and let a human decide - it is frozen the moment it ships.
|
||||
proposed_vst3=$(printf '%s' "${new_struct}Plugin000000000000" | cut -c1-16)
|
||||
n=$(printf '%s' "$new_vst3" | wc -c | tr -d ' ')
|
||||
[ "$n" -eq 16 ] || die "VST3_CLASS_ID \"$new_vst3\" is $n bytes, must be exactly 16"
|
||||
|
||||
case "$new_clap_id" in
|
||||
*\ *|*[A-Z]*) die "CLAP_ID \"$new_clap_id\" must be lowercase with no spaces" ;;
|
||||
*.*) ;;
|
||||
*) die "CLAP_ID \"$new_clap_id\" should be dotted reverse-DNS" ;;
|
||||
esac
|
||||
|
||||
# CLAP_DESCRIPTION is user-facing: keep development history out of it.
|
||||
for hist in "$CODENAME" "$OLD_DISPLAY" "$OLD_PKG"; do
|
||||
case "$new_clap_description" in
|
||||
*"$hist"*) die "CLAP_DESCRIPTION still mentions \"$hist\" - it is shown to users, who never knew the development name" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- plan -------------------------------------------------------------------
|
||||
printf 'rename plan\n\n'
|
||||
row() { [ "$2" = "$3" ] && printf ' %-18s %s (unchanged)\n' "$1" "$2" || printf ' %-18s %s -> %s\n' "$1" "$2" "$3"; }
|
||||
row "package" "$OLD_PKG" "$new_pkg"
|
||||
row "display" "$OLD_DISPLAY" "$new_display"
|
||||
row "Plugin::NAME" "$OLD_PLUGIN_NAME" "$new_display"
|
||||
row "vendor" "$OLD_VENDOR" "$new_vendor"
|
||||
row "cargo author" "$OLD_AUTHOR" "$new_author"
|
||||
row "email" "$OLD_EMAIL" "$new_email"
|
||||
row "homepage" "$OLD_HOMEPAGE" "$new_homepage"
|
||||
row "description" "$OLD_DESCRIPTION" "$new_description"
|
||||
row "clap desc" "$OLD_CLAP_DESCRIPTION" "$new_clap_description"
|
||||
row "struct" "$OLD_STRUCT" "$new_struct"
|
||||
row "params struct" "$OLD_PARAMS_STRUCT" "$new_params_struct"
|
||||
row "CLAP_ID" "$OLD_CLAP_ID" "$new_clap_id"
|
||||
row "VST3_CLASS_ID" "$OLD_VST3" "$new_vst3"
|
||||
printf '\n repo codename stays %s - fixed at creation, never renamed\n' "$CODENAME"
|
||||
if [ "$new_vst3" = "$OLD_VST3" ]; then
|
||||
printf ' suggested VST3_CLASS_ID for this name (16 bytes): "%s"\n' "$proposed_vst3"
|
||||
printf ' apply with --vst3-class-id "%s" --allow-identity-change, and only before first release\n' "$proposed_vst3"
|
||||
fi
|
||||
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
printf '\n%d problem(s); nothing written.\n' "$fail"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$apply" -eq 0 ]; then
|
||||
printf '\nDry run. Re-run with --apply to write these changes.\n'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- apply ------------------------------------------------------------------
|
||||
# Three scratch files, one trap: the regenerated site table, the rows carried
|
||||
# through from the old one, and the value-substitution pairs.
|
||||
gen="$(mktemp)"; keep="$(mktemp)"; subst_file="$(mktemp)"
|
||||
trap 'rm -f "$gen" "$keep" "$subst_file"' EXIT
|
||||
|
||||
T="$(printf '\t')"
|
||||
{
|
||||
printf 'req%spkg.cargo%sCargo.toml%sname = "%s"\n' "$T" "$T" "$T" "$new_pkg"
|
||||
printf 'req%spkg.bundler%sbundler.toml%s[%s]\n' "$T" "$T" "$T" "$new_pkg"
|
||||
printf 'opt%spkg.lock%sCargo.lock%sname = "%s"\n' "$T" "$T" "$T" "$new_pkg"
|
||||
printf 'opt%spkg.ci%s.github/workflows/ci.yaml%scargo xtask bundle %s\n' "$T" "$T" "$T" "$new_pkg"
|
||||
printf 'opt%spkg.readme%sREADME.md%scargo xtask bundle %s\n' "$T" "$T" "$T" "$new_pkg"
|
||||
printf 'req%sdisplay.bundler%sbundler.toml%sname = "%s"\n' "$T" "$T" "$T" "$new_display"
|
||||
printf 'opt%sdisplay.notice%sNOTICE%s%s\n' "$T" "$T" "$T" "$new_display"
|
||||
printf 'req%sname.plugin%s%s%sconst NAME: &'"'"'static str = "%s"\n' "$T" "$T" "$LIB_FILE" "$T" "$new_display"
|
||||
printf 'req%svendor.plugin%s%s%sconst VENDOR: &'"'"'static str = "%s"\n' "$T" "$T" "$LIB_FILE" "$T" "$new_vendor"
|
||||
printf 'req%semail.plugin%s%s%sconst EMAIL: &'"'"'static str = "%s"\n' "$T" "$T" "$LIB_FILE" "$T" "$new_email"
|
||||
printf 'req%sauthors.cargo%sCargo.toml%sauthors = ["%s <%s>"]\n' "$T" "$T" "$T" "$new_author" "$new_email"
|
||||
printf 'req%shomepage.cargo%sCargo.toml%shomepage = "%s"\n' "$T" "$T" "$T" "$new_homepage"
|
||||
printf 'req%surl.plugin%s%s%sconst URL: &'"'"'static str = env!("CARGO_PKG_HOMEPAGE")\n' "$T" "$T" "$LIB_FILE" "$T"
|
||||
printf 'req%sdescription.cargo%sCargo.toml%sdescription = "%s"\n' "$T" "$T" "$T" "$new_description"
|
||||
# Narrowest distinctive fragment, not the whole statement: rustfmt wraps a long
|
||||
# CLAP_DESCRIPTION onto its own line, and a pattern spanning the assignment
|
||||
# would then never match a correctly formatted file.
|
||||
printf 'req%sdescription.clap%s%s%sSome("%s")\n' "$T" "$T" "$LIB_FILE" "$T" "$new_clap_description"
|
||||
printf 'req%sclapid.plugin%s%s%sconst CLAP_ID: &'"'"'static str = "%s"\n' "$T" "$T" "$LIB_FILE" "$T" "$new_clap_id"
|
||||
printf 'req%svst3id.plugin%s%s%sconst VST3_CLASS_ID: [u8; 16] = *b"%s"\n' "$T" "$T" "$LIB_FILE" "$T" "$new_vst3"
|
||||
printf 'req%sstruct.def%s%s%sstruct %s {\n' "$T" "$T" "$LIB_FILE" "$T" "$new_struct"
|
||||
printf 'req%sstruct.plugin%s%s%simpl Plugin for %s {\n' "$T" "$T" "$LIB_FILE" "$T" "$new_struct"
|
||||
printf 'req%sstruct.clap%s%s%simpl ClapPlugin for %s {\n' "$T" "$T" "$LIB_FILE" "$T" "$new_struct"
|
||||
printf 'req%sstruct.vst3%s%s%simpl Vst3Plugin for %s {\n' "$T" "$T" "$LIB_FILE" "$T" "$new_struct"
|
||||
printf 'req%sstruct.exportclap%s%s%snih_export_clap!(%s);\n' "$T" "$T" "$LIB_FILE" "$T" "$new_struct"
|
||||
printf 'req%sstruct.exportvst3%s%s%snih_export_vst3!(%s);\n' "$T" "$T" "$LIB_FILE" "$T" "$new_struct"
|
||||
printf 'req%sparams.def%s%s%sstruct %s {\n' "$T" "$T" "$PARAMS_FILE" "$T" "$new_params_struct"
|
||||
printf 'req%sparams.default%s%s%simpl Default for %s {\n' "$T" "$T" "$PARAMS_FILE" "$T" "$new_params_struct"
|
||||
printf 'req%sparams.field%s%s%sparams: Arc<%s>,\n' "$T" "$T" "$LIB_FILE" "$T" "$new_params_struct"
|
||||
printf 'opt%sdeploy.pkg%sdeploy.ps1%s$Package = "%s"\n' "$T" "$T" "$T" "$new_pkg"
|
||||
printf 'opt%sdeploy.vst3%sdeploy.ps1%s$vst3Name = "%s.vst3"\n' "$T" "$T" "$T" "$new_display"
|
||||
printf 'opt%sdeploy.clap%sdeploy.ps1%s$clapName = "%s.clap"\n' "$T" "$T" "$T" "$new_display"
|
||||
} > "$gen"
|
||||
|
||||
# Pass 1 - site-directed. Each owned row in the existing table carries the OLD
|
||||
# resolved literal for its site; the regenerated row carries the new one. Rewriting
|
||||
# by that pair is unambiguous, which plain value substitution is not: AUTHOR
|
||||
# defaults to VENDOR, so both fields can hold the same old string and a global
|
||||
# replace cannot tell which occurrence belongs to which. This must run BEFORE
|
||||
# pass 2, or the global replace consumes the old literals first and leaves the
|
||||
# precise rewrite with nothing to match.
|
||||
sites="tools/branding-sites.tsv"
|
||||
T="$(printf '\t')"
|
||||
if [ -f "$sites" ]; then
|
||||
while IFS="$T" read -r ok_ oo_ of_ op_; do
|
||||
case "$ok_" in ''|\#*) continue ;; esac
|
||||
np_=$(awk -F"$T" -v o="$oo_" '$2==o {print $4; exit}' "$gen")
|
||||
[ -n "$np_" ] || continue
|
||||
[ "$np_" != "$op_" ] || continue
|
||||
[ -f "$of_" ] || continue
|
||||
esc_o=$(printf '%s' "$op_" | sed 's/[][\.*^$/|&]/\\&/g')
|
||||
esc_n=$(printf '%s' "$np_" | sed 's/[\\/&|]/\\&/g')
|
||||
tmp_=$(mktemp)
|
||||
sed "s|$esc_o|$esc_n|g" "$of_" > "$tmp_" && cat "$tmp_" > "$of_"
|
||||
rm -f "$tmp_"
|
||||
done < "$sites"
|
||||
printf ' pass 1: rewrote known sites from the table\n'
|
||||
fi
|
||||
|
||||
# Pass 2 - value substitution, for everything the table does not enumerate:
|
||||
# doc comments, use sites in other modules, prose in the README.
|
||||
# Longest values first: a shorter spelling can be a substring of a longer one
|
||||
# (the package name inside a URL, say), and replacing it first would corrupt the
|
||||
# longer match. branding.conf is excluded and rewritten wholesale below, so its
|
||||
# STALE list is never rewritten into meaninglessness.
|
||||
{
|
||||
printf '%s\t%s\n' "$OLD_CLAP_ID" "$new_clap_id"
|
||||
printf '%s\t%s\n' "$OLD_HOMEPAGE" "$new_homepage"
|
||||
printf '%s\t%s\n' "$OLD_CLAP_DESCRIPTION" "$new_clap_description"
|
||||
printf '%s\t%s\n' "$OLD_DESCRIPTION" "$new_description"
|
||||
printf '%s\t%s\n' "$OLD_PARAMS_STRUCT" "$new_params_struct"
|
||||
printf '%s\t%s\n' "$OLD_VST3" "$new_vst3"
|
||||
printf '%s\t%s\n' "$OLD_PLUGIN_NAME" "$new_display"
|
||||
printf '%s\t%s\n' "$OLD_DISPLAY" "$new_display"
|
||||
printf '%s\t%s\n' "$OLD_STRUCT" "$new_struct"
|
||||
printf '%s\t%s\n' "$OLD_EMAIL" "$new_email"
|
||||
printf '%s\t%s\n' "$OLD_AUTHOR" "$new_author"
|
||||
printf '%s\t%s\n' "$OLD_VENDOR" "$new_vendor"
|
||||
printf '%s\t%s\n' "$OLD_PKG" "$new_pkg"
|
||||
} | awk -F'\t' '$1 != $2 { print length($1)"\t"$0 }' | sort -rn | cut -f2- > "$subst_file"
|
||||
|
||||
changed=0
|
||||
git ls-files 2>/dev/null | while IFS= read -r f; do
|
||||
[ -f "$f" ] || continue
|
||||
# branding.conf alone is excluded: it is rewritten wholesale below, and its
|
||||
# STALE list names every retired spelling by design. The site table IS
|
||||
# substituted, so hand-added custom rows track the rename; owned rows are
|
||||
# regenerated afterwards regardless.
|
||||
case "$f" in tools/branding.conf) continue ;; esac
|
||||
before=$(cat "$f")
|
||||
after="$before"
|
||||
while IFS="$(printf '\t')" read -r old new; do
|
||||
[ -n "$old" ] || continue
|
||||
after=$(printf '%s' "$after" | sed "s|$(printf '%s' "$old" | sed 's/[][\.*^$/|&]/\\&/g')|$(printf '%s' "$new" | sed 's/[\\/&|]/\\&/g')|g")
|
||||
done < "$subst_file"
|
||||
if [ "$before" != "$after" ]; then printf '%s\n' "$after" > "$f"; printf ' rewrote %s\n' "$f"; fi
|
||||
done
|
||||
|
||||
# branding.conf last, with the retired spellings appended to STALE so the next
|
||||
# run of the checker sweeps for anything this pass missed.
|
||||
# Deduplicated: two fields can retire to the same spelling - DISPLAY and
|
||||
# PLUGIN_NAME are commonly identical - and listing it twice makes the checker
|
||||
# report the same drift twice. Note that neither this script nor the checker
|
||||
# contains a branding literal anywhere: both read every name from
|
||||
# branding.conf, so a rename never has to rewrite its own tooling.
|
||||
retired=$(cut -f1 "$subst_file" | awk '!seen[$0]++')
|
||||
sed -e "s|^PKG=.*|PKG=\"$new_pkg\"|" \
|
||||
-e "s|^DISPLAY=.*|DISPLAY=\"$new_display\"|" \
|
||||
-e "s|^PLUGIN_NAME=.*|PLUGIN_NAME=\"$new_display\"|" \
|
||||
-e "s|^VENDOR=.*|VENDOR=\"$new_vendor\"|" \
|
||||
-e "s|^# *AUTHOR=.*|AUTHOR=\"$new_author\"|" \
|
||||
-e "s|^AUTHOR=.*|AUTHOR=\"$new_author\"|" \
|
||||
-e "s|^EMAIL=.*|EMAIL=\"$new_email\"|" \
|
||||
-e "s|^HOMEPAGE=.*|HOMEPAGE=\"$new_homepage\"|" \
|
||||
-e "s|^DESCRIPTION=.*|DESCRIPTION=\"$new_description\"|" \
|
||||
-e "s|^CLAP_DESCRIPTION=.*|CLAP_DESCRIPTION=\"$new_clap_description\"|" \
|
||||
-e "s|^CLAP_ID=.*|CLAP_ID=\"$new_clap_id\"|" \
|
||||
-e "s|^VST3_CLASS_ID=.*|VST3_CLASS_ID=\"$new_vst3\"|" \
|
||||
-e "s|^STRUCT=.*|STRUCT=\"$new_struct\"|" \
|
||||
-e "s|^PARAMS_STRUCT=.*|PARAMS_STRUCT=\"$new_params_struct\"|" \
|
||||
tools/branding.conf > tools/branding.conf.new
|
||||
if [ -n "$retired" ]; then
|
||||
{ sed '$ s/"$//' tools/branding.conf.new; printf '%s"\n' "$retired"; } > tools/branding.conf
|
||||
else
|
||||
# Nothing retired (a no-op rename, or a regeneration): leave STALE untouched
|
||||
# rather than appending a blank line to it on every run.
|
||||
cat tools/branding.conf.new > tools/branding.conf
|
||||
fi
|
||||
rm -f tools/branding.conf.new
|
||||
if [ "$new_author" = "$new_vendor" ]; then
|
||||
# Identical to VENDOR, so re-comment it: the conf should keep showing that this
|
||||
# value derives rather than pinning a duplicate that then has to be maintained.
|
||||
tmp_c=$(mktemp)
|
||||
sed "s|^AUTHOR=.*|# AUTHOR=\"$new_author\"|" tools/branding.conf > "$tmp_c" && cat "$tmp_c" > tools/branding.conf
|
||||
rm -f "$tmp_c"
|
||||
fi
|
||||
printf ' rewrote tools/branding.conf (retired spellings appended to STALE)\n'
|
||||
|
||||
# Regenerate the site table. Rows whose owner this script recognises are
|
||||
# rewritten with the new resolved literals; every other row - anything marked
|
||||
# custom, or added by hand for a file this template does not ship - is carried
|
||||
# through untouched. Clobbering those silently is how a tool stops being trusted.
|
||||
sites="tools/branding-sites.tsv"
|
||||
|
||||
owned=$(cut -f2 "$gen")
|
||||
if [ -f "$sites" ]; then
|
||||
grep '^#' "$sites" > "$keep" 2>/dev/null || : > "$keep"
|
||||
while IFS="$T" read -r k o f pat; do
|
||||
case "$k" in ''|\#*) continue ;; esac
|
||||
printf '%s\n' "$owned" | grep -qxF "$o" || printf '%s%s%s%s%s%s%s\n' "$k" "$T" "$o" "$T" "$f" "$T" "$pat" >> "$keep"
|
||||
done < "$sites"
|
||||
else
|
||||
: > "$keep"
|
||||
fi
|
||||
{ cat "$keep"; cat "$gen"; } > "$sites"
|
||||
printf ' rewrote %s (%s owned rows, %s preserved)\n' "$sites" "$(wc -l < "$gen" | tr -d ' ')" "$(grep -cv '^#' "$keep" 2>/dev/null || echo 0)"
|
||||
|
||||
printf '\nverifying with check-branding.sh\n\n'
|
||||
sh tools/check-branding.sh
|
||||
@@ -0,0 +1,45 @@
|
||||
# branding-sites.tsv - every place a canonical name has to appear, and in what form.
|
||||
#
|
||||
# Generated and refreshed by tools/brand-plugin.sh; read by tools/check-branding.sh,
|
||||
# which asserts each pattern is present in its file. Tab-separated, four columns:
|
||||
#
|
||||
# kind req = a missing file is a failure; opt = a missing file is a skip
|
||||
# owner the brand-plugin.sh rule that manages this row, or "custom" for rows
|
||||
# you added by hand. Custom rows are preserved across regeneration;
|
||||
# owned rows are overwritten, so do not hand-edit those.
|
||||
# file repo-relative path
|
||||
# pattern literal text that must appear in that file, already resolved
|
||||
#
|
||||
# Adding a site for something the template does not ship is a one-line edit here
|
||||
# with owner "custom" - no shell to change, and it survives the next rename.
|
||||
#
|
||||
#kind owner file pattern
|
||||
req pkg.cargo Cargo.toml name = "plugin_name"
|
||||
req pkg.bundler bundler.toml [plugin_name]
|
||||
opt pkg.lock Cargo.lock name = "plugin_name"
|
||||
opt pkg.ci .github/workflows/ci.yaml cargo xtask bundle plugin_name
|
||||
opt pkg.readme README.md cargo xtask bundle plugin_name
|
||||
req display.bundler bundler.toml name = "Plugin Name"
|
||||
opt display.notice NOTICE Plugin Name
|
||||
req name.plugin src/lib.rs const NAME: &'static str = "Plugin Name"
|
||||
req vendor.plugin src/lib.rs const VENDOR: &'static str = "Your Name"
|
||||
req email.plugin src/lib.rs const EMAIL: &'static str = "your@email.com"
|
||||
req authors.cargo Cargo.toml authors = ["Your Name <your@email.com>"]
|
||||
req homepage.cargo Cargo.toml homepage = "https://wiki.novoyuuparosk.org"
|
||||
req url.plugin src/lib.rs const URL: &'static str = env!("CARGO_PKG_HOMEPAGE")
|
||||
req description.cargo Cargo.toml description = "A minimal NIH-plug audio plugin"
|
||||
req description.clap src/lib.rs Some("Your plugin description")
|
||||
req clapid.plugin src/lib.rs const CLAP_ID: &'static str = "com.your-domain.plugin-name"
|
||||
req vst3id.plugin src/lib.rs const VST3_CLASS_ID: [u8; 16] = *b"Unique16CharId!!"
|
||||
req struct.def src/lib.rs struct PluginName {
|
||||
req struct.plugin src/lib.rs impl Plugin for PluginName {
|
||||
req struct.clap src/lib.rs impl ClapPlugin for PluginName {
|
||||
req struct.vst3 src/lib.rs impl Vst3Plugin for PluginName {
|
||||
req struct.exportclap src/lib.rs nih_export_clap!(PluginName);
|
||||
req struct.exportvst3 src/lib.rs nih_export_vst3!(PluginName);
|
||||
req params.def src/lib.rs struct PluginNameParams {
|
||||
req params.default src/lib.rs impl Default for PluginNameParams {
|
||||
req params.field src/lib.rs params: Arc<PluginNameParams>,
|
||||
opt deploy.pkg deploy.ps1 $Package = "plugin_name"
|
||||
opt deploy.vst3 deploy.ps1 $vst3Name = "Plugin Name.vst3"
|
||||
opt deploy.clap deploy.ps1 $clapName = "Plugin Name.clap"
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 64.
|
@@ -0,0 +1,99 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# branding.conf - this plugin's canonical identity.
|
||||
#
|
||||
# Managed by tools/brand-plugin.sh, read by tools/check-branding.sh. Hand-editing
|
||||
# works and is sometimes the quickest thing, but the helper is what keeps this
|
||||
# file, the source tree and tools/branding-sites.tsv agreeing with each other.
|
||||
# Edit here and you are on the hook for running the checker afterwards.
|
||||
|
||||
# --- derivations ------------------------------------------------------------
|
||||
# Defined before the values so the defaults below can use them.
|
||||
# Package name: lowercased, every run of non-alphanumerics becomes one
|
||||
# underscore. Cargo accepts hyphens too and maps them to underscores for the
|
||||
# built artifact, which nih_plug_xtask already handles; underscores are used to
|
||||
# match the Rust convention.
|
||||
_derive_pkg() {
|
||||
printf '%s' "$1" | tr '[:upper:]' '[:lower:]' \
|
||||
| sed -e 's/[^a-z0-9]\{1,\}/_/g' -e 's/^_//' -e 's/_$//'
|
||||
}
|
||||
# Rust type name: CamelCase, non-alphanumerics dropped.
|
||||
_derive_struct() {
|
||||
printf '%s' "$1" | sed -e 's/[^A-Za-z0-9]\{1,\}/ /g' \
|
||||
| awk '{for(i=1;i<=NF;i++) printf "%s%s", toupper(substr($i,1,1)), substr($i,2); print ""}'
|
||||
}
|
||||
|
||||
# --- the names ---------------------------------------------------------------
|
||||
PLUGIN_NAME="Plugin Name"
|
||||
VENDOR="Your Name"
|
||||
EMAIL="your@email.com"
|
||||
# Cargo's authors entry names whoever wrote it, which is not always the vendor:
|
||||
# an org ships the plugin, a person authored it. Defaults to VENDOR when the two
|
||||
# are the same, which is the common case for a one-person project.
|
||||
# AUTHOR="Your Name"
|
||||
HOMEPAGE="https://wiki.novoyuuparosk.org"
|
||||
DESCRIPTION="A minimal NIH-plug audio plugin"
|
||||
|
||||
# What the plugin does *now*. No codename, no "prototype", no "v2 rewrite" -
|
||||
# hosts show this to users who never knew any of that. check-branding.sh
|
||||
# enforces the mechanical half by rejecting retired names and the repo codename.
|
||||
CLAP_DESCRIPTION="Your plugin description"
|
||||
|
||||
# --- frozen identity ---------------------------------------------------------
|
||||
# Hosts key saved projects and presets off these two. Change either and every
|
||||
# existing session silently loses the plugin: the track comes up empty, with no
|
||||
# error. Choose once before the first release, then never again.
|
||||
# brand-plugin.sh refuses to move them without --allow-identity-change.
|
||||
CLAP_ID="com.your-domain.plugin-name"
|
||||
VST3_CLASS_ID="Unique16CharId!!"
|
||||
|
||||
# --- fixed at repo creation --------------------------------------------------
|
||||
# The repository's own name. Deliberately NOT renamed when the plugin is: the
|
||||
# repo keeps its development codename while the plugin gets a product name.
|
||||
# Recorded only so it can be kept out of user-facing text.
|
||||
CODENAME="nih-plug-template"
|
||||
|
||||
# Where the two Rust types are defined. A plugin whose params outgrow lib.rs
|
||||
# points PARAMS_FILE at src/params.rs.
|
||||
LIB_FILE="src/lib.rs"
|
||||
PARAMS_FILE="src/lib.rs"
|
||||
|
||||
# --- derived unless overridden -----------------------------------------------
|
||||
# Set one only when the derivation is wrong or rejected - a name like
|
||||
# "206 Prototype" derives to "206_prototype", which cargo refuses because a
|
||||
# package name cannot start with a digit.
|
||||
#
|
||||
# This template overrides three of them, which a real plugin usually will not:
|
||||
# its package and type names are the template's own rather than derived from a
|
||||
# product name. Delete these three lines after renaming and the derivations
|
||||
# from PLUGIN_NAME take over.
|
||||
PKG="plugin_name"
|
||||
STRUCT="PluginName"
|
||||
PARAMS_STRUCT="PluginNameParams"
|
||||
# DISPLAY="Plugin Name" # defaults to PLUGIN_NAME
|
||||
: "${AUTHOR:=$VENDOR}"
|
||||
: "${DISPLAY:=$PLUGIN_NAME}"
|
||||
: "${PKG:=$(_derive_pkg "$PLUGIN_NAME")}"
|
||||
: "${STRUCT:=$(_derive_struct "$PLUGIN_NAME")}"
|
||||
: "${PARAMS_STRUCT:=${STRUCT}Params}"
|
||||
|
||||
# --- retired spellings -------------------------------------------------------
|
||||
# Must no longer appear in tracked files. An entry is skipped while it is still
|
||||
# part of a canonical value above and arms the moment it stops being one, so a
|
||||
# rename is self-checking in both directions. brand-plugin.sh appends here.
|
||||
STALE="nih_plug_template
|
||||
MyPlugin
|
||||
PluginParams
|
||||
A minimal NIH-plug audio plugin
|
||||
Your plugin description
|
||||
Plugin Name
|
||||
Your Name
|
||||
your@email.com
|
||||
com.your-domain.plugin-name
|
||||
Unique16CharId!!
|
||||
YOUR-USERNAME
|
||||
YOUR-PLUGIN-NAME
|
||||
your-domain
|
||||
https://github.com/YOUR-USERNAME/YOUR-PLUGIN-NAME
|
||||
nih_plug_template
|
||||
PluginParams
|
||||
MyPlugin"
|
||||
Executable
+188
@@ -0,0 +1,188 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user