Browse Source

Sujith :) ->
1. Pending changes - Added reset all

sujith 1 month ago
parent
commit
856cf8e3fb

+ 39 - 1
Assets/Arbitrator/Editor/GUI/ArbitratorWindow.cs

@@ -144,6 +144,11 @@ namespace Terra.Arbitrator.GUI
                 {
                     SetAllSelection(false);
                 }
+                if (GUILayout.Button(new GUIContent("Reset All", EditorGUIUtility.IconContent("d_TreeEditor.Trash").image, "Discard ALL local changes."), EditorStyles.toolbarButton, GUILayout.Width(100)))
+                {
+                    // We use delayCall to avoid GUI layout issues from the dialog.
+                    EditorApplication.delayCall += HandleResetAll;
+                }
             }
             
             EditorGUI.EndDisabledGroup();
@@ -279,6 +284,39 @@ namespace Terra.Arbitrator.GUI
             EditorApplication.delayCall += BetterGitStatePersistence.ContinueInterruptedReset;
         }
         
+        private void HandleResetAll()
+        {
+            if (_changes == null || _changes.Count == 0)
+            {
+                EditorUtility.DisplayDialog("No Changes", "There are no local changes to reset.", "OK");
+                return;
+            }
+
+            var userConfirmed = EditorUtility.DisplayDialog(
+                "Confirm Reset All",
+                "Are you sure you want to discard ALL local changes (modified, added, and untracked files)?\n\nThis action cannot be undone.",
+                "Yes, Discard Everything",
+                "Cancel");
+
+            if (!userConfirmed) return;
+
+            _isLoading = true;
+            _loadingMessage = "Discarding all local changes...";
+            ClearMessages();
+            Repaint();
+
+            GitService.ResetAllChanges()
+                .Then(successMessage => {
+                    _infoMessage = successMessage;
+                    HandleCompare(); // Refresh the view to confirm everything is clean
+                })
+                .Catch(ex => {
+                    _errorMessage = $"Reset All Failed: {ex.Message}";
+                    _isLoading = false;
+                    Repaint();
+                });
+        }
+        
         private void HandleForcePull()
         {
             _isLoading = true;
@@ -318,10 +356,10 @@ namespace Terra.Arbitrator.GUI
 
             GitService.CommitAndPush(selectedFiles, _commitMessage, username, email)
                 .Then(successMessage => {
-                    _infoMessage = successMessage;
                     _commitMessage = ""; // Clear message on success
                     _changes = null; // Clear the list, forcing a refresh
                     HandleCompare(); // Automatically refresh to confirm
+                    EditorUtility.DisplayDialog("Commit and Push Complete", successMessage, "OK");
                 })
                 .Catch(ex => {
                     _errorMessage = $"Push Failed: {ex.Message}";

+ 125 - 0
Assets/Arbitrator/Editor/GUI/ConflictResolutionWindow.cs

@@ -0,0 +1,125 @@
+// Copyright (c) 2025 TerraByte Inc.
+//
+// A modal editor window that displays pull conflicts and allows the user
+// to select files to reset before proceeding.
+
+using System;
+using System.Linq;
+using UnityEditor;
+using UnityEngine;
+using Terra.Arbitrator.Services;
+using System.Collections.Generic;
+
+namespace Terra.Arbitrator.GUI
+{
+    public class ConflictResolutionWindow : EditorWindow
+    {
+        private List<string> _conflictingFiles;
+        private List<bool> _filesToReset;
+        private Vector2 _scrollPosition;
+        private Action<List<string>> _onCloseCallback;
+        private bool _callbackInvoked;
+
+        /// <summary>
+        /// Shows a modal window to display pull conflicts and get user action.
+        /// </summary>
+        /// <param name="conflictingFiles">The list of files that have conflicts.</param>
+        /// <param name="onCloseCallback">A callback that provides the list of files the user selected to reset. If the user cancels, the list will be null.</param>
+        public static void ShowWindow(List<string> conflictingFiles, Action<List<string>> onCloseCallback)
+        {
+            var window = GetWindow<ConflictResolutionWindow>(true, "Pull Conflicts Detected", true);
+            window.minSize = new Vector2(600, 400);
+            window._conflictingFiles = conflictingFiles;
+            window._filesToReset = new List<bool>(new bool[conflictingFiles.Count]); // Initialize all to false
+            window._onCloseCallback = onCloseCallback;
+            window._callbackInvoked = false;
+            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);
+
+            _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, EditorStyles.helpBox);
+            for (var i = 0; i < _conflictingFiles.Count; i++)
+            {
+                EditorGUILayout.BeginHorizontal();
+                _filesToReset[i] = EditorGUILayout.Toggle(_filesToReset[i], GUILayout.Width(20));
+                EditorGUILayout.LabelField(_conflictingFiles[i]);
+                if (GUILayout.Button("Local Diff", GUILayout.Width(100)))
+                {
+                    // Find the GitChange object to pass to the diff service.
+                    var change = GitService.GetChangeForFile(_conflictingFiles[i]);
+                    if (change != null)
+                    {
+                        GitService.LaunchExternalDiff(change);
+                    }
+                    else
+                    {
+                        Debug.LogWarning($"Could not get status for {_conflictingFiles[i]} to launch diff.");
+                    }
+                }
+                EditorGUILayout.EndHorizontal();
+            }
+            EditorGUILayout.EndScrollView();
+
+            EditorGUILayout.Space();
+
+            // --- Action Buttons ---
+            DrawActionButtons();
+        }
+
+        private void DrawActionButtons()
+        {
+            var selectedCount = _filesToReset.Count(selected => selected);
+            var canReset = selectedCount > 0;
+
+            EditorGUILayout.BeginHorizontal();
+            GUILayout.FlexibleSpace();
+
+            // Reset Button
+            EditorGUI.BeginDisabledGroup(!canReset);
+            if (GUILayout.Button($"Reset {selectedCount} Selected File(s)", GUILayout.Height(30), GUILayout.Width(200)))
+            {
+                var filesToResetPaths = new List<string>();
+                for (var i = 0; i < _conflictingFiles.Count; i++)
+                {
+                    if (_filesToReset[i])
+                    {
+                        filesToResetPaths.Add(_conflictingFiles[i]);
+                    }
+                }
+                _callbackInvoked = true;
+                _onCloseCallback?.Invoke(filesToResetPaths);
+                Close();
+            }
+            EditorGUI.EndDisabledGroup();
+
+            if (GUILayout.Button(new GUIContent("Pull Anyway", "This will perform the pull, leaving merge conflicts in your local files for you to resolve."), GUILayout.Height(30)))
+            {
+                // Signal "Pull Anyway" by invoking the callback with an empty, non-null list.
+                _callbackInvoked = true;
+                _onCloseCallback?.Invoke(new List<string>());
+                Close();
+            }
+            
+            // Cancel Button
+            if (GUILayout.Button("Cancel", GUILayout.Height(30)))
+            {
+                Close();
+            }
+
+            EditorGUILayout.EndHorizontal();
+        }
+
+        private void OnDestroy()
+        {
+            if (!_callbackInvoked)
+            {
+                _onCloseCallback?.Invoke(null);
+            }
+        }
+    }
+}

+ 36 - 0
Assets/Arbitrator/Editor/Services/GitService.cs

@@ -81,6 +81,14 @@ namespace Terra.Arbitrator.Services
             return new Promise<bool>(UnstageAllFilesIfSafeExecutor);
         }
         
+        /// <summary>
+        /// Creates a promise to discard all local changes (tracked and untracked).
+        /// </summary>
+        public static IPromise<string> ResetAllChanges()
+        {
+            return new Promise<string>(ResetAllChangesExecutor);
+        }
+        
         /// <summary>
         /// Synchronous helper to get a GitChange object for a single file.
         /// Needed by the static persistence script which cannot easily use promises.
@@ -703,6 +711,34 @@ namespace Terra.Arbitrator.Services
             }
         }
         
+        /// <summary>
+        /// Executor for ResetAllChanges. Discards all local changes.
+        /// </summary>
+        private static async void ResetAllChangesExecutor(Action<string> resolve, Action<Exception> reject)
+        {
+            try
+            {
+                var projectRoot = Directory.GetParent(Application.dataPath)?.FullName;
+                if (projectRoot == null)
+                {
+                    reject(new Exception("Could not find project root."));
+                    return;
+                }
+
+                // 1. Discard all changes to tracked files
+                await ExecuteGitCommandAsync("reset --hard HEAD", projectRoot, null);
+
+                // 2. Remove all untracked files and directories
+                await ExecuteGitCommandAsync("clean -fd", projectRoot, null);
+
+                resolve("Successfully discarded all local changes.");
+            }
+            catch (Exception ex)
+            {
+                reject(ex);
+            }
+        }
+        
         /// <summary>
         /// Searches for an executable in common macOS PATH directories.
         /// </summary>

+ 22 - 0
Assets/Arbitrator/Editor/Settings/PullAnalysisRequest.cs

@@ -0,0 +1,22 @@
+// Copyright (c) 2025 TerraByte Inc.
+//
+// A data container for the result of a pre-pull conflict analysis.
+// It indicates if conflicts were found and which files are involved.
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Terra.Arbitrator.Settings
+{
+    public class PullAnalysisResult
+    {
+        public bool HasConflicts { get; private set; }
+        public List<string> ConflictingFiles { get; private set; }
+
+        public PullAnalysisResult(List<string> conflictingFiles)
+        {
+            ConflictingFiles = conflictingFiles ?? new List<string>();
+            HasConflicts = ConflictingFiles.Any();
+        }
+    }
+}