#!/usr/bin/env bash # # check-proto-sync.sh — 检查 .proto 和 .pb.go 的 rawDesc 是否一致 # # 工作原理:从 .proto 文件提取字段数量,从 .pb.go 的 Go struct 提取字段数量, # 如果 struct 的字段比 proto 的字段多(说明手动添加了字段没有重新生成),则报错。 # # 用法: # ./check-proto-sync.sh # 检查所有 proto 文件 # ./check-proto-sync.sh --fix # 如果有 protoc,自动重新生成 set -e ROOT=$(dirname "$0")/.. PROTO_DIR="$ROOT/pkg/rpc/protos" PB_DIR="$ROOT/pkg/rpc/pb" ERRORS=0 echo "Checking proto <-> pb.go sync ..." # 对每个 .proto 文件,检查 message 中的字段数量是否和 .pb.go 一致 for proto_file in "$PROTO_DIR"/*.proto "$PROTO_DIR"/models/*.proto; do [ -f "$proto_file" ] || continue base=$(basename "$proto_file" .proto) pb_file="$PB_DIR/${base}.pb.go" [ -f "$pb_file" ] || continue # 从 .proto 提取每个 message 的字段数(格式: "MessageName:N") # 只计算顶层 message 的直接字段(= N 格式的行) current_msg="" declare -A proto_fields while IFS= read -r line; do # 匹配 message 声明 if [[ "$line" =~ ^[[:space:]]*message[[:space:]]+([A-Za-z0-9_]+) ]]; then current_msg="${BASH_REMATCH[1]}" proto_fields["$current_msg"]=0 fi # 匹配字段声明(type name = N;) if [ -n "$current_msg" ] && [[ "$line" =~ =[[:space:]]*[0-9]+\; ]]; then proto_fields["$current_msg"]=$(( ${proto_fields["$current_msg"]} + 1 )) fi # message 结束 if [ -n "$current_msg" ] && [[ "$line" =~ ^[[:space:]]*\} ]]; then current_msg="" fi done < "$proto_file" # 从 .pb.go 提取每个 struct 的 protobuf 字段数 declare -A pbgo_fields current_struct="" while IFS= read -r line; do if [[ "$line" =~ ^type[[:space:]]+([A-Za-z0-9_]+)[[:space:]]+struct ]]; then current_struct="${BASH_REMATCH[1]}" pbgo_fields["$current_struct"]=0 fi if [ -n "$current_struct" ] && [[ "$line" =~ protobuf:\" ]]; then pbgo_fields["$current_struct"]=$(( ${pbgo_fields["$current_struct"]} + 1 )) fi if [ -n "$current_struct" ] && [[ "$line" =~ ^\} ]]; then current_struct="" fi done < "$pb_file" # 比较 for msg in "${!proto_fields[@]}"; do proto_count=${proto_fields["$msg"]} pbgo_count=${pbgo_fields["$msg"]:-0} if [ "$pbgo_count" -gt "$proto_count" ] 2>/dev/null; then echo " [WARN] $base: struct '$msg' has $pbgo_count fields in .pb.go but only $proto_count in .proto (hand-edited?)" ERRORS=$((ERRORS + 1)) elif [ "$pbgo_count" -lt "$proto_count" ] 2>/dev/null; then echo " [WARN] $base: struct '$msg' has $pbgo_count fields in .pb.go but $proto_count in .proto (needs regeneration)" ERRORS=$((ERRORS + 1)) fi done unset proto_fields unset pbgo_fields declare -A proto_fields declare -A pbgo_fields done if [ "$ERRORS" -gt 0 ]; then echo "" echo "Found $ERRORS proto sync issue(s)." echo "Fix: install protoc and run 'cd EdgeCommon/build && ./build.sh'" if [ "$1" = "--fix" ]; then if command -v protoc &>/dev/null; then echo "Regenerating ..." cd "$(dirname "$0")" ./build.sh echo "Done. Please review and commit the changes." else echo "protoc not found, cannot auto-fix." exit 1 fi else exit 1 fi else echo "All proto files are in sync. OK" fi