#!/usr/bin/env bash set -euo pipefail # 修复 Xcode Organizer 显示 “Generic Xcode Archive” 的问题: # - 某些情况下 xcodebuild 生成的 .xcarchive/Info.plist 缺少 ApplicationProperties # - Organizer 无法识别归档中的主 App(即使 Products/Applications/*.app 存在) # # 用法: # ./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 # 取第一个 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")" # 例如 HeyMama.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)" 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" # 如果已有 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"