feat(scripts): add rebrand script to swap brand identity
Replace the standalone "GPUStack" brand word with a target brand (default MesaStack) across user-facing text. Word-boundary + case- sensitive matching deliberately skips functional references: lowercase gpustack (npm pkg/URLs/paths/k8s ns), ALL-CAPS GPUSTACK_ constants, JS identifiers (getGPUStackPlugin etc.), and X-* HTTP headers. A line-level skip list protects backend-contract strings matched at runtime (e.g. the model-file-not-found startsWith check). Re-run on each new v<version>-lofyer branch after syncing upstream. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
4da7a19520
commit
4b790bcfe4
Executable
+102
@@ -0,0 +1,102 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# rebrand: 把面向用户的品牌标识从 GPUStack 批量替换为 MesaStack(或自定义品牌)。
|
||||
#
|
||||
# 设计目标:上游每次更新后,在新的 v<version>-lofyer 分支上跑一次即可重新应用品牌定制。
|
||||
#
|
||||
# 只替换「独立的品牌词」FROM,并刻意跳过所有功能性引用:
|
||||
# - 小写 `gpustack` —— npm 包名 (@gpustack/core-ui)、URL、路径、k8s 命名空间、author(大小写敏感,天然不匹配)
|
||||
# - 全大写 `GPUSTACK` —— 常量/环境变量/全局 (GPUSTACK_API_BASE_URL, __GPUSTACK_*__, GPUSTACK_UI_*)(大小写敏感,不匹配)
|
||||
# - 代码标识符 —— getGPUStackPlugin / GPUStackVersionAtom / GPUStackPluginManager / GPUStackLogo 等
|
||||
# (FROM 紧邻字母时视为标识符的一部分,跳过)
|
||||
# - HTTP 头 X-GPUStack-* —— 后端契约 (如 X-GPUStack-Model),跳过
|
||||
#
|
||||
# 匹配规则:FROM 前后都不是字母(独立单词),且不是 `X-` 前缀的头名。
|
||||
#
|
||||
# 环境变量:
|
||||
# FROM 源品牌词(默认 GPUStack)
|
||||
# TO 目标品牌词(默认 MesaStack)
|
||||
# DRY_RUN 设为 1 时只预览将改动的行,不写文件
|
||||
#
|
||||
set -e
|
||||
|
||||
FROM="${FROM:-GPUStack}"
|
||||
TO="${TO:-MesaStack}"
|
||||
DRY_RUN="${DRY_RUN:-0}"
|
||||
|
||||
log() { echo -e "\033[1;34m[rebrand]\033[0m $*"; }
|
||||
|
||||
# 大小写敏感、单词边界、排除 X- 头前缀的 Perl 正则。
|
||||
# (?<![A-Za-z]) 前面不是字母 (?<!X-) 不是 X- 头 (?![A-Za-z]) 后面不是字母
|
||||
# FROM 为纯字母品牌词(无正则元字符),故直接拼接,不用 \Q\E
|
||||
# —— \Q\E 在「经变量插值进正则」时不会被求值,反而会破坏匹配。
|
||||
PATTERN="(?<![A-Za-z])(?<!X-)${FROM}(?![A-Za-z])"
|
||||
|
||||
# 行级排除:某些 FROM 出现在「与后端契约绑定的字符串」里,改了会破坏运行时逻辑,
|
||||
# 即使是独立单词也必须整行跳过。命中下列任一正则的行不替换。
|
||||
# 已知例外:
|
||||
# - llmodels/hooks/index.ts 用 startsWith() 比对后端返回的英文兼容性消息
|
||||
# ("... does not exist on the GPUStack server ..."),后端仍发 GPUStack,前端不能改。
|
||||
SKIP_LINE_PATTERNS=(
|
||||
'does not exist on the .*server. It'"'"'s recommended'
|
||||
)
|
||||
skip_line() {
|
||||
local line="$1" pat
|
||||
for pat in "${SKIP_LINE_PATTERNS[@]}"; do
|
||||
if echo "$line" | grep -qP "$pat"; then return 0; fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# 待处理的已跟踪文本文件(排除 lockfile 与本脚本自身)。
|
||||
mapfile -t files < <(
|
||||
git ls-files -- \
|
||||
'*.ts' '*.tsx' '*.js' '*.jsx' '*.json' '*.less' '*.html' '*.md' \
|
||||
| grep -v 'pnpm-lock.yaml'
|
||||
)
|
||||
|
||||
log "品牌替换: '${FROM}' -> '${TO}'"
|
||||
log "候选文件: ${#files[@]}"
|
||||
|
||||
# 把行级排除合并成一个 perl 正则,供预览与替换共用(经环境变量传入,免去转义)。
|
||||
SKIP_RE=""
|
||||
for pat in "${SKIP_LINE_PATTERNS[@]}"; do
|
||||
SKIP_RE="${SKIP_RE:+${SKIP_RE}|}(?:${pat})"
|
||||
done
|
||||
export REBRAND_SKIP_RE="${SKIP_RE}"
|
||||
export REBRAND_PATTERN="${PATTERN}"
|
||||
export REBRAND_TO="${TO}"
|
||||
|
||||
# 统计命中行(预览/确认用),已扣除被行级排除的行。
|
||||
log "命中行预览(最多 40 行):"
|
||||
grep -rnP "${PATTERN}" "${files[@]}" 2>/dev/null \
|
||||
| { [[ -n "${SKIP_RE}" ]] && grep -vP "${SKIP_RE}" || cat; } \
|
||||
| head -40 || true
|
||||
total=$(grep -rnP "${PATTERN}" "${files[@]}" 2>/dev/null \
|
||||
| { [[ -n "${SKIP_RE}" ]] && grep -vP "${SKIP_RE}" || cat; } | wc -l)
|
||||
log "命中总行数: ${total}"
|
||||
if [[ -n "${SKIP_RE}" ]]; then
|
||||
skipped=$(grep -rnP "${PATTERN}" "${files[@]}" 2>/dev/null | grep -cP "${SKIP_RE}" || true)
|
||||
log "行级排除(后端契约,保留 ${FROM}): ${skipped} 行"
|
||||
fi
|
||||
|
||||
if [[ "${DRY_RUN}" == "1" ]]; then
|
||||
log "DRY_RUN=1:未写入任何文件。"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 实际替换(in-place)。命中行级排除的行整行跳过。
|
||||
changed=0
|
||||
for f in "${files[@]}"; do
|
||||
if grep -qP "${PATTERN}" "$f" 2>/dev/null; then
|
||||
perl -i -pe '
|
||||
my $skip = $ENV{REBRAND_SKIP_RE};
|
||||
next if length($skip) && /$skip/;
|
||||
s/$ENV{REBRAND_PATTERN}/$ENV{REBRAND_TO}/g;
|
||||
' "$f"
|
||||
changed=$((changed + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
log "已修改文件数: ${changed}"
|
||||
log "完成。请用 'git diff' 复核改动。"
|
||||
Reference in New Issue
Block a user