Browse Source

Sujith :) ->
1. Added branch support

sujith 1 month ago
parent
commit
421cefe993

+ 42 - 1
Assets/Arbitrator/Editor/GUI/ArbitratorController.cs

@@ -32,6 +32,8 @@ namespace Terra.Arbitrator.GUI
         public SortColumn CurrentSortColumn { get; private set; } = SortColumn.FilePath;
         public float PushProgress { get; private set; }
         public string PushProgressMessage { get; private set; }
+        public IReadOnlyList<string> RemoteBranchList { get; private set; } = new List<string>();
+        public string CurrentBranchName { get; private set; } = "master";
 
         private readonly Action _requestRepaint;
         private readonly Func<string, string, string, string, bool> _displayDialog;
@@ -72,6 +74,7 @@ namespace Terra.Arbitrator.GUI
             UnstageStep()
                 .Then(CompareStep)
                 .Then(FetchUpstreamStep)
+                .Then(FetchBranchDataStep)
                 .Then(FinalizeRefresh)
                 .Catch(HandleOperationError)
                 .Finally(FinishOperation);
@@ -288,6 +291,36 @@ namespace Terra.Arbitrator.GUI
                 change.IsSelectedForCommit = selected;
             }
         }
+        
+        public void SwitchToBranch(string targetBranch)
+        {
+            if (IsLoading || targetBranch == CurrentBranchName) return;
+
+            if (Changes.Any())
+            {
+                if (!_displayDialog("Discard Local Changes?", $"You have local changes. To switch branches, these changes must be discarded.\n\nDiscard changes and switch to '{targetBranch}'?", "Yes, Discard and Switch", "Cancel"))
+                {
+                    return;
+                }
+                
+                StartOperation($"Discarding changes and switching to {targetBranch}...");
+                GitService.ResetAndSwitchBranch(targetBranch)
+                    .Then(successMsg => { InfoMessage = successMsg; Refresh(); })
+                    .Catch(ex => { HandleOperationError(ex); FinishOperation(); });
+            }
+            else
+            {
+                if (!_displayDialog("Confirm Branch Switch", $"Are you sure you want to switch to branch '{targetBranch}'?", "Yes, Switch", "Cancel"))
+                {
+                    return;
+                }
+
+                StartOperation($"Switching to {targetBranch}...");
+                GitService.SwitchBranch(targetBranch)
+                    .Then(successMsg => { InfoMessage = successMsg; Refresh(); })
+                    .Catch(ex => { HandleOperationError(ex); FinishOperation(); });
+            }
+        }
 
         // --- Private Methods ---
         
@@ -315,9 +348,17 @@ namespace Terra.Arbitrator.GUI
                 new Promise<int?>((resolve, _) => resolve(0)) : GitService.GetUpstreamAheadBy();
         }
 
-        private void FinalizeRefresh(int? pullCount)
+        private IPromise<BranchData> FetchBranchDataStep(int? pullCount)
         {
             CommitsToPull = pullCount ?? 0;
+            return GitService.GetBranchData();
+        }
+
+        private void FinalizeRefresh(BranchData branchData)
+        {
+            CurrentBranchName = branchData.CurrentBranch;
+            RemoteBranchList = branchData.AllBranches;
+            ApplyGrouping();
         }
         
         // --- Shared Helper Methods ---

+ 15 - 0
Assets/Arbitrator/Editor/GUI/ArbitratorWindow.cs

@@ -75,6 +75,8 @@ namespace Terra.Arbitrator.GUI
         {
             EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
             EditorGUI.BeginDisabledGroup(_controller.IsLoading);
+            
+            DrawBranchSelector();
 
             if (GUILayout.Button(new GUIContent("Refresh", EditorGUIUtility.IconContent("Refresh").image), EditorStyles.toolbarButton, GUILayout.Width(80)))
             {
@@ -136,6 +138,19 @@ namespace Terra.Arbitrator.GUI
             EditorGUILayout.EndHorizontal();
         }
         
+        private void DrawBranchSelector()
+        {
+            var branches = _controller.RemoteBranchList.ToArray();
+            var currentIndex = System.Array.IndexOf(branches, _controller.CurrentBranchName);
+            if (currentIndex == -1) currentIndex = 0;
+
+            var newIndex = EditorGUILayout.Popup(currentIndex, branches, EditorStyles.toolbarPopup, GUILayout.Width(150));
+
+            if (newIndex == currentIndex) return;
+            var selectedBranch = branches[newIndex];
+            EditorApplication.delayCall += () => _controller.SwitchToBranch(selectedBranch);
+        }
+        
         private void DrawMessageArea()
         {
             if (!string.IsNullOrEmpty(_controller.ErrorMessage))

+ 63 - 0
Assets/Arbitrator/Editor/Services/GitExecutors.cs

@@ -19,6 +19,15 @@ using System.Collections.Generic;
 
 namespace Terra.Arbitrator.Services
 {
+    /// <summary>
+    /// A simple data container for branch information.
+    /// </summary>
+    public class BranchData
+    {
+        public string CurrentBranch { get; set; }
+        public List<string> AllBranches { get; set; }
+    }
+    
     /// <summary>
     /// Contains the promise executor methods for all Git operations.
     /// This is an internal implementation detail and is not exposed publicly.
@@ -28,6 +37,60 @@ namespace Terra.Arbitrator.Services
         private static string _projectRoot;
         private static string ProjectRoot => _projectRoot ??= Directory.GetParent(Application.dataPath)?.FullName;
         
+        public static void GetBranchDataExecutor(Action<BranchData> resolve, Action<Exception> reject)
+        {
+            try
+            {
+                using var repo = new Repository(ProjectRoot);
+                var data = new BranchData
+                {
+                    CurrentBranch = repo.Head.FriendlyName,
+                    // Get all local and remote branches, then get their friendly names and remove duplicates.
+                    AllBranches = repo.Branches
+                                      .Where(b => !b.FriendlyName.Contains("HEAD")) // Filter out the detached HEAD entry
+                                      .Select(b => b.FriendlyName.Replace("origin/", "")) // Clean up remote names
+                                      .Distinct()
+                                      .OrderBy(name => name)
+                                      .ToList()
+                };
+                resolve(data);
+            }
+            catch(Exception ex)
+            {
+                reject(ex);
+            }
+        }
+        
+        public static async void SwitchBranchExecutor(Action<string> resolve, Action<Exception> reject, string branchName)
+        {
+            try
+            {
+                var log = new StringBuilder();
+                await GitCommand.RunAsync(log, new[] { "checkout", branchName });
+                resolve($"Successfully switched to branch '{branchName}'.");
+            }
+            catch (Exception ex)
+            {
+                reject(ex);
+            }
+        }
+        
+        public static async void ResetAndSwitchBranchExecutor(Action<string> resolve, Action<Exception> reject, string branchName)
+        {
+            try
+            {
+                var log = new StringBuilder();
+                await GitCommand.RunAsync(log, new[] { "reset", "--hard", "HEAD" });
+                await GitCommand.RunAsync(log, new[] { "clean", "-fd" });
+                await GitCommand.RunAsync(log, new[] { "checkout", branchName });
+                resolve($"Discarded local changes and switched to branch '{branchName}'.");
+            }
+            catch (Exception ex)
+            {
+                reject(ex);
+            }
+        }
+        
         /// <summary>
         /// Synchronous helper to get a GitChange object for a single file.
         /// This is public so it can be called by the GitService wrapper.

+ 24 - 8
Assets/Arbitrator/Editor/Services/GitService.cs

@@ -16,6 +16,30 @@ namespace Terra.Arbitrator.Services
     /// </summary>
     public static class GitService
     {
+        /// <summary>
+        /// Gets the current branch and a list of all available branches.
+        /// </summary>
+        public static IPromise<BranchData> GetBranchData()
+        {
+            return new Promise<BranchData>(GitExecutors.GetBranchDataExecutor);
+        }
+
+        /// <summary>
+        /// Performs a safe checkout to the specified branch.
+        /// </summary>
+        public static IPromise<string> SwitchBranch(string branchName)
+        {
+            return new Promise<string>((resolve, reject) => GitExecutors.SwitchBranchExecutor(resolve, reject, branchName));
+        }
+
+        /// <summary>
+        /// Discards all local changes and forcibly checks out the specified branch.
+        /// </summary>
+        public static IPromise<string> ResetAndSwitchBranch(string branchName)
+        {
+            return new Promise<string>((resolve, reject) => GitExecutors.ResetAndSwitchBranchExecutor(resolve, reject, branchName));
+        }
+        
         /// <summary>
         /// Synchronously gets the Git status for a single file.
         /// Required by UI elements that cannot easily use promises.
@@ -107,13 +131,5 @@ namespace Terra.Arbitrator.Services
         {
             return new Promise<bool>(GitExecutors.UnstageAllFilesIfSafeExecutor);
         }
-        
-        /// <summary>
-        /// Discards all local changes (tracked and untracked) in the repository.
-        /// </summary>
-        public static IPromise<string> ResetAllChanges()
-        {
-            return new Promise<string>(GitExecutors.ResetAllChangesExecutor);
-        }
     }
 }