Browse Source

Sujith :) ->
1. Added Pull and Overwrite feature. Need to be tested.

sujith 1 month ago
parent
commit
fb2ad9e87d

+ 14 - 13
Assets/Better Git/Arbitrator/Editor/GUI/ArbitratorController.cs

@@ -102,7 +102,8 @@ namespace Terra.Arbitrator.GUI
                     FinishOperation();
                     if (analysisResult.HasConflicts)
                     {
-                        ConflictResolutionWindow.ShowWindow(this, analysisResult.ConflictingFiles);
+                        var conflictingChanges = _changes.Where(c => analysisResult.ConflictingFiles.Contains(c.FilePath)).ToList();
+                        ConflictResolutionWindow.ShowWindow(this, conflictingChanges);
                     }
                     else
                     {
@@ -133,23 +134,23 @@ namespace Terra.Arbitrator.GUI
                 .Finally(EditorApplication.UnlockReloadAssemblies);
         }
         
-        public void ResetSingleConflictingFile(string filePath, Action onResetComplete)
+        public void ResolveConflictsAndPull(List<GitChange> resolutions)
         {
-            var change = GitService.GetChangeForFile(filePath);
-            if (change == null)
-            {
-                ErrorMessage = $"Could not find file '{filePath}' to reset.";
-                onResetComplete?.Invoke();
-                return;
-            }
-            
-            GitService.ResetFileChanges(change)
+            StartOperation("Resolving conflicts and pulling...");
+            EditorApplication.LockReloadAssemblies();
+
+            GitService.PullAndOverwrite(resolutions)
                 .Then(successMessage =>
                 {
                     InfoMessage = successMessage;
                 })
                 .Catch(HandleOperationError)
-                .Finally(onResetComplete);
+                .Finally(() =>
+                {
+                    EditorApplication.UnlockReloadAssemblies();
+                    AssetDatabase.Refresh();
+                    Refresh();
+                });
         }
 
         public void CommitAndPush(string commitMessage)
@@ -205,7 +206,7 @@ namespace Terra.Arbitrator.GUI
             };
         }
         
-        private int GetStatusSortPriority(LibGit2Sharp.ChangeKind status)
+        private static int GetStatusSortPriority(LibGit2Sharp.ChangeKind status)
         {
             return status switch
             {

+ 32 - 34
Assets/Better Git/Arbitrator/Editor/GUI/ConflictResolutionWindow.cs

@@ -3,9 +3,12 @@
 // A modal editor window that displays pull conflicts and allows the user
 // to select files to reset before proceeding.
 
+using System.IO;
 using UnityEditor;
 using UnityEngine;
+using System.Linq;
 using UnityEngine.Scripting;
+using Terra.Arbitrator.Services;
 using System.Collections.Generic;
 
 namespace Terra.Arbitrator.GUI
@@ -13,34 +16,46 @@ namespace Terra.Arbitrator.GUI
     [Preserve]
     public class ConflictResolutionWindow : EditorWindow
     {
-        private List<string> _conflictingFiles;
-        private string _fileBeingReset;
+        private List<GitChange> _conflictingFiles;
         private Vector2 _scrollPosition;
         private ArbitratorController _controller;
+        private GUIStyle _wordWrapStyle;
 
         /// <summary>
         /// Shows a modal window to display pull conflicts and get user action.
         /// </summary>
         /// <param name="controller">Reference to the arbitrator controller</param>
         /// <param name="conflictingFiles">The list of files that have conflicts.</param>
-        public static void ShowWindow(ArbitratorController controller, List<string> conflictingFiles)
+        public static void ShowWindow(ArbitratorController controller, IReadOnlyList<GitChange> conflictingFiles)
         {
             var window = GetWindow<ConflictResolutionWindow>(true, "Pull Conflicts Detected", true);
             window.minSize = new Vector2(600, 400);
             window._controller = controller;
-            window._conflictingFiles = new List<string>(conflictingFiles);
+            window._conflictingFiles = new List<GitChange>(conflictingFiles);
             window.ShowModalUtility();
         }
 
         private void OnGUI()
         {
-            EditorGUILayout.HelpBox("A pull would result in conflicts with your local changes. To proceed with a clean pull, you must reset your local changes for the conflicting files listed below.", MessageType.Warning);
-            EditorGUILayout.LabelField("Conflicting Files:", EditorStyles.boldLabel);
+            _wordWrapStyle ??= new GUIStyle(EditorStyles.label) { wordWrap = true };
+            
+            EditorGUILayout.HelpBox("A pull would result in conflicts with your local changes. To proceed with a clean pull, you must choose a resolution for the conflicting files listed below.", MessageType.Warning);
+            
+            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
+            GUILayout.Label("Filename");
+            GUILayout.FlexibleSpace();
+            GUILayout.Label(""); //Spacer
+            GUILayout.FlexibleSpace();
+            GUILayout.Label("Choice", GUILayout.Width(70));
+            EditorGUILayout.EndHorizontal();
 
             _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, EditorStyles.helpBox);
-            foreach (var file in new List<string>(_conflictingFiles))
+            if (_conflictingFiles != null)
             {
-                DrawFileRow(file);
+                foreach (var change in _conflictingFiles)
+                {
+                    DrawFileRow(change);
+                }
             }
             EditorGUILayout.EndScrollView();
 
@@ -48,44 +63,27 @@ namespace Terra.Arbitrator.GUI
             DrawActionButtons();
         }
         
-        private void DrawFileRow(string filePath)
+        private void DrawFileRow(GitChange change)
         {
-            EditorGUILayout.BeginHorizontal();
-            EditorGUILayout.LabelField(new GUIContent(filePath, filePath));
+            EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
 
-            var isThisFileLoading = _fileBeingReset == filePath;
-
-            EditorGUI.BeginDisabledGroup(isThisFileLoading || !string.IsNullOrEmpty(_fileBeingReset));
-            if (GUILayout.Button(isThisFileLoading ? "Resetting..." : "Reset", GUILayout.Width(100)))
-            {
-                HandleResetFile(filePath);
-            }
-            EditorGUI.EndDisabledGroup();
+            EditorGUILayout.LabelField(new GUIContent(change.FilePath, change.FilePath), _wordWrapStyle, GUILayout.ExpandWidth(true));
+            change.Resolution = (GitChange.ConflictResolution)EditorGUILayout.EnumPopup(change.Resolution, GUILayout.Width(70));
             
             EditorGUILayout.EndHorizontal();
         }
-        
-        private void HandleResetFile(string filePath)
-        {
-            _fileBeingReset = filePath;
-            Repaint();
-            
-            _controller.ResetSingleConflictingFile(filePath, () =>
-            {
-                _conflictingFiles.Remove(filePath);
-                _fileBeingReset = null;
-                Repaint();
-            });
-        }
 
         private void DrawActionButtons()
         {
             EditorGUILayout.BeginHorizontal();
             GUILayout.FlexibleSpace();
 
-            if (GUILayout.Button("Proceed with Pull (Risky)", GUILayout.Height(30), GUILayout.Width(180)))
+            var allResolved = _conflictingFiles != null && _conflictingFiles.All(c => c.Resolution != GitChange.ConflictResolution.None);
+            var pullButtonText = allResolved ? "Pull Safely" : "Pull Anyways (Risky)";
+
+            if (GUILayout.Button(pullButtonText, GUILayout.Height(30), GUILayout.Width(180)))
             {
-                _controller.ForcePull();
+                _controller?.ResolveConflictsAndPull(_conflictingFiles);
                 Close();
             }
             if (GUILayout.Button("Cancel", GUILayout.Height(30)))

+ 9 - 9
Assets/Better Git/Arbitrator/Editor/Services/GitChange.cs

@@ -3,10 +3,6 @@
 // This script defines the data model for a single Git change.
 // An object of this class holds information about a file that has been
 // added, modified, or deleted.
-//
-// HOW TO USE:
-// 1. Place this script inside the "Editor" folder.
-// 2. This class is used by GitService.cs and ArbitratorWindow.cs.
 
 using LibGit2Sharp;
 using UnityEngine.Scripting;
@@ -22,18 +18,22 @@ namespace Terra.Arbitrator.Services
         public string FilePath { get; private set; }
         public string OldFilePath { get; private set; }
         public ChangeKind Status { get; private set; }
-        
-        /// <summary>
-        /// Represents whether the user has checked the box for this file in the UI.
-        /// </summary>
         public bool IsSelectedForCommit { get; set; }
+        public ConflictResolution Resolution { get; set; } = ConflictResolution.None;
 
         public GitChange(string newPath, string oldPath, ChangeKind status)
         {
             FilePath = newPath;
             OldFilePath = oldPath;
             Status = status;
-            IsSelectedForCommit = true; // Default to select
+            IsSelectedForCommit = true;
+        }
+
+        public enum ConflictResolution
+        {
+            None,
+            Mine,
+            Theirs
         }
     }
 }

+ 56 - 0
Assets/Better Git/Arbitrator/Editor/Services/GitExecutors.cs

@@ -544,6 +544,62 @@ namespace Terra.Arbitrator.Services
             }
         }
         
+        public static async void PullAndOverwriteExecutor(Action<string> resolve, Action<Exception> reject, List<GitChange> resolutions)
+        {
+            var tempFiles = new Dictionary<string, string>();
+            var log = new StringBuilder();
+            try
+            {
+                foreach (var resolution in resolutions.Where(r => r.Resolution == GitChange.ConflictResolution.Mine))
+                {
+                    var fullPath = Path.Combine(ProjectRoot, resolution.FilePath);
+                    var tempPath = Path.GetTempFileName();
+                    File.Copy(fullPath, tempPath, true);
+                    tempFiles[resolution.FilePath] = tempPath;
+                }
+
+                using (var repo = new Repository(ProjectRoot))
+                {
+                    var filesToReset = resolutions.Where(r => r.Resolution != GitChange.ConflictResolution.None).Select(r => r.FilePath).ToArray();
+                    if(filesToReset.Length > 0)
+                    {
+                        repo.CheckoutPaths(repo.Head.Tip.Sha, filesToReset, new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force });
+                    }
+                }
+
+                await GitCommand.RunGitAsync(log, new[] { "pull", "--no-rebase" });
+
+                foreach (var entry in tempFiles)
+                {
+                    var finalPath = Path.Combine(ProjectRoot, entry.Key);
+                    File.Copy(entry.Value, finalPath, true);
+                    await GitCommand.RunGitAsync(log, new[] { "add", entry.Key });
+                }
+
+                var unresolvedFiles = resolutions.Where(r => r.Resolution == GitChange.ConflictResolution.None).ToList();
+                if (unresolvedFiles.Any())
+                {
+                    var fileList = string.Join(", ", unresolvedFiles.Select(f => f.FilePath));
+                    resolve($"Pull completed with unresolved conflicts in: {fileList}. Please resolve them manually.");
+                }
+                else
+                {
+                    resolve("Pull successful. Your chosen local changes have been preserved.");
+                }
+            }
+            catch (Exception ex)
+            {
+                reject(ex);
+            }
+            finally
+            {
+                foreach (var tempFile in tempFiles.Values.Where(File.Exists))
+                {
+                    File.Delete(tempFile);
+                }
+            }
+        }
+        
         public static async void LaunchMergeToolExecutor(Action<string> resolve, Action<Exception> reject, GitChange change)
         {
             try

+ 8 - 0
Assets/Better Git/Arbitrator/Editor/Services/GitService.cs

@@ -117,6 +117,14 @@ namespace Terra.Arbitrator.Services
         {
             return new Promise<string>(GitExecutors.ForcePullExecutor);
         }
+
+        /// <summary>
+        /// Performs a pull operation, intelligently handling conflicts based on user choices.
+        /// </summary>
+        public static IPromise<string> PullAndOverwrite(List<GitChange> resolutions)
+        {
+            return new Promise<string>((resolve, reject) => GitExecutors.PullAndOverwriteExecutor(resolve, reject, resolutions));
+        }
         
         /// <summary>
         /// Launches an external merge tool for a conflicted file.