|
| 1 | +#!/bin/sh |
| 2 | +# Verifies that Unity's API updater rewrites NGO 2.x editor API references to their NGO 3.x |
| 3 | +# Unity.Netcode.GameObjects.Editor equivalents. macOS and Linux; see run-upgrade-test.ps1 for Windows. |
| 4 | +# |
| 5 | +# Runs the editor over this project in batch mode with -accept-apiupdate, then asserts that every |
| 6 | +# Unity.Netcode.Editor reference under Assets/Editor was rewritten and that no stale reference |
| 7 | +# survived. The 2.x sources are restored on exit so the test can be re-run. |
| 8 | +# |
| 9 | +# ./run-upgrade-test.sh |
| 10 | +# ./run-upgrade-test.sh --unity /Applications/Unity/Hub/Editor/6000.6.0b5/Unity.app/Contents/MacOS/Unity --clean |
| 11 | +# |
| 12 | +# --unity <path> Editor binary. Defaults to $UNITY_EDITOR_PATH, then to the hub install |
| 13 | +# matching ProjectSettings/ProjectVersion.txt. |
| 14 | +# --clean Delete Library and Temp first, for a cold import. |
| 15 | +# --keep-updated-sources Leave the rewritten sources in place instead of restoring the originals. |
| 16 | + |
| 17 | +set -eu |
| 18 | + |
| 19 | +PROJECT_PATH=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) |
| 20 | +SOURCE_DIR="$PROJECT_PATH/Assets/Editor" |
| 21 | +LOG_FILE="$PROJECT_PATH/upgrade-test.log" |
| 22 | + |
| 23 | +UNITY_EXE="" |
| 24 | +CLEAN=0 |
| 25 | +KEEP_UPDATED_SOURCES=0 |
| 26 | + |
| 27 | +while [ $# -gt 0 ]; do |
| 28 | + case "$1" in |
| 29 | + --unity) |
| 30 | + [ $# -ge 2 ] || { echo "--unity requires a path" >&2; exit 2; } |
| 31 | + UNITY_EXE="$2"; shift 2 ;; |
| 32 | + --clean) CLEAN=1; shift ;; |
| 33 | + --keep-updated-sources) KEEP_UPDATED_SOURCES=1; shift ;; |
| 34 | + -h|--help) sed -n '2,16p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; |
| 35 | + *) echo "Unknown argument: $1" >&2; exit 2 ;; |
| 36 | + esac |
| 37 | +done |
| 38 | + |
| 39 | +# Every 2.x type the sources reference, and what the updater is expected to turn it into. |
| 40 | +# Frozen: this is the public editor API of develop-2.0.0, which is released and will not change. |
| 41 | +# Extend it by hand if a public editor type is ever relocated again within 3.x. |
| 42 | +EXPECTED_TYPES=" |
| 43 | +Unity.Netcode.Editor.HiddenScriptEditor |
| 44 | +Unity.Netcode.Editor.UnityTransportEditor |
| 45 | +Unity.Netcode.Editor.NetworkAnimatorEditor |
| 46 | +Unity.Netcode.Editor.NetworkRigidbodyEditor |
| 47 | +Unity.Netcode.Editor.NetworkRigidbody2DEditor |
| 48 | +Unity.Netcode.Editor.NetcodeEditorBase |
| 49 | +Unity.Netcode.Editor.NetworkBehaviourEditor |
| 50 | +Unity.Netcode.Editor.NetworkManagerEditor |
| 51 | +Unity.Netcode.Editor.NetworkManagerHelper |
| 52 | +Unity.Netcode.Editor.NetworkObjectEditor |
| 53 | +Unity.Netcode.Editor.NetworkRigidbodyBaseEditor |
| 54 | +Unity.Netcode.Editor.NetworkTransformEditor |
| 55 | +Unity.Netcode.Editor.NetworkPrefabsEditor |
| 56 | +Unity.Netcode.Editor.Configuration.NetcodeForGameObjectsProjectSettings |
| 57 | +Unity.Netcode.Editor.Configuration.NetworkPrefabProcessor |
| 58 | +" |
| 59 | + |
| 60 | +resolve_unity() { |
| 61 | + if [ -n "$UNITY_EXE" ]; then |
| 62 | + [ -x "$UNITY_EXE" ] || { echo "Editor not found or not executable: $UNITY_EXE" >&2; exit 1; } |
| 63 | + echo "$UNITY_EXE"; return |
| 64 | + fi |
| 65 | + if [ -n "${UNITY_EDITOR_PATH:-}" ]; then |
| 66 | + [ -x "$UNITY_EDITOR_PATH" ] || { echo "UNITY_EDITOR_PATH is not executable: $UNITY_EDITOR_PATH" >&2; exit 1; } |
| 67 | + echo "$UNITY_EDITOR_PATH"; return |
| 68 | + fi |
| 69 | + |
| 70 | + version=$(sed -n 's/^m_EditorVersion:[[:space:]]*\(.*\)$/\1/p' \ |
| 71 | + "$PROJECT_PATH/ProjectSettings/ProjectVersion.txt" | tr -d '\r' | head -n 1) |
| 72 | + [ -n "$version" ] || { echo "Could not read m_EditorVersion from ProjectSettings/ProjectVersion.txt" >&2; exit 1; } |
| 73 | + |
| 74 | + # Default hub locations differ per platform, and the macOS editor lives inside the .app bundle. |
| 75 | + case "$(uname -s)" in |
| 76 | + Darwin) candidate="/Applications/Unity/Hub/Editor/$version/Unity.app/Contents/MacOS/Unity" ;; |
| 77 | + *) candidate="$HOME/Unity/Hub/Editor/$version/Editor/Unity" ;; |
| 78 | + esac |
| 79 | + [ -x "$candidate" ] && { echo "$candidate"; return; } |
| 80 | + |
| 81 | + echo "No editor found for $version at $candidate. Pass --unity or set UNITY_EDITOR_PATH." >&2 |
| 82 | + exit 1 |
| 83 | +} |
| 84 | + |
| 85 | +UNITY=$(resolve_unity) |
| 86 | +echo "Editor: $UNITY" |
| 87 | +echo "Project: $PROJECT_PATH" |
| 88 | + |
| 89 | +BACKUP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/ngo-apiupdater-XXXXXX") |
| 90 | +cp -R "$SOURCE_DIR/." "$BACKUP_DIR/" |
| 91 | + |
| 92 | +# Restore on any exit path, so an interrupted run does not leave rewritten sources behind. |
| 93 | +# Guarded: trapping both EXIT and INT/TERM means this can be entered twice. |
| 94 | +CLEANED=0 |
| 95 | +cleanup() { |
| 96 | + [ "$CLEANED" -eq 0 ] || return 0 |
| 97 | + CLEANED=1 |
| 98 | + if [ "$KEEP_UPDATED_SOURCES" -eq 0 ]; then |
| 99 | + cp -R "$BACKUP_DIR/." "$SOURCE_DIR/" |
| 100 | + rm -rf "$BACKUP_DIR" |
| 101 | + fi |
| 102 | +} |
| 103 | +trap cleanup EXIT INT TERM |
| 104 | + |
| 105 | +if [ "$CLEAN" -eq 1 ]; then |
| 106 | + for stale in Library Temp; do |
| 107 | + if [ -d "$PROJECT_PATH/$stale" ]; then |
| 108 | + echo "Removing $stale ..." |
| 109 | + rm -rf "$PROJECT_PATH/$stale" |
| 110 | + fi |
| 111 | + done |
| 112 | +fi |
| 113 | + |
| 114 | +rm -f "$LOG_FILE" |
| 115 | + |
| 116 | +echo "Running the editor (this imports the project and runs the API updater)..." |
| 117 | +# The editor returns non-zero when compilation fails, which is the normal state before the updater |
| 118 | +# rewrites the sources, so do not let set -e abort here. |
| 119 | +EDITOR_STATUS=0 |
| 120 | +"$UNITY" \ |
| 121 | + -batchmode -nographics -quit \ |
| 122 | + -accept-apiupdate \ |
| 123 | + -ignoreCompilerErrors \ |
| 124 | + -burst-disable-compilation \ |
| 125 | + -projectPath "$PROJECT_PATH" \ |
| 126 | + -logFile "$LOG_FILE" || EDITOR_STATUS=$? |
| 127 | +echo "Editor exit code: $EDITOR_STATUS" |
| 128 | + |
| 129 | +ALL_TEXT=$(cat "$SOURCE_DIR"/*.cs) |
| 130 | + |
| 131 | +TOTAL=0 |
| 132 | +FAILURES=0 |
| 133 | +printf '\n%-72s %8s %6s %s\n' "TYPE" "UPDATED" "STALE" "RESULT" |
| 134 | +for old in $EXPECTED_TYPES; do |
| 135 | + TOTAL=$((TOTAL + 1)) |
| 136 | + new="Unity.Netcode.GameObjects.${old#Unity.Netcode.}" |
| 137 | + |
| 138 | + updated=$(printf '%s' "$ALL_TEXT" | grep -o -F "$new" | wc -l | tr -d ' ') |
| 139 | + # The old name only ever survives as a distinct token; a trailing word char or dot means it is |
| 140 | + # really part of the longer new name, so exclude those. |
| 141 | + stale=$(printf '%s' "$ALL_TEXT" | grep -oE "$(printf '%s' "$old" | sed 's/\./\\./g')([^A-Za-z0-9_.]|$)" | wc -l | tr -d ' ') |
| 142 | + |
| 143 | + if [ "$updated" -gt 0 ] && [ "$stale" -eq 0 ]; then |
| 144 | + result="PASS" |
| 145 | + else |
| 146 | + result="FAIL" |
| 147 | + FAILURES=$((FAILURES + 1)) |
| 148 | + fi |
| 149 | + printf '%-72s %8s %6s %s\n' "$old" "$updated" "$stale" "$result" |
| 150 | +done |
| 151 | + |
| 152 | +echo "" |
| 153 | +if [ "$FAILURES" -eq 0 ]; then |
| 154 | + echo "PASS: all $TOTAL deprecated editor types were rewritten." |
| 155 | +else |
| 156 | + echo "FAIL: $FAILURES of $TOTAL types were not rewritten. See $LOG_FILE" |
| 157 | +fi |
| 158 | + |
| 159 | +if [ "$KEEP_UPDATED_SOURCES" -eq 1 ]; then |
| 160 | + echo "Rewritten sources left in place under Assets/Editor (backup: $BACKUP_DIR)." |
| 161 | +fi |
| 162 | + |
| 163 | +[ "$FAILURES" -eq 0 ] || exit 1 |
| 164 | +exit 0 |
0 commit comments