- 品牌與顯示:app.json、Info.plist、package scheme、iOS 產物 DearMama.app - 協議與條款:隱私協議/使用條款全文、設計文檔、server legal_docs + legal API、push 預設 title - 多語言:all.json / zh-TW / zh-CN / en / es / pt 的 consent、widget 標題與引導文案 - 小工具:EmotionWidget.swift 品牌文案、Dear Mama.xcscheme - CocoaPods:project.pbxproj objectVersion 70→56 以通過 pod install - Metro:react-native-text-size 用 require + extraNodeModules 解析 - textWrap:measureWidthImpl 改為 require 載入 react-native-text-size Co-authored-by: Cursor <cursoragent@cursor.com>
134 lines
6.9 KiB
Bash
Executable File
134 lines
6.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
# 修复 Xcode Organizer 显示 “Generic Xcode Archive” 的问题:
|
||
# - 某些情况下 xcodebuild 生成的 .xcarchive/Info.plist 缺少 ApplicationProperties
|
||
# - Organizer 无法识别归档中的主 App(即使 Products/Applications/*.app 存在)
|
||
#
|
||
# 说明:
|
||
# - 该脚本的核心作用是让 Organizer 能识别归档里的主 App,从而出现“分发/上传 TestFlight”入口。
|
||
# - 这类问题通常发生在命令行/CI 归档(xcodebuild archive)或某些自定义归档流程中,
|
||
# 导致 .xcarchive/Info.plist 缺少/不完整。
|
||
#
|
||
# 用法:
|
||
# ./scripts/fix-xcarchive-header.sh "/path/to/xxx.xcarchive"
|
||
|
||
ARCHIVE_PATH="${1:-}"
|
||
if [[ -z "$ARCHIVE_PATH" ]]; then
|
||
echo "用法: $0 \"/path/to/xxx.xcarchive\"" >&2
|
||
exit 2
|
||
fi
|
||
|
||
if [[ ! -d "$ARCHIVE_PATH" ]]; then
|
||
echo "错误:找不到归档目录:$ARCHIVE_PATH" >&2
|
||
exit 2
|
||
fi
|
||
|
||
ARCHIVE_INFO_PLIST="$ARCHIVE_PATH/Info.plist"
|
||
if [[ ! -f "$ARCHIVE_INFO_PLIST" ]]; then
|
||
echo "错误:找不到归档 Info.plist:$ARCHIVE_INFO_PLIST" >&2
|
||
exit 2
|
||
fi
|
||
|
||
# 归档名:尽量从路径推导,避免依赖 Xcode 环境变量
|
||
archive_basename="$(/usr/bin/basename "$ARCHIVE_PATH")"
|
||
archive_name="${archive_basename%.xcarchive}"
|
||
|
||
# 取第一个 App(归档里通常只有一个主 App)
|
||
APP_PLIST="$(/usr/bin/find "$ARCHIVE_PATH/Products/Applications" -maxdepth 2 -name Info.plist -path "*.app/Info.plist" 2>/dev/null | /usr/bin/head -n 1 || true)"
|
||
if [[ -z "$APP_PLIST" ]]; then
|
||
echo "错误:归档中未找到 Products/Applications/*.app/Info.plist(请先确保归档产出包含 .app)" >&2
|
||
exit 2
|
||
fi
|
||
|
||
APP_DIR="$(/usr/bin/dirname "$APP_PLIST")"
|
||
APP_NAME="$(/usr/bin/basename "$APP_DIR")" # 例如 DearMama.app
|
||
APP_REL_PATH="Applications/$APP_NAME"
|
||
|
||
bundle_id="$(/usr/bin/plutil -extract CFBundleIdentifier raw -o - "$APP_PLIST" 2>/dev/null || true)"
|
||
short_version="$(/usr/bin/plutil -extract CFBundleShortVersionString raw -o - "$APP_PLIST" 2>/dev/null || true)"
|
||
build_version="$(/usr/bin/plutil -extract CFBundleVersion raw -o - "$APP_PLIST" 2>/dev/null || true)"
|
||
display_name="$(/usr/bin/plutil -extract CFBundleDisplayName raw -o - "$APP_PLIST" 2>/dev/null || true)"
|
||
bundle_name="$(/usr/bin/plutil -extract CFBundleName raw -o - "$APP_PLIST" 2>/dev/null || true)"
|
||
|
||
# SchemeName 在 Organizer 中会用到,但在某些归档流程里会缺失
|
||
scheme_name="${SCHEME_NAME:-}"
|
||
if [[ -z "$scheme_name" ]]; then
|
||
scheme_name="${archive_name:-}"
|
||
fi
|
||
|
||
if [[ -z "$bundle_id" || -z "$short_version" || -z "$build_version" ]]; then
|
||
echo "错误:无法从 App Info.plist 读取 bundle/version/build:$APP_PLIST" >&2
|
||
exit 2
|
||
fi
|
||
|
||
# 解析 embedded.mobileprovision(若存在)
|
||
profile_name=""
|
||
profile_uuid=""
|
||
team_id=""
|
||
provision_path="$APP_DIR/embedded.mobileprovision"
|
||
if [[ -f "$provision_path" ]]; then
|
||
decoded="$(/usr/bin/security cms -D -i "$provision_path" 2>/dev/null || true)"
|
||
if [[ -n "$decoded" ]]; then
|
||
# 使用 plutil 从 xml 中提取字段
|
||
profile_name="$(printf "%s" "$decoded" | /usr/bin/plutil -extract Name raw -o - - 2>/dev/null || true)"
|
||
profile_uuid="$(printf "%s" "$decoded" | /usr/bin/plutil -extract UUID raw -o - - 2>/dev/null || true)"
|
||
team_id="$(printf "%s" "$decoded" | /usr/bin/plutil -extract TeamIdentifier.0 raw -o - - 2>/dev/null || true)"
|
||
fi
|
||
fi
|
||
|
||
# 备份一份,防止误操作
|
||
cp -f "$ARCHIVE_INFO_PLIST" "$ARCHIVE_INFO_PLIST.bak"
|
||
|
||
# 修复归档根字段,避免 Organizer 仍然把它当 Generic Archive
|
||
# 参考:标准 .xcarchive/Info.plist 通常包含 Name / SchemeName / ArchiveVersion / CreationDate 等。
|
||
# 我们只在缺失时补齐,尽量不改动归档的其他内容。
|
||
if ! /usr/bin/plutil -extract Name xml1 -o - "$ARCHIVE_INFO_PLIST" >/dev/null 2>&1; then
|
||
/usr/bin/plutil -insert Name -string "${archive_name:-${display_name:-${bundle_name:-}}}" "$ARCHIVE_INFO_PLIST" 2>/dev/null || true
|
||
fi
|
||
if ! /usr/bin/plutil -extract SchemeName xml1 -o - "$ARCHIVE_INFO_PLIST" >/dev/null 2>&1; then
|
||
/usr/bin/plutil -insert SchemeName -string "${scheme_name:-${archive_name:-}}" "$ARCHIVE_INFO_PLIST" 2>/dev/null || true
|
||
fi
|
||
|
||
# 如果已有 ApplicationProperties,直接更新关键字段即可
|
||
if /usr/bin/plutil -extract ApplicationProperties xml1 -o - "$ARCHIVE_INFO_PLIST" >/dev/null 2>&1; then
|
||
/usr/bin/plutil -replace ApplicationProperties.ApplicationPath -string "$APP_REL_PATH" "$ARCHIVE_INFO_PLIST"
|
||
/usr/bin/plutil -replace ApplicationProperties.CFBundleIdentifier -string "$bundle_id" "$ARCHIVE_INFO_PLIST"
|
||
/usr/bin/plutil -replace ApplicationProperties.CFBundleShortVersionString -string "$short_version" "$ARCHIVE_INFO_PLIST"
|
||
/usr/bin/plutil -replace ApplicationProperties.CFBundleVersion -string "$build_version" "$ARCHIVE_INFO_PLIST"
|
||
else
|
||
# 新增 ApplicationProperties(注意:plutil 的空字典/数组类型是 -dictionary / -array)
|
||
/usr/bin/plutil -insert ApplicationProperties -dictionary "$ARCHIVE_INFO_PLIST"
|
||
/usr/bin/plutil -insert ApplicationProperties.ApplicationPath -string "$APP_REL_PATH" "$ARCHIVE_INFO_PLIST"
|
||
/usr/bin/plutil -insert ApplicationProperties.CFBundleIdentifier -string "$bundle_id" "$ARCHIVE_INFO_PLIST"
|
||
/usr/bin/plutil -insert ApplicationProperties.CFBundleShortVersionString -string "$short_version" "$ARCHIVE_INFO_PLIST"
|
||
/usr/bin/plutil -insert ApplicationProperties.CFBundleVersion -string "$build_version" "$ARCHIVE_INFO_PLIST"
|
||
/usr/bin/plutil -insert ApplicationProperties.Architectures -array "$ARCHIVE_INFO_PLIST"
|
||
/usr/bin/plutil -insert ApplicationProperties.Architectures.0 -string "arm64" "$ARCHIVE_INFO_PLIST"
|
||
fi
|
||
|
||
# 可选字段:Provisioning Profile 信息(不保证一定存在)
|
||
if [[ -n "$profile_name" ]]; then
|
||
/usr/bin/plutil -replace ApplicationProperties.ProvisioningProfileName -string "$profile_name" "$ARCHIVE_INFO_PLIST" 2>/dev/null || \
|
||
/usr/bin/plutil -insert ApplicationProperties.ProvisioningProfileName -string "$profile_name" "$ARCHIVE_INFO_PLIST"
|
||
fi
|
||
if [[ -n "$profile_uuid" ]]; then
|
||
/usr/bin/plutil -replace ApplicationProperties.ProvisioningProfileUUID -string "$profile_uuid" "$ARCHIVE_INFO_PLIST" 2>/dev/null || \
|
||
/usr/bin/plutil -insert ApplicationProperties.ProvisioningProfileUUID -string "$profile_uuid" "$ARCHIVE_INFO_PLIST"
|
||
fi
|
||
if [[ -n "$team_id" ]]; then
|
||
/usr/bin/plutil -replace ApplicationProperties.Team -string "$team_id" "$ARCHIVE_INFO_PLIST" 2>/dev/null || \
|
||
/usr/bin/plutil -insert ApplicationProperties.Team -string "$team_id" "$ARCHIVE_INFO_PLIST"
|
||
fi
|
||
|
||
echo "已修复归档 header:$ARCHIVE_INFO_PLIST"
|
||
echo "主 App:$APP_REL_PATH"
|
||
echo "Bundle:$bundle_id"
|
||
echo "Version/Build:$short_version/$build_version"
|
||
echo "Name/SchemeName:${archive_name:-} / ${scheme_name:-}"
|
||
|
||
# 轻量自检:确保关键字段存在(不强制失败,避免中断归档)
|
||
if ! /usr/bin/plutil -extract ApplicationProperties.ApplicationPath xml1 -o - "$ARCHIVE_INFO_PLIST" >/dev/null 2>&1; then
|
||
echo "警告:归档 Info.plist 仍缺少 ApplicationProperties.ApplicationPath,Organizer 可能仍显示 Generic Archive" >&2
|
||
fi
|