#if UNITY_EDITOR using UnityEditor; using UnityEngine; using System.Diagnostics; using System.IO; using Debug = UnityEngine.Debug; /// /// GitAutoSync — Unity Editor 자동 git sync (BurningTimes BT5-Dev C안, 2026-04-23 PD 승인) /// /// 구조: Unity Editor(본 스크립트) = trigger 전용. 실제 git 작업은 /// BT 본 레포 scripts/unity_auto_sync.sh (bash) 가 수행. /// 이 분리로 스크립트 컴파일 오류가 git 기능을 마비시키는 리스크 차단. /// /// 동작: /// - Unity Editor 시작 시: 자동 pull (EditorPrefs 토글 가능) /// - Unity Editor 종료 시: 자동 push (add + commit + push 일괄) /// - Menu: Tools/Git/Pull Now·Push Now·Status·토글 옵션 /// /// 의존: /// - Git for Windows (bash.exe) — PD 실증 환경 /// - BURNINGTIMES_ROOT 환경변수 또는 기본 E:/BurningTimes /// - paths.local.json 의 UNITY_PROJECT_ROOT · UNITY_GIT_REMOTE 설정 /// [InitializeOnLoad] public static class GitAutoSync { private const string BT_ROOT_ENV = "BURNINGTIMES_ROOT"; private const string BT_ROOT_FALLBACK = "E:/BurningTimes"; private const string SYNC_SCRIPT_REL = "scripts/unity_auto_sync.sh"; private const string PREF_PULL_ON_LOAD = "GitAutoSync.PullOnLoad"; private const string PREF_PUSH_ON_QUIT = "GitAutoSync.PushOnQuit"; private const string GIT_BASH_FALLBACK = @"C:\Program Files\Git\bin\bash.exe"; static GitAutoSync() { // Unity Editor 시작 시 컴파일 안정화 후 pull (delayCall은 프레임 지연) EditorApplication.delayCall += OnEditorStart; EditorApplication.quitting += OnEditorQuit; } // ───────────────────────────────────────────────────────── // 경로·bash 해결 // ───────────────────────────────────────────────────────── private static string GetBTRoot() { string envRoot = System.Environment.GetEnvironmentVariable(BT_ROOT_ENV); return string.IsNullOrEmpty(envRoot) ? BT_ROOT_FALLBACK : envRoot; } private static string GetSyncScriptPath() { return Path.Combine(GetBTRoot(), SYNC_SCRIPT_REL).Replace('\\', '/'); } private static string GetBashPath() { // Windows Git Bash 우선 (PD 환경 실증) if (File.Exists(GIT_BASH_FALLBACK)) return GIT_BASH_FALLBACK; // PATH 검색 fallback (macOS/Linux 포함) return "bash"; } // ───────────────────────────────────────────────────────── // bash 스크립트 호출 // ───────────────────────────────────────────────────────── private static int RunSync(string action) { string scriptPath = GetSyncScriptPath(); if (!File.Exists(scriptPath)) { Debug.LogWarning($"[GitAutoSync] 스크립트 부재: {scriptPath}\n" + $"BT 본 레포 확인 필요 (환경변수 {BT_ROOT_ENV} 또는 {BT_ROOT_FALLBACK})"); return -1; } var psi = new ProcessStartInfo { FileName = GetBashPath(), Arguments = $"\"{scriptPath}\" {action}", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true }; try { using (var proc = Process.Start(psi)) { string stdout = proc.StandardOutput.ReadToEnd(); string stderr = proc.StandardError.ReadToEnd(); proc.WaitForExit(); string combined = stdout + (string.IsNullOrEmpty(stderr) ? "" : "\n[stderr]\n" + stderr); if (proc.ExitCode == 0) { Debug.Log($"[GitAutoSync] {action} 성공\n{combined}"); } else { Debug.LogError($"[GitAutoSync] {action} 실패 (exit {proc.ExitCode})\n{combined}"); // 수동 개입 필요한 케이스 (충돌 등)는 Dialog로 PD 알림 if (action == "pull" || action == "push") { EditorApplication.delayCall += () => EditorUtility.DisplayDialog( "GitAutoSync 실패", $"{action} 실패 (exit {proc.ExitCode}).\n\nConsole 로그 확인 후 수동 해결 필요.", "확인"); } } return proc.ExitCode; } } catch (System.Exception ex) { Debug.LogError($"[GitAutoSync] {action} 예외: {ex.Message}\n{ex.StackTrace}"); return -2; } } // ───────────────────────────────────────────────────────── // 자동 hook // ───────────────────────────────────────────────────────── private static void OnEditorStart() { if (EditorPrefs.GetBool(PREF_PULL_ON_LOAD, true)) { Debug.Log("[GitAutoSync] Unity Editor 시작 — auto pull"); RunSync("pull"); } } private static void OnEditorQuit() { if (EditorPrefs.GetBool(PREF_PUSH_ON_QUIT, true)) { Debug.Log("[GitAutoSync] Unity Editor 종료 — auto push"); RunSync("push"); } } // ───────────────────────────────────────────────────────── // Menu 수동 발동 // ───────────────────────────────────────────────────────── [MenuItem("Tools/Git/Pull Now %#g")] private static void MenuPull() { RunSync("pull"); } [MenuItem("Tools/Git/Push Now %#p")] private static void MenuPush() { RunSync("push"); } [MenuItem("Tools/Git/Status")] private static void MenuStatus() { RunSync("status"); } [MenuItem("Tools/Git/Init Repo (최초 1회)")] private static void MenuInit() { if (EditorUtility.DisplayDialog( "Unity 프로젝트 git 초기화", "Unity 프로젝트 경로에 git 레포를 초기화합니다. 최초 1회만 수행하세요.\n\nGitea 레포 생성은 별도로 수동 집행 필요.", "진행", "취소")) { RunSync("init"); } } [MenuItem("Tools/Git/Toggle Auto Pull On Load")] private static void TogglePull() { bool next = !EditorPrefs.GetBool(PREF_PULL_ON_LOAD, true); EditorPrefs.SetBool(PREF_PULL_ON_LOAD, next); Debug.Log($"[GitAutoSync] Auto Pull On Load: {next}"); } [MenuItem("Tools/Git/Toggle Auto Push On Quit")] private static void TogglePush() { bool next = !EditorPrefs.GetBool(PREF_PUSH_ON_QUIT, true); EditorPrefs.SetBool(PREF_PUSH_ON_QUIT, next); Debug.Log($"[GitAutoSync] Auto Push On Quit: {next}"); } } #endif