#!/bin/bash # # rebrand: 把面向用户的品牌标识从 GPUStack 批量替换为 MesaStack(或自定义品牌)。 # # 设计目标:上游每次更新后,在新的 v-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 正则。 # (? '${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' 复核改动。"