EerieVillage/Assets/Editor/GitAutoSync/GitAutoSync.cs

188 lines
7.6 KiB
C#

#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using System.Diagnostics;
using System.IO;
using Debug = UnityEngine.Debug;
/// <summary>
/// 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 설정
/// </summary>
[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