From afec12d40756006c20fc9dcac08bce52c6d82d8c Mon Sep 17 00:00:00 2001 From: Sam Christiansen Date: Thu, 8 Nov 2018 15:25:10 -0800 Subject: [PATCH 01/19] File History --- src/GitHub.Api/Application/ApiClient.cs | 4 +- src/GitHub.Api/Application/IApiClient.cs | 2 +- src/GitHub.Api/Application/Organization.cs | 4 +- src/GitHub.Api/Git/GitClient.cs | 34 +++ src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs | 23 +- src/GitHub.Api/Git/Tasks/GitLogTask.cs | 16 +- .../Editor/GitHub.Unity/UI/BaseWindow.cs | 2 +- .../Editor/GitHub.Unity/UI/ContextMenu.cs | 36 +++ .../GitHub.Unity/UI/FileHistoryWindow.cs | 244 ++++++++++++++++++ .../Editor/GitHub.Unity/UI/HistoryView.cs | 2 +- .../Editor/GitHub.Unity/UI/PopupWindow.cs | 2 +- 11 files changed, 359 insertions(+), 10 deletions(-) create mode 100644 src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs create mode 100644 src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs diff --git a/src/GitHub.Api/Application/ApiClient.cs b/src/GitHub.Api/Application/ApiClient.cs index 01d189def..51d13fe38 100644 --- a/src/GitHub.Api/Application/ApiClient.cs +++ b/src/GitHub.Api/Application/ApiClient.cs @@ -283,13 +283,13 @@ private GitHubUser GetValidatedGitHubUser(Connection keychainConnection, IKeycha } } - class GitHubUser + public class GitHubUser { public string Name { get; set; } public string Login { get; set; } } - class GitHubRepository + public class GitHubRepository { public string Name { get; set; } public string CloneUrl { get; set; } diff --git a/src/GitHub.Api/Application/IApiClient.cs b/src/GitHub.Api/Application/IApiClient.cs index 650595ce2..1bd5fc070 100644 --- a/src/GitHub.Api/Application/IApiClient.cs +++ b/src/GitHub.Api/Application/IApiClient.cs @@ -2,7 +2,7 @@ namespace GitHub.Unity { - interface IApiClient + public interface IApiClient { HostAddress HostAddress { get; } UriString OriginalUrl { get; } diff --git a/src/GitHub.Api/Application/Organization.cs b/src/GitHub.Api/Application/Organization.cs index e78849dd6..8deea7d99 100644 --- a/src/GitHub.Api/Application/Organization.cs +++ b/src/GitHub.Api/Application/Organization.cs @@ -1,8 +1,8 @@ namespace GitHub.Unity { - class Organization + public class Organization { public string Name { get; set; } public string Login { get; set; } } -} \ No newline at end of file +} diff --git a/src/GitHub.Api/Git/GitClient.cs b/src/GitHub.Api/Git/GitClient.cs index 5e454f6fa..d0e97787c 100644 --- a/src/GitHub.Api/Git/GitClient.cs +++ b/src/GitHub.Api/Git/GitClient.cs @@ -199,6 +199,15 @@ public interface IGitClient /// String output of git command ITask DiscardAll(IOutputProcessor processor = null); + /// + /// Executes at least one `git checkout` command to checkout files at the given changeset + /// + /// The md5 of the changeset + /// The files to check out + /// A custom output processor instance + /// String output of git command + ITask CheckoutVersion(string changeset, IEnumerable files, IOutputProcessor processor = null); + /// /// Executes at least one `git reset HEAD` command to remove files from the git index. /// @@ -241,6 +250,13 @@ public interface IGitClient /// of output ITask> Log(BaseOutputListProcessor processor = null); + /// + /// Executes `git log -- ` to get the history of a specific file. + /// + /// A custom output processor instance + /// of output + ITask> LogFile(NPath file, BaseOutputListProcessor processor = null); + /// /// Executes `git --version` to get the git version. /// @@ -332,6 +348,17 @@ public ITask> Log(BaseOutputListProcessor process .Then((success, list) => success ? list : new List()); } + /// + public ITask> LogFile(NPath file, BaseOutputListProcessor processor = null) + { + return new GitLogTask(file, new GitObjectFactory(environment), cancellationToken, processor) + .Configure(processManager) + .Catch(exception => exception is ProcessException && + exception.Message.StartsWith("fatal: your current branch") && + exception.Message.EndsWith("does not have any commits yet")) + .Then((success, list) => success ? list : new List()); + } + /// public ITask Version(IOutputProcessor processor = null) { @@ -549,6 +576,13 @@ public ITask DiscardAll(IOutputProcessor processor = null) .Configure(processManager); } + /// + public ITask CheckoutVersion(string changeset, IEnumerable files, IOutputProcessor processor = null) + { + return new GitCheckoutTask(changeset, files, cancellationToken, processor) + .Configure(processManager); + } + /// public ITask Remove(IList files, IOutputProcessor processor = null) diff --git a/src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs b/src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs index ea2e9f4d3..401281e22 100644 --- a/src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs +++ b/src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs @@ -30,8 +30,29 @@ public GitCheckoutTask(CancellationToken token, arguments = "checkout -- ."; } + public GitCheckoutTask( + string changeset, + IEnumerable files, + CancellationToken token, + IOutputProcessor processor = null) : base(token, processor ?? new SimpleOutputProcessor()) + { + Guard.ArgumentNotNull(files, "files"); + Name = TaskName; + + arguments = "checkout "; + arguments += changeset; + arguments += " -- "; + + foreach (var file in files) + { + arguments += " \"" + file.ToNPath().ToString(SlashMode.Forward) + "\""; + } + + Message = "Checking out files at rev " + changeset.Substring(0, 7); + } + public override string ProcessArguments { get { return arguments; } } public override TaskAffinity Affinity { get { return TaskAffinity.Exclusive; } } - public override string Message { get; set; } = "Checking out branch..."; + public override string Message { get; set; } = "Checking out files..."; } } \ No newline at end of file diff --git a/src/GitHub.Api/Git/Tasks/GitLogTask.cs b/src/GitHub.Api/Git/Tasks/GitLogTask.cs index 955521a61..a55e72e5c 100644 --- a/src/GitHub.Api/Git/Tasks/GitLogTask.cs +++ b/src/GitHub.Api/Git/Tasks/GitLogTask.cs @@ -5,17 +5,31 @@ namespace GitHub.Unity class GitLogTask : ProcessTaskWithListOutput { private const string TaskName = "git log"; + private const string baseArguments = @"-c i18n.logoutputencoding=utf8 -c core.quotepath=false log --pretty=format:""%H%n%P%n%aN%n%aE%n%aI%n%cN%n%cE%n%cI%n%B---GHUBODYEND---"" --name-status"; + private readonly string arguments; public GitLogTask(IGitObjectFactory gitObjectFactory, CancellationToken token, BaseOutputListProcessor processor = null) : base(token, processor ?? new LogEntryOutputProcessor(gitObjectFactory)) { Name = TaskName; + arguments = baseArguments; + } + + public GitLogTask(NPath file, + IGitObjectFactory gitObjectFactory, + CancellationToken token, BaseOutputListProcessor processor = null) + : base(token, processor ?? new LogEntryOutputProcessor(gitObjectFactory)) + { + Name = TaskName; + arguments = baseArguments; + arguments += " -- "; + arguments += " \"" + file.ToString(SlashMode.Forward) + "\""; } public override string ProcessArguments { - get { return @"-c i18n.logoutputencoding=utf8 -c core.quotepath=false log --pretty=format:""%H%n%P%n%aN%n%aE%n%aI%n%cN%n%cE%n%cI%n%B---GHUBODYEND---"" --name-status"; } + get { return arguments; } } public override string Message { get; set; } = "Loading the history..."; } diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/BaseWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/BaseWindow.cs index fa21bebf3..134af3c2a 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/BaseWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/BaseWindow.cs @@ -7,7 +7,7 @@ namespace GitHub.Unity { - abstract class BaseWindow : EditorWindow, IView + public abstract class BaseWindow : EditorWindow, IView { [NonSerialized] private bool initialized = false; [NonSerialized] private IUser cachedUser; diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs new file mode 100644 index 000000000..95872fb45 --- /dev/null +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs @@ -0,0 +1,36 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace GitHub.Unity +{ + public class ContextMenu + { + [MenuItem("Assets/Git/History", false)] + private static void GitFileHistory() + { + if (Selection.assetGUIDs != null) + { + int maxWindowsToOpen = 10; + int windowsOpened = 0; + foreach(var guid in Selection.assetGUIDs) + { + var assetPath = AssetDatabase.GUIDToAssetPath(guid); + FileHistoryWindow.OpenWindow(assetPath); + windowsOpened++; + if (windowsOpened >= maxWindowsToOpen) + { + break; + } + } + } + } + + [MenuItem("Assets/Git/History", true)] + private static bool GitFileHistoryValidation() + { + return Selection.assetGUIDs != null && Selection.assetGUIDs.Length > 0; + } + } +} \ No newline at end of file diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs new file mode 100644 index 000000000..bf4d6989f --- /dev/null +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -0,0 +1,244 @@ +using System.Collections.Generic; +using System.Linq; +using System; +using UnityEngine; +using UnityEditor; + +namespace GitHub.Unity +{ + public class FileHistoryWindow : BaseWindow + { + [SerializeField] private string assetPath; + [SerializeField] private List history; + [SerializeField] private Vector2 scroll; + [SerializeField] private Vector2 detailsScroll; + [NonSerialized] private bool busy; + [SerializeField] private HistoryControl historyControl; + [SerializeField] private GitLogEntry selectedEntry = GitLogEntry.Default; + [SerializeField] private ChangesTree treeChanges = new ChangesTree { IsSelectable = false, DisplayRootNode = false }; + + public static FileHistoryWindow OpenWindow(string assetPath) + { + var popupWindow = CreateInstance(); + + popupWindow.titleContent = new GUIContent(assetPath + " History"); + popupWindow.Open(assetPath); + + popupWindow.Show(); + + return popupWindow; + } + + public override bool IsBusy { get { return this.busy; } } + + public void Open(string assetPath) + { + this.assetPath = assetPath; + + this.RefreshLog(); + } + + public void RefreshLog() + { + var path = Application.dataPath.ToNPath().Parent.Combine(assetPath.ToNPath()); + this.busy = true; + this.GitClient.LogFile(path).ThenInUI((success, logEntries) => { + this.history = logEntries; + this.BuildHistoryControl(); + this.Repaint(); + this.busy = false; + }).Start(); + } + + private void CheckoutVersion(string commitID) + { + this.busy = true; + this.GitClient.CheckoutVersion(commitID, new string[]{assetPath}).ThenInUI((success, result) => { + AssetDatabase.Refresh(); + this.busy = false; + }).Start(); + } + + private void Checkout() + { + // TODO: This is a destructive, irreversible operation; we should prompt user if + // there are any changes to the file + this.CheckoutVersion(this.selectedEntry.CommitID); + } + + public override void OnUI() + { + // TODO: + // - should handle case where the file is outside of the repository (handle exceptional cases) + // - should display a spinner while history is still loading... + base.OnUI(); + GUILayout.BeginHorizontal(Styles.HeaderStyle); + { + GUILayout.Label("GIT File History for: ", Styles.BoldLabel); + if (HyperlinkLabel(this.assetPath)) + { + var asset = AssetDatabase.LoadMainAssetAtPath(this.assetPath); + Selection.activeObject = asset; + EditorGUIUtility.PingObject(asset); + } + GUILayout.FlexibleSpace(); + } + GUILayout.EndHorizontal(); + + if (historyControl != null) + { + var rect = GUILayoutUtility.GetLastRect(); + var historyControlRect = new Rect(0f, 0f, Position.width, Position.height - rect.height); + + var requiresRepaint = historyControl.Render(historyControlRect, + entry => { + selectedEntry = entry; + BuildTree(); + }, + entry => { }, entry => { + GenericMenu menu = new GenericMenu(); + menu.AddItem(new GUIContent("Checkout version " + entry.ShortID), false, Checkout); + menu.ShowAsContext(); + }); + + if (requiresRepaint) + Redraw(); + } + + // DrawDetails is maybe irrelevant? Would be a nice place to put the short id perhaps? + DrawDetails(); + } + + private bool HyperlinkLabel(string label) + { + bool returnValue = false; + if (GUILayout.Button(label, HyperlinkStyle)) + { + returnValue = true; + } + var rect = GUILayoutUtility.GetLastRect(); + var size = HyperlinkStyle.CalcSize(new GUIContent(label)); + rect.width = size.x; + EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link); + return returnValue; + } + + private void BuildHistoryControl() + { + if (historyControl == null) + { + historyControl = new HistoryControl(); + } + + historyControl.Load(0, this.history); + } + + private const string CommitDetailsTitle = "Commit details"; + private const string ClearSelectionButton = "×"; + + private void DrawDetails() + { + if (!selectedEntry.Equals(GitLogEntry.Default)) + { + // Top bar for scrolling to selection or clearing it + GUILayout.BeginHorizontal(EditorStyles.toolbar); + { + if (GUILayout.Button(CommitDetailsTitle, Styles.ToolbarButtonStyle)) + { + historyControl.ScrollTo(historyControl.SelectedIndex); + } + if (GUILayout.Button(ClearSelectionButton, Styles.ToolbarButtonStyle, GUILayout.ExpandWidth(false))) + { + selectedEntry = GitLogEntry.Default; + historyControl.SelectedIndex = -1; + } + } + GUILayout.EndHorizontal(); + + // Log entry details - including changeset tree (if any changes are found) + detailsScroll = GUILayout.BeginScrollView(detailsScroll, GUILayout.Height(250)); + { + HistoryDetailsEntry(selectedEntry); + + GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); + GUILayout.Label("Files changed", EditorStyles.boldLabel); + GUILayout.Space(-5); + + var rect = GUILayoutUtility.GetLastRect(); + GUILayout.BeginHorizontal(Styles.HistoryFileTreeBoxStyle); + GUILayout.BeginVertical(); + { + var borderLeft = Styles.Label.margin.left; + var treeControlRect = new Rect(rect.x + borderLeft, rect.y, Position.width - borderLeft * 2, Position.height - rect.height + Styles.CommitAreaPadding); + var treeRect = new Rect(0f, 0f, 0f, 0f); + if (treeChanges != null) + { + treeChanges.FolderStyle = Styles.Foldout; + treeChanges.TreeNodeStyle = Styles.TreeNode; + treeChanges.ActiveTreeNodeStyle = Styles.ActiveTreeNode; + treeChanges.FocusedTreeNodeStyle = Styles.FocusedTreeNode; + treeChanges.FocusedActiveTreeNodeStyle = Styles.FocusedActiveTreeNode; + + treeRect = treeChanges.Render(treeControlRect, detailsScroll, + node => { + }, + node => { + }, + node => { + }); + + if (treeChanges.RequiresRepaint) + Redraw(); + } + + GUILayout.Space(treeRect.y - treeControlRect.y); + } + GUILayout.EndVertical(); + GUILayout.EndHorizontal(); + + GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); + } + GUILayout.EndScrollView(); + } + } + + private void HistoryDetailsEntry(GitLogEntry entry) + { + GUILayout.BeginVertical(Styles.HeaderBoxStyle); + GUILayout.Label(entry.Summary, Styles.HistoryDetailsTitleStyle); + + GUILayout.Space(-5); + + GUILayout.BeginHorizontal(); + GUILayout.Label(entry.PrettyTimeString, Styles.HistoryDetailsMetaInfoStyle); + GUILayout.Label(entry.AuthorName, Styles.HistoryDetailsMetaInfoStyle); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + GUILayout.Space(3); + GUILayout.EndVertical(); + } + + private void BuildTree() + { + treeChanges.PathSeparator = Environment.FileSystem.DirectorySeparatorChar.ToString(); + treeChanges.Load(selectedEntry.changes.Select(entry => new GitStatusEntryTreeData(entry))); + Redraw(); + } + + protected static GUIStyle hyperlinkStyle = null; + + public static GUIStyle HyperlinkStyle + { + get + { + if (hyperlinkStyle == null) + { + hyperlinkStyle = new GUIStyle(EditorStyles.wordWrappedLabel); + hyperlinkStyle.normal.textColor = new Color(95.0f/255.0f, 170.0f/255.0f, 247.0f/255.0f); + } + return hyperlinkStyle; + } + } + } +} \ No newline at end of file diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs index 69b42e83e..f35423133 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs @@ -7,7 +7,7 @@ namespace GitHub.Unity { [Serializable] - class HistoryControl + public class HistoryControl { private const string HistoryEntryDetailFormat = "{0} {1}"; diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/PopupWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/PopupWindow.cs index d7da7cfbe..85fea7a02 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/PopupWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/PopupWindow.cs @@ -5,7 +5,7 @@ namespace GitHub.Unity { [Serializable] - class PopupWindow : BaseWindow + public class PopupWindow : BaseWindow { public enum PopupViewType { From f9f5202f716a46d8887a457618f540726710afe8 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Wed, 2 Jan 2019 08:48:55 -0500 Subject: [PATCH 02/19] Fixing build error --- src/GitHub.Api/Application/ApiClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitHub.Api/Application/ApiClient.cs b/src/GitHub.Api/Application/ApiClient.cs index a81a6f152..161540e41 100644 --- a/src/GitHub.Api/Application/ApiClient.cs +++ b/src/GitHub.Api/Application/ApiClient.cs @@ -469,14 +469,14 @@ private GitHubUser GetValidatedGitHubUser() } } - class GitHubHostMeta + public class GitHubHostMeta { public bool VerifiablePasswordAuthentication { get; set; } public string GithubServicesSha { get; set; } public string InstalledVersion { get; set; } } - class GitHubUser + public class GitHubUser { public string Name { get; set; } public string Login { get; set; } From f5bab7a101f73ef12c6f468503397788818c348e Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Wed, 2 Jan 2019 08:49:03 -0500 Subject: [PATCH 03/19] Nit pick text --- src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs b/src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs index 401281e22..d1d050b52 100644 --- a/src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs +++ b/src/GitHub.Api/Git/Tasks/GitCheckoutTask.cs @@ -48,11 +48,11 @@ public GitCheckoutTask( arguments += " \"" + file.ToNPath().ToString(SlashMode.Forward) + "\""; } - Message = "Checking out files at rev " + changeset.Substring(0, 7); - } + Message = "Checking out files at rev " + changeset.Substring(0, 7); + } public override string ProcessArguments { get { return arguments; } } public override TaskAffinity Affinity { get { return TaskAffinity.Exclusive; } } public override string Message { get; set; } = "Checking out files..."; } -} \ No newline at end of file +} From 29b5142949a9a34a353d81533e89f89d32961f02 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Wed, 2 Jan 2019 10:09:07 -0500 Subject: [PATCH 04/19] Fixing project reference --- .../Assets/Editor/GitHub.Unity/GitHub.Unity.45.csproj | 2 ++ .../Assets/Editor/GitHub.Unity/GitHub.Unity.csproj | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.45.csproj b/src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.45.csproj index 7cf5bb05b..1bedc423f 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.45.csproj +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.45.csproj @@ -90,6 +90,8 @@ + + diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.csproj b/src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.csproj index ae6f39583..28ca2c0d4 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.csproj +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.csproj @@ -77,6 +77,8 @@ + + From dd5218d4ef41884582e2cbe2272470e10efc264e Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Mon, 14 Jan 2019 09:34:23 -0500 Subject: [PATCH 05/19] Adding a context menu --- .../Editor/GitHub.Unity/UI/ContextMenu.cs | 2 +- .../Editor/GitHub.Unity/UI/HistoryView.cs | 23 ++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs index 95872fb45..2ca5eb783 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs @@ -33,4 +33,4 @@ private static bool GitFileHistoryValidation() return Selection.assetGUIDs != null && Selection.assetGUIDs.Length > 0; } } -} \ No newline at end of file +} diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs index f35423133..afef175e8 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs @@ -320,7 +320,7 @@ class HistoryView : Subview [SerializeField] private int statusAhead; - [SerializeField] private ChangesTree treeChanges = new ChangesTree { IsSelectable = false, DisplayRootNode = false }; + [SerializeField] private ChangesTree treeChanges = new ChangesTree { DisplayRootNode = false }; [SerializeField] private CacheUpdateEvent lastLogChangedEvent; [SerializeField] private CacheUpdateEvent lastTrackingStatusChangedEvent; @@ -435,11 +435,13 @@ public override void OnGUI() treeChanges.FocusedActiveTreeNodeStyle = Styles.FocusedActiveTreeNode; treeRect = treeChanges.Render(treeControlRect, detailsScroll, - node => { }, - node => { - }, - node => { - }); + singleClick: node => { }, + doubleClick: node => { }, + rightClick: node => { + var menu = CreateChangesTreeContextMenu(node); + menu.ShowAsContext(); + } + ); if (treeChanges.RequiresRepaint) Redraw(); @@ -588,5 +590,14 @@ private void BuildTree() treeChanges.Load(selectedEntry.changes.Select(entry => new GitStatusEntryTreeData(entry))); Redraw(); } + + private GenericMenu CreateChangesTreeContextMenu(ChangesTreeNode node) + { + var genericMenu = new GenericMenu(); + + genericMenu.AddItem(new GUIContent("Show History"), false, () => { }); + + return genericMenu; + } } } From 5f566c4c1a77c54c94bccbcadfd2ed2e1a2b2860 Mon Sep 17 00:00:00 2001 From: Sam Christiansen Date: Mon, 14 Jan 2019 12:16:07 -0800 Subject: [PATCH 06/19] Prefer IList vs IEnumerable --- src/GitHub.Api/Git/GitClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitHub.Api/Git/GitClient.cs b/src/GitHub.Api/Git/GitClient.cs index 6facb03aa..6b77866cb 100644 --- a/src/GitHub.Api/Git/GitClient.cs +++ b/src/GitHub.Api/Git/GitClient.cs @@ -215,7 +215,7 @@ public interface IGitClient /// The files to check out /// A custom output processor instance /// String output of git command - ITask CheckoutVersion(string changeset, IEnumerable files, IOutputProcessor processor = null); + ITask CheckoutVersion(string changeset, IList files, IOutputProcessor processor = null); /// /// Executes at least one `git reset HEAD` command to remove files from the git index. @@ -593,7 +593,7 @@ public ITask DiscardAll(IOutputProcessor processor = null) } /// - public ITask CheckoutVersion(string changeset, IEnumerable files, IOutputProcessor processor = null) + public ITask CheckoutVersion(string changeset, IList files, IOutputProcessor processor = null) { return new GitCheckoutTask(changeset, files, cancellationToken, processor) .Configure(processManager); From 6e8ed9a712023b3fd749b7b90e72052f6eface1c Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Tue, 15 Jan 2019 10:37:09 -0500 Subject: [PATCH 07/19] Adding generalized FileHistoryWindow and HistoryBase --- .../Assets/Editor/GitHub.Unity/Misc/Styles.cs | 4 +- .../Editor/GitHub.Unity/UI/ContextMenu.cs | 2 +- .../GitHub.Unity/UI/FileHistoryWindow.cs | 281 +++++---------- .../Editor/GitHub.Unity/UI/HistoryView.cs | 335 ++++++++++++------ 4 files changed, 323 insertions(+), 299 deletions(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/Misc/Styles.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/Misc/Styles.cs index 5a72b41ad..64d851201 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/Misc/Styles.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/Misc/Styles.cs @@ -472,14 +472,14 @@ public static GUIStyle ToolbarButtonStyle } } - public static GUIStyle HistoryLockStyle + public static GUIStyle LockButtonStyle { get { if (historyLockStyle == null) { historyLockStyle = new GUIStyle(GUI.skin.FindStyle("IN LockButton")); - historyLockStyle.name = "HistoryLockStyle"; + historyLockStyle.name = "LockStyle"; } historyLockStyle.margin = new RectOffset(3, 3, 2, 2); return historyLockStyle; diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs index 2ca5eb783..4adfce9fd 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs @@ -17,7 +17,7 @@ private static void GitFileHistory() foreach(var guid in Selection.assetGUIDs) { var assetPath = AssetDatabase.GUIDToAssetPath(guid); - FileHistoryWindow.OpenWindow(assetPath); + FileHistoryWindow.OpenWindow(EntryPoint.ApplicationManager, assetPath); windowsOpened++; if (windowsOpened >= maxWindowsToOpen) { diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index bf4d6989f..73f05dba4 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -1,244 +1,149 @@ -using System.Collections.Generic; -using System.Linq; -using System; -using UnityEngine; +using System; using UnityEditor; +using UnityEngine; namespace GitHub.Unity { public class FileHistoryWindow : BaseWindow { + private const string Title = "File History"; + + [NonSerialized] private bool firstOnGUI = true; + + [SerializeField] private bool locked; [SerializeField] private string assetPath; - [SerializeField] private List history; - [SerializeField] private Vector2 scroll; - [SerializeField] private Vector2 detailsScroll; - [NonSerialized] private bool busy; - [SerializeField] private HistoryControl historyControl; - [SerializeField] private GitLogEntry selectedEntry = GitLogEntry.Default; - [SerializeField] private ChangesTree treeChanges = new ChangesTree { IsSelectable = false, DisplayRootNode = false }; + [SerializeField] private FileHistoryView fileHistoryView = new FileHistoryView(); - public static FileHistoryWindow OpenWindow(string assetPath) + public static FileHistoryWindow OpenWindow(IApplicationManager applicationManager, string assetPath) { - var popupWindow = CreateInstance(); + var fileHistoryWindow = CreateInstance(); + fileHistoryWindow.InitializeWindow(applicationManager); - popupWindow.titleContent = new GUIContent(assetPath + " History"); - popupWindow.Open(assetPath); + fileHistoryWindow.Open(assetPath); + fileHistoryWindow.Show(); - popupWindow.Show(); + return fileHistoryWindow; + } - return popupWindow; + public void Open(string path) + { + assetPath = path; + fileHistoryView.SetPath(path); } - public override bool IsBusy { get { return this.busy; } } + public override void Initialize(IApplicationManager applicationManager) + { + base.Initialize(applicationManager); - public void Open(string assetPath) + fileHistoryView.InitializeView(this); + } + + public override bool IsBusy { - this.assetPath = assetPath; + get { return false; } + } - this.RefreshLog(); + public override void OnEnable() + { + base.OnEnable(); + + if (fileHistoryView != null) + fileHistoryView.OnEnable(); } - public void RefreshLog() + public override void OnDisable() { - var path = Application.dataPath.ToNPath().Parent.Combine(assetPath.ToNPath()); - this.busy = true; - this.GitClient.LogFile(path).ThenInUI((success, logEntries) => { - this.history = logEntries; - this.BuildHistoryControl(); - this.Repaint(); - this.busy = false; - }).Start(); + base.OnDisable(); + if (fileHistoryView != null) + fileHistoryView.OnDisable(); } - private void CheckoutVersion(string commitID) + public override void OnDataUpdate() { - this.busy = true; - this.GitClient.CheckoutVersion(commitID, new string[]{assetPath}).ThenInUI((success, result) => { - AssetDatabase.Refresh(); - this.busy = false; - }).Start(); + base.OnDataUpdate(); + MaybeUpdateData(); + + if (fileHistoryView != null) + fileHistoryView.OnDataUpdate(); } - private void Checkout() + public override void OnFocusChanged() { - // TODO: This is a destructive, irreversible operation; we should prompt user if - // there are any changes to the file - this.CheckoutVersion(this.selectedEntry.CommitID); + if (fileHistoryView != null) + fileHistoryView.OnFocusChanged(); } - public override void OnUI() + public override void OnRepositoryChanged(IRepository oldRepository) { - // TODO: - // - should handle case where the file is outside of the repository (handle exceptional cases) - // - should display a spinner while history is still loading... - base.OnUI(); - GUILayout.BeginHorizontal(Styles.HeaderStyle); + base.OnRepositoryChanged(oldRepository); + + DetachHandlers(oldRepository); + AttachHandlers(Repository); + + if (HasRepository) { - GUILayout.Label("GIT File History for: ", Styles.BoldLabel); - if (HyperlinkLabel(this.assetPath)) - { - var asset = AssetDatabase.LoadMainAssetAtPath(this.assetPath); - Selection.activeObject = asset; - EditorGUIUtility.PingObject(asset); - } - GUILayout.FlexibleSpace(); + } - GUILayout.EndHorizontal(); - - if (historyControl != null) + else { - var rect = GUILayoutUtility.GetLastRect(); - var historyControlRect = new Rect(0f, 0f, Position.width, Position.height - rect.height); - - var requiresRepaint = historyControl.Render(historyControlRect, - entry => { - selectedEntry = entry; - BuildTree(); - }, - entry => { }, entry => { - GenericMenu menu = new GenericMenu(); - menu.AddItem(new GUIContent("Checkout version " + entry.ShortID), false, Checkout); - menu.ShowAsContext(); - }); - - if (requiresRepaint) - Redraw(); + } + } - // DrawDetails is maybe irrelevant? Would be a nice place to put the short id perhaps? - DrawDetails(); + public override void OnSelectionChange() + { + base.OnSelectionChange(); + if (fileHistoryView != null) + fileHistoryView.OnSelectionChange(); } - private bool HyperlinkLabel(string label) + public override void Refresh() { - bool returnValue = false; - if (GUILayout.Button(label, HyperlinkStyle)) - { - returnValue = true; - } - var rect = GUILayoutUtility.GetLastRect(); - var size = HyperlinkStyle.CalcSize(new GUIContent(label)); - rect.width = size.x; - EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link); - return returnValue; + base.Refresh(); + if (fileHistoryView != null) + fileHistoryView.Refresh(); + Refresh(CacheType.GitLocks); + Redraw(); } - private void BuildHistoryControl() + public override void OnUI() { - if (historyControl == null) - { - historyControl = new HistoryControl(); - } + base.OnUI(); - historyControl.Load(0, this.history); + fileHistoryView.OnGUI(); } - private const string CommitDetailsTitle = "Commit details"; - private const string ClearSelectionButton = "×"; - - private void DrawDetails() + private void MaybeUpdateData() { - if (!selectedEntry.Equals(GitLogEntry.Default)) + if (firstOnGUI) { - // Top bar for scrolling to selection or clearing it - GUILayout.BeginHorizontal(EditorStyles.toolbar); - { - if (GUILayout.Button(CommitDetailsTitle, Styles.ToolbarButtonStyle)) - { - historyControl.ScrollTo(historyControl.SelectedIndex); - } - if (GUILayout.Button(ClearSelectionButton, Styles.ToolbarButtonStyle, GUILayout.ExpandWidth(false))) - { - selectedEntry = GitLogEntry.Default; - historyControl.SelectedIndex = -1; - } - } - GUILayout.EndHorizontal(); - - // Log entry details - including changeset tree (if any changes are found) - detailsScroll = GUILayout.BeginScrollView(detailsScroll, GUILayout.Height(250)); - { - HistoryDetailsEntry(selectedEntry); - - GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); - GUILayout.Label("Files changed", EditorStyles.boldLabel); - GUILayout.Space(-5); - - var rect = GUILayoutUtility.GetLastRect(); - GUILayout.BeginHorizontal(Styles.HistoryFileTreeBoxStyle); - GUILayout.BeginVertical(); - { - var borderLeft = Styles.Label.margin.left; - var treeControlRect = new Rect(rect.x + borderLeft, rect.y, Position.width - borderLeft * 2, Position.height - rect.height + Styles.CommitAreaPadding); - var treeRect = new Rect(0f, 0f, 0f, 0f); - if (treeChanges != null) - { - treeChanges.FolderStyle = Styles.Foldout; - treeChanges.TreeNodeStyle = Styles.TreeNode; - treeChanges.ActiveTreeNodeStyle = Styles.ActiveTreeNode; - treeChanges.FocusedTreeNodeStyle = Styles.FocusedTreeNode; - treeChanges.FocusedActiveTreeNodeStyle = Styles.FocusedActiveTreeNode; - - treeRect = treeChanges.Render(treeControlRect, detailsScroll, - node => { - }, - node => { - }, - node => { - }); - - if (treeChanges.RequiresRepaint) - Redraw(); - } - - GUILayout.Space(treeRect.y - treeControlRect.y); - } - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - - GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); - } - GUILayout.EndScrollView(); + titleContent = new GUIContent(Title, Styles.SmallLogo); } + firstOnGUI = false; } - private void HistoryDetailsEntry(GitLogEntry entry) + private void AttachHandlers(IRepository repository) { - GUILayout.BeginVertical(Styles.HeaderBoxStyle); - GUILayout.Label(entry.Summary, Styles.HistoryDetailsTitleStyle); - - GUILayout.Space(-5); - - GUILayout.BeginHorizontal(); - GUILayout.Label(entry.PrettyTimeString, Styles.HistoryDetailsMetaInfoStyle); - GUILayout.Label(entry.AuthorName, Styles.HistoryDetailsMetaInfoStyle); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - - GUILayout.Space(3); - GUILayout.EndVertical(); + if (repository == null) + return; } - private void BuildTree() + private void DetachHandlers(IRepository repository) { - treeChanges.PathSeparator = Environment.FileSystem.DirectorySeparatorChar.ToString(); - treeChanges.Load(selectedEntry.changes.Select(entry => new GitStatusEntryTreeData(entry))); - Redraw(); + if (repository == null) + return; } - protected static GUIStyle hyperlinkStyle = null; - - public static GUIStyle HyperlinkStyle + private void ShowButton(Rect rect) { - get - { - if (hyperlinkStyle == null) - { - hyperlinkStyle = new GUIStyle(EditorStyles.wordWrappedLabel); - hyperlinkStyle.normal.textColor = new Color(95.0f/255.0f, 170.0f/255.0f, 247.0f/255.0f); - } - return hyperlinkStyle; - } - } + EditorGUI.BeginChangeCheck(); + + locked = GUI.Toggle(rect, locked, GUIContent.none, Styles.LockButtonStyle); + + if (!EditorGUI.EndChangeCheck()) + return; + + this.OnSelectionChange(); + } } -} \ No newline at end of file +} diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs index afef175e8..6ee1a2cd7 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs @@ -302,83 +302,94 @@ public void ScrollTo(int index, float offset = 0f) } } - [Serializable] - class HistoryView : Subview + abstract class HistoryBase : Subview { - private const string CommitDetailsTitle = "Commit details"; - private const string ClearSelectionButton = "×"; - - [SerializeField] private bool currentLogHasUpdate; - [SerializeField] private bool currentTrackingStatusHasUpdate; - - [SerializeField] private HistoryControl historyControl; - [SerializeField] private GitLogEntry selectedEntry = GitLogEntry.Default; - - [SerializeField] private Vector2 detailsScroll; - - [SerializeField] private List logEntries = new List(); - - [SerializeField] private int statusAhead; + protected const string CommitDetailsTitle = "Commit details"; + protected const string ClearSelectionButton = "×"; - [SerializeField] private ChangesTree treeChanges = new ChangesTree { DisplayRootNode = false }; - - [SerializeField] private CacheUpdateEvent lastLogChangedEvent; - [SerializeField] private CacheUpdateEvent lastTrackingStatusChangedEvent; + protected abstract HistoryControl HistoryControl { get; set; } + protected abstract GitLogEntry SelectedEntry { get; set; } + protected abstract ChangesTree TreeChanges { get; set; } + protected abstract Vector2 DetailsScroll { get; set; } - public override void OnEnable() + protected void BuildHistoryControl(int loadAhead, List gitLogEntries) { - base.OnEnable(); - - if (treeChanges != null) + if (HistoryControl == null) { - treeChanges.ViewHasFocus = HasFocus; - treeChanges.UpdateIcons(Styles.FolderIcon); + HistoryControl = new HistoryControl(); } - AttachHandlers(Repository); - ValidateCachedData(Repository); + HistoryControl.Load(loadAhead, gitLogEntries); + if (!SelectedEntry.Equals(GitLogEntry.Default) + && SelectedEntry.CommitID != HistoryControl.SelectedGitLogEntry.CommitID) + { + SelectedEntry = GitLogEntry.Default; + } } - public override void OnDisable() + protected void BuildTree() { - base.OnDisable(); - DetachHandlers(Repository); + TreeChanges.PathSeparator = Environment.FileSystem.DirectorySeparatorChar.ToString(); + TreeChanges.Load(SelectedEntry.changes.Select(entry => new GitStatusEntryTreeData(entry))); + Redraw(); } - public override void Refresh() + protected void RevertCommit() { - base.Refresh(); - Refresh(CacheType.GitLog); - Refresh(CacheType.GitAheadBehind); + var dialogTitle = "Revert commit"; + var dialogBody = string.Format(@"Are you sure you want to revert the following commit:""{0}""", SelectedEntry.Summary); + + if (EditorUtility.DisplayDialog(dialogTitle, dialogBody, "Revert", "Cancel")) + { + Repository + .Revert(SelectedEntry.CommitID) + .FinallyInUI((success, e) => { + if (!success) + { + EditorUtility.DisplayDialog(dialogTitle, + "Error reverting commit: " + e.Message, Localization.Cancel); + } + }) + .Start(); + } } - public override void OnDataUpdate() + protected void HistoryDetailsEntry(GitLogEntry entry) { - base.OnDataUpdate(); - MaybeUpdateData(); + GUILayout.BeginVertical(Styles.HeaderBoxStyle); + GUILayout.Label(entry.Summary, Styles.HistoryDetailsTitleStyle); + + GUILayout.Space(-5); + + GUILayout.BeginHorizontal(); + GUILayout.Label(entry.PrettyTimeString, Styles.HistoryDetailsMetaInfoStyle); + GUILayout.Label(entry.AuthorName, Styles.HistoryDetailsMetaInfoStyle); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + GUILayout.Space(3); + GUILayout.EndVertical(); } - public override void OnFocusChanged() + protected GenericMenu CreateChangesTreeContextMenu(ChangesTreeNode node) { - base.OnFocusChanged(); - var hasFocus = HasFocus; - if (treeChanges.ViewHasFocus != hasFocus) - { - treeChanges.ViewHasFocus = hasFocus; - Redraw(); - } + var genericMenu = new GenericMenu(); + + genericMenu.AddItem(new GUIContent("Show History"), false, () => { }); + + return genericMenu; } public override void OnGUI() { var rect = GUILayoutUtility.GetLastRect(); - if (historyControl != null) + if (HistoryControl != null) { var historyControlRect = new Rect(0f, 0f, Position.width, Position.height - rect.height); - var requiresRepaint = historyControl.Render(historyControlRect, + var requiresRepaint = HistoryControl.Render(historyControlRect, entry => { - selectedEntry = entry; + SelectedEntry = entry; BuildTree(); }, entry => { }, entry => { @@ -393,27 +404,27 @@ public override void OnGUI() DoProgressGUI(); - if (!selectedEntry.Equals(GitLogEntry.Default)) + if (!SelectedEntry.Equals(GitLogEntry.Default)) { // Top bar for scrolling to selection or clearing it GUILayout.BeginHorizontal(EditorStyles.toolbar); { if (GUILayout.Button(CommitDetailsTitle, Styles.ToolbarButtonStyle)) { - historyControl.ScrollTo(historyControl.SelectedIndex); + HistoryControl.ScrollTo(HistoryControl.SelectedIndex); } if (GUILayout.Button(ClearSelectionButton, Styles.ToolbarButtonStyle, GUILayout.ExpandWidth(false))) { - selectedEntry = GitLogEntry.Default; - historyControl.SelectedIndex = -1; + SelectedEntry = GitLogEntry.Default; + HistoryControl.SelectedIndex = -1; } } GUILayout.EndHorizontal(); // Log entry details - including changeset tree (if any changes are found) - detailsScroll = GUILayout.BeginScrollView(detailsScroll, GUILayout.Height(250)); + DetailsScroll = GUILayout.BeginScrollView(DetailsScroll, GUILayout.Height(250)); { - HistoryDetailsEntry(selectedEntry); + HistoryDetailsEntry(SelectedEntry); GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); GUILayout.Label("Files changed", EditorStyles.boldLabel); @@ -426,15 +437,15 @@ public override void OnGUI() var borderLeft = Styles.Label.margin.left; var treeControlRect = new Rect(rect.x + borderLeft, rect.y, Position.width - borderLeft * 2, Position.height - rect.height + Styles.CommitAreaPadding); var treeRect = new Rect(0f, 0f, 0f, 0f); - if (treeChanges != null) + if (TreeChanges != null) { - treeChanges.FolderStyle = Styles.Foldout; - treeChanges.TreeNodeStyle = Styles.TreeNode; - treeChanges.ActiveTreeNodeStyle = Styles.ActiveTreeNode; - treeChanges.FocusedTreeNodeStyle = Styles.FocusedTreeNode; - treeChanges.FocusedActiveTreeNodeStyle = Styles.FocusedActiveTreeNode; + TreeChanges.FolderStyle = Styles.Foldout; + TreeChanges.TreeNodeStyle = Styles.TreeNode; + TreeChanges.ActiveTreeNodeStyle = Styles.ActiveTreeNode; + TreeChanges.FocusedTreeNodeStyle = Styles.FocusedTreeNode; + TreeChanges.FocusedActiveTreeNodeStyle = Styles.FocusedActiveTreeNode; - treeRect = treeChanges.Render(treeControlRect, detailsScroll, + treeRect = TreeChanges.Render(treeControlRect, DetailsScroll, singleClick: node => { }, doubleClick: node => { }, rightClick: node => { @@ -443,7 +454,7 @@ public override void OnGUI() } ); - if (treeChanges.RequiresRepaint) + if (TreeChanges.RequiresRepaint) Redraw(); } @@ -458,43 +469,74 @@ public override void OnGUI() } } - private void HistoryDetailsEntry(GitLogEntry entry) + public override void OnEnable() { - GUILayout.BeginVertical(Styles.HeaderBoxStyle); - GUILayout.Label(entry.Summary, Styles.HistoryDetailsTitleStyle); + base.OnEnable(); - GUILayout.Space(-5); + if (TreeChanges != null) + { + TreeChanges.ViewHasFocus = HasFocus; + TreeChanges.UpdateIcons(Styles.FolderIcon); + } - GUILayout.BeginHorizontal(); - GUILayout.Label(entry.PrettyTimeString, Styles.HistoryDetailsMetaInfoStyle); - GUILayout.Label(entry.AuthorName, Styles.HistoryDetailsMetaInfoStyle); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); + AttachHandlers(Repository); + ValidateCachedData(Repository); + } - GUILayout.Space(3); - GUILayout.EndVertical(); + public override void OnDisable() + { + base.OnDisable(); + DetachHandlers(Repository); } - private void RevertCommit() + public override void OnDataUpdate() { - var dialogTitle = "Revert commit"; - var dialogBody = string.Format(@"Are you sure you want to revert the following commit:""{0}""", selectedEntry.Summary); + base.OnDataUpdate(); + MaybeUpdateData(); + } - if (EditorUtility.DisplayDialog(dialogTitle, dialogBody, "Revert", "Cancel")) + public override void OnFocusChanged() + { + base.OnFocusChanged(); + var hasFocus = HasFocus; + if (TreeChanges.ViewHasFocus != hasFocus) { - Repository - .Revert(selectedEntry.CommitID) - .FinallyInUI((success, e) => { - if (!success) - { - EditorUtility.DisplayDialog(dialogTitle, - "Error reverting commit: " + e.Message, Localization.Cancel); - } - }) - .Start(); + TreeChanges.ViewHasFocus = hasFocus; + Redraw(); } } + protected abstract void AttachHandlers(IRepository repository); + protected abstract void DetachHandlers(IRepository repository); + protected abstract void ValidateCachedData(IRepository repository); + protected abstract void MaybeUpdateData(); + } + + [Serializable] + class HistoryView : HistoryBase + { + [SerializeField] private bool currentLogHasUpdate; + [SerializeField] private bool currentTrackingStatusHasUpdate; + + [SerializeField] private List logEntries = new List(); + + [SerializeField] private int statusAhead; + + [SerializeField] private CacheUpdateEvent lastLogChangedEvent; + [SerializeField] private CacheUpdateEvent lastTrackingStatusChangedEvent; + + [SerializeField] private HistoryControl historyControl; + [SerializeField] private GitLogEntry selectedEntry = GitLogEntry.Default; + [SerializeField] private ChangesTree treeChanges = new ChangesTree { DisplayRootNode = false }; + [SerializeField] private Vector2 detailsScroll; + + public override void Refresh() + { + base.Refresh(); + Refresh(CacheType.GitLog); + Refresh(CacheType.GitAheadBehind); + } + private void RepositoryOnTrackingStatusChanged(CacheUpdateEvent cacheUpdateEvent) { if (!lastTrackingStatusChangedEvent.Equals(cacheUpdateEvent)) @@ -517,7 +559,7 @@ private void RepositoryOnLogChanged(CacheUpdateEvent cacheUpdateEvent) } } - private void AttachHandlers(IRepository repository) + protected override void AttachHandlers(IRepository repository) { if (repository == null) { @@ -528,7 +570,7 @@ private void AttachHandlers(IRepository repository) repository.LogChanged += RepositoryOnLogChanged; } - private void DetachHandlers(IRepository repository) + protected override void DetachHandlers(IRepository repository) { if (repository == null) { @@ -539,13 +581,13 @@ private void DetachHandlers(IRepository repository) repository.LogChanged -= RepositoryOnLogChanged; } - private void ValidateCachedData(IRepository repository) + protected override void ValidateCachedData(IRepository repository) { repository.CheckAndRaiseEventsIfCacheNewer(CacheType.GitLog, lastLogChangedEvent); repository.CheckAndRaiseEventsIfCacheNewer(CacheType.GitAheadBehind, lastTrackingStatusChangedEvent); } - private void MaybeUpdateData() + protected override void MaybeUpdateData() { if (Repository == null) { @@ -565,39 +607,116 @@ private void MaybeUpdateData() logEntries = Repository.CurrentLog; - BuildHistoryControl(); + BuildHistoryControl(statusAhead, logEntries); } } - private void BuildHistoryControl() + protected override HistoryControl HistoryControl { - if (historyControl == null) + get { return historyControl; } + set { historyControl = value; } + } + + protected override GitLogEntry SelectedEntry + { + get { return selectedEntry; } + set { selectedEntry = value; } + } + + protected override ChangesTree TreeChanges + { + get { return treeChanges; } + set { treeChanges = value; } + } + + protected override Vector2 DetailsScroll + { + get { return detailsScroll; } + set { detailsScroll = value; } + } + } + + [Serializable] + class FileHistoryView : HistoryBase + { + [SerializeField] private bool currentLogHasUpdate; + [SerializeField] private List logEntries = new List(); + + [SerializeField] private HistoryControl historyControl; + [SerializeField] private GitLogEntry selectedEntry = GitLogEntry.Default; + [SerializeField] private ChangesTree treeChanges = new ChangesTree { DisplayRootNode = false }; + [SerializeField] private Vector2 detailsScroll; + [SerializeField] private string filePath; + + public override void Refresh() + { + base.Refresh(); + Refresh(CacheType.GitLog); + Refresh(CacheType.GitAheadBehind); + } + + protected override void AttachHandlers(IRepository repository) + { + if (repository == null) { - historyControl = new HistoryControl(); + return; } + } - historyControl.Load(statusAhead, logEntries); - if (!selectedEntry.Equals(GitLogEntry.Default) - && selectedEntry.CommitID != historyControl.SelectedGitLogEntry.CommitID) + protected override void DetachHandlers(IRepository repository) + { + if (repository == null) { - selectedEntry = GitLogEntry.Default; + return; } } - private void BuildTree() + protected override void ValidateCachedData(IRepository repository) { - treeChanges.PathSeparator = Environment.FileSystem.DirectorySeparatorChar.ToString(); - treeChanges.Load(selectedEntry.changes.Select(entry => new GitStatusEntryTreeData(entry))); - Redraw(); } - private GenericMenu CreateChangesTreeContextMenu(ChangesTreeNode node) + protected override void MaybeUpdateData() { - var genericMenu = new GenericMenu(); + if (Repository == null) + { + return; + } - genericMenu.AddItem(new GUIContent("Show History"), false, () => { }); + if (currentLogHasUpdate) + { + currentLogHasUpdate = false; - return genericMenu; + BuildHistoryControl(0, new List()); + } + } + + protected override HistoryControl HistoryControl + { + get { return historyControl; } + set { historyControl = value; } + } + + protected override GitLogEntry SelectedEntry + { + get { return selectedEntry; } + set { selectedEntry = value; } + } + + protected override ChangesTree TreeChanges + { + get { return treeChanges; } + set { treeChanges = value; } + } + + protected override Vector2 DetailsScroll + { + get { return detailsScroll; } + set { detailsScroll = value; } + } + + public void SetPath(string filePath) + { + this.filePath = filePath; } } } From 5a2cb01b7c45fc776a102a194ff646c05bbc9c34 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Tue, 15 Jan 2019 10:44:23 -0500 Subject: [PATCH 08/19] Fixing context menu displays --- .../Editor/GitHub.Unity/UI/HistoryView.cs | 63 ++++++++++++------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs index 6ee1a2cd7..c1c102192 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs @@ -327,7 +327,7 @@ protected void BuildHistoryControl(int loadAhead, List gitLogEntrie } } - protected void BuildTree() + protected void BuildTreeChanges() { TreeChanges.PathSeparator = Environment.FileSystem.DirectorySeparatorChar.ToString(); TreeChanges.Load(SelectedEntry.changes.Select(entry => new GitStatusEntryTreeData(entry))); @@ -371,16 +371,8 @@ protected void HistoryDetailsEntry(GitLogEntry entry) GUILayout.EndVertical(); } - protected GenericMenu CreateChangesTreeContextMenu(ChangesTreeNode node) - { - var genericMenu = new GenericMenu(); - - genericMenu.AddItem(new GUIContent("Show History"), false, () => { }); - - return genericMenu; - } - - public override void OnGUI() + protected void DoHistoryGui(Action historyControlRightClick = null, + Action changesTreeRightClick = null) { var rect = GUILayoutUtility.GetLastRect(); if (HistoryControl != null) @@ -388,15 +380,14 @@ public override void OnGUI() var historyControlRect = new Rect(0f, 0f, Position.width, Position.height - rect.height); var requiresRepaint = HistoryControl.Render(historyControlRect, - entry => { + singleClick: entry => { SelectedEntry = entry; - BuildTree(); + BuildTreeChanges(); + }, + doubleClick: entry => { + }, - entry => { }, entry => { - GenericMenu menu = new GenericMenu(); - menu.AddItem(new GUIContent("Revert"), false, RevertCommit); - menu.ShowAsContext(); - }); + rightClick: historyControlRightClick); if (requiresRepaint) Redraw(); @@ -413,6 +404,7 @@ public override void OnGUI() { HistoryControl.ScrollTo(HistoryControl.SelectedIndex); } + if (GUILayout.Button(ClearSelectionButton, Styles.ToolbarButtonStyle, GUILayout.ExpandWidth(false))) { SelectedEntry = GitLogEntry.Default; @@ -435,7 +427,8 @@ public override void OnGUI() GUILayout.BeginVertical(); { var borderLeft = Styles.Label.margin.left; - var treeControlRect = new Rect(rect.x + borderLeft, rect.y, Position.width - borderLeft * 2, Position.height - rect.height + Styles.CommitAreaPadding); + var treeControlRect = new Rect(rect.x + borderLeft, rect.y, Position.width - borderLeft * 2, + Position.height - rect.height + Styles.CommitAreaPadding); var treeRect = new Rect(0f, 0f, 0f, 0f); if (TreeChanges != null) { @@ -448,11 +441,7 @@ public override void OnGUI() treeRect = TreeChanges.Render(treeControlRect, DetailsScroll, singleClick: node => { }, doubleClick: node => { }, - rightClick: node => { - var menu = CreateChangesTreeContextMenu(node); - menu.ShowAsContext(); - } - ); + rightClick: changesTreeRightClick); if (TreeChanges.RequiresRepaint) Redraw(); @@ -611,6 +600,18 @@ protected override void MaybeUpdateData() } } + public override void OnGUI() + { + DoHistoryGui(entry => { + GenericMenu menu = new GenericMenu(); + menu.AddItem(new GUIContent("Revert"), false, RevertCommit); + menu.ShowAsContext(); + }, node => { + var menu = CreateChangesTreeContextMenu(node); + menu.ShowAsContext(); + }); + } + protected override HistoryControl HistoryControl { get { return historyControl; } @@ -634,6 +635,15 @@ protected override Vector2 DetailsScroll get { return detailsScroll; } set { detailsScroll = value; } } + + private GenericMenu CreateChangesTreeContextMenu(ChangesTreeNode node) + { + var genericMenu = new GenericMenu(); + + genericMenu.AddItem(new GUIContent("Show History"), false, () => { }); + + return genericMenu; + } } [Serializable] @@ -690,6 +700,11 @@ protected override void MaybeUpdateData() } } + public override void OnGUI() + { + DoHistoryGui(); + } + protected override HistoryControl HistoryControl { get { return historyControl; } From ad90c866427d73b27e6e1b327e31ace802b40e16 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Thu, 17 Jan 2019 13:24:07 -0500 Subject: [PATCH 09/19] Start of a working File History --- src/GitHub.Api/Cache/CacheContainer.cs | 1 + src/GitHub.Api/Cache/CacheInterfaces.cs | 7 +++ src/GitHub.Api/Git/GitClient.cs | 5 ++ src/GitHub.Api/Git/GitFileLog.cs | 32 +++++++++++++ src/GitHub.Api/Git/IRepository.cs | 5 +- src/GitHub.Api/Git/Repository.cs | 19 ++++++++ src/GitHub.Api/Git/RepositoryManager.cs | 19 ++++++++ src/GitHub.Api/GitHub.Api.45.csproj | 1 + src/GitHub.Api/GitHub.Api.csproj | 1 + .../Editor/GitHub.Unity/ApplicationCache.cs | 41 ++++++++++++++++ .../Editor/GitHub.Unity/UI/ContextMenu.cs | 26 +--------- .../GitHub.Unity/UI/FileHistoryWindow.cs | 47 ++++++++++++------- .../Editor/GitHub.Unity/UI/HistoryView.cs | 45 ++++++++++++------ 13 files changed, 192 insertions(+), 57 deletions(-) create mode 100644 src/GitHub.Api/Git/GitFileLog.cs diff --git a/src/GitHub.Api/Cache/CacheContainer.cs b/src/GitHub.Api/Cache/CacheContainer.cs index 40f1802fb..2c07ff867 100644 --- a/src/GitHub.Api/Cache/CacheContainer.cs +++ b/src/GitHub.Api/Cache/CacheContainer.cs @@ -90,6 +90,7 @@ public void Dispose() public IBranchCache BranchCache { get { return (IBranchCache)caches[CacheType.Branches].Value; } } public IGitLogCache GitLogCache { get { return (IGitLogCache)caches[CacheType.GitLog].Value; } } + public IGitFileLogCache GitFileLogCache { get { return (IGitFileLogCache)caches[CacheType.GitFileLog].Value; } } public IGitAheadBehindCache GitTrackingStatusCache { get { return (IGitAheadBehindCache)caches[CacheType.GitAheadBehind].Value; } } public IGitStatusCache GitStatusEntriesCache { get { return (IGitStatusCache)caches[CacheType.GitStatus].Value; } } public IGitLocksCache GitLocksCache { get { return (IGitLocksCache)caches[CacheType.GitLocks].Value; } } diff --git a/src/GitHub.Api/Cache/CacheInterfaces.cs b/src/GitHub.Api/Cache/CacheInterfaces.cs index be6bab1f1..ae815beac 100644 --- a/src/GitHub.Api/Cache/CacheInterfaces.cs +++ b/src/GitHub.Api/Cache/CacheInterfaces.cs @@ -9,6 +9,7 @@ public enum CacheType RepositoryInfo, Branches, GitLog, + GitFileLog, GitAheadBehind, GitStatus, GitLocks, @@ -22,6 +23,7 @@ public interface ICacheContainer : IDisposable IBranchCache BranchCache { get; } IGitLogCache GitLogCache { get; } + IGitFileLogCache GitFileLogCache { get; } IGitAheadBehindCache GitTrackingStatusCache { get; } IGitStatusCache GitStatusEntriesCache { get; } IGitLocksCache GitLocksCache { get; } @@ -115,6 +117,11 @@ public interface IGitLogCache : IManagedCache List Log { get; set; } } + public interface IGitFileLogCache : IManagedCache + { + GitFileLog FileLog { get; set; } + } + public interface ICanUpdate { void UpdateData(T data); diff --git a/src/GitHub.Api/Git/GitClient.cs b/src/GitHub.Api/Git/GitClient.cs index 6b77866cb..50deee430 100644 --- a/src/GitHub.Api/Git/GitClient.cs +++ b/src/GitHub.Api/Git/GitClient.cs @@ -360,6 +360,11 @@ public ITask> Log(BaseOutputListProcessor process /// public ITask> LogFile(NPath file, BaseOutputListProcessor processor = null) { + if (file == NPath.Default) + { + return new FuncTask>(cancellationToken, () => new List(0)); + } + return new GitLogTask(file, new GitObjectFactory(environment), cancellationToken, processor) .Configure(processManager) .Catch(exception => exception is ProcessException && diff --git a/src/GitHub.Api/Git/GitFileLog.cs b/src/GitHub.Api/Git/GitFileLog.cs new file mode 100644 index 000000000..053aff740 --- /dev/null +++ b/src/GitHub.Api/Git/GitFileLog.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace GitHub.Unity +{ + [Serializable] + public struct GitFileLog + { + public static GitFileLog Default = new GitFileLog(NPath.Default, new List(0)); + + public NPath path; + public List logEntries; + + public GitFileLog(NPath path, List logEntries) + { + this.path = path; + this.logEntries = logEntries; + } + + public NPath Path + { + get { return path; } + set { path = value; } + } + + public List LogEntries + { + get { return logEntries; } + set { logEntries = value; } + } + } +} diff --git a/src/GitHub.Api/Git/IRepository.cs b/src/GitHub.Api/Git/IRepository.cs index 148015282..90481b5b6 100644 --- a/src/GitHub.Api/Git/IRepository.cs +++ b/src/GitHub.Api/Git/IRepository.cs @@ -61,8 +61,10 @@ public interface IRepository : IEquatable, IDisposable, IBackedByCa List CurrentLog { get; } bool IsBusy { get; } string CurrentHead { get; } + GitFileLog CurrentFileLog { get; } event Action LogChanged; + event Action FileLogChanged; event Action TrackingStatusChanged; event Action StatusEntriesChanged; event Action CurrentBranchChanged; @@ -80,5 +82,6 @@ public interface IRepository : IEquatable, IDisposable, IBackedByCa ITask SwitchBranch(string branch); void Refresh(CacheType cacheType); event Action OnProgress; + ITask UpdateFileLog(NPath path); } -} \ No newline at end of file +} diff --git a/src/GitHub.Api/Git/Repository.cs b/src/GitHub.Api/Git/Repository.cs index 9cceea0bc..8c27f13fa 100644 --- a/src/GitHub.Api/Git/Repository.cs +++ b/src/GitHub.Api/Git/Repository.cs @@ -25,8 +25,10 @@ sealed class Repository : IEquatable, IRepository private HashSet cacheInvalidationRequests = new HashSet(); private Dictionary> cacheUpdateEvents; private ProgressReporter progressReporter = new ProgressReporter(); + private NPath lastFileLog = NPath.Default; public event Action LogChanged; + public event Action FileLogChanged; public event Action TrackingStatusChanged; public event Action StatusEntriesChanged; public event Action CurrentBranchChanged; @@ -63,6 +65,7 @@ public Repository(NPath localPath, ICacheContainer container) { CacheType.GitAheadBehind, c => TrackingStatusChanged?.Invoke(c) }, { CacheType.GitLocks, c => LocksChanged?.Invoke(c) }, { CacheType.GitLog, c => LogChanged?.Invoke(c) }, + { CacheType.GitFileLog, c => FileLogChanged?.Invoke(c) }, { CacheType.GitStatus, c => StatusEntriesChanged?.Invoke(c) }, { CacheType.GitUser, cacheUpdateEvent => { } }, { CacheType.RepositoryInfo, cacheUpdateEvent => { @@ -91,6 +94,7 @@ public void Initialize(IRepositoryManager theRepositoryManager, ITaskManager the this.repositoryManager.GitStatusUpdated += RepositoryManagerOnGitStatusUpdated; this.repositoryManager.GitAheadBehindStatusUpdated += RepositoryManagerOnGitAheadBehindStatusUpdated; this.repositoryManager.GitLogUpdated += RepositoryManagerOnGitLogUpdated; + this.repositoryManager.GitFileLogUpdated += RepositoryManagerOnGitFileLogUpdated; this.repositoryManager.GitLocksUpdated += RepositoryManagerOnGitLocksUpdated; this.repositoryManager.LocalBranchesUpdated += RepositoryManagerOnLocalBranchesUpdated; this.repositoryManager.RemoteBranchesUpdated += RepositoryManagerOnRemoteBranchesUpdated; @@ -143,6 +147,11 @@ public ITask SetupRemote(string remote, string remoteUrl) public ITask DeleteBranch(string branch, bool force) => repositoryManager.DeleteBranch(branch, force); public ITask CreateBranch(string branch, string baseBranch) => repositoryManager.CreateBranch(branch, baseBranch); public ITask SwitchBranch(string branch) => repositoryManager.SwitchBranch(branch); + public ITask UpdateFileLog(NPath path) + { + lastFileLog = path; + return repositoryManager.UpdateFileLog(path); + } public void CheckAndRaiseEventsIfCacheNewer(CacheType cacheType, CacheUpdateEvent cacheUpdateEvent) => cacheContainer.CheckAndRaiseEventsIfCacheNewer(cacheType, cacheUpdateEvent); @@ -215,6 +224,10 @@ private void CacheHasBeenInvalidated(CacheType cacheType) repositoryManager?.UpdateGitLog().Catch(ex => InvalidationFailed(ex, cacheType)).Start(); break; + case CacheType.GitFileLog: + repositoryManager?.UpdateFileLog(lastFileLog).Catch(ex => InvalidationFailed(ex, cacheType)).Start(); + break; + case CacheType.GitAheadBehind: repositoryManager?.UpdateGitAheadBehindStatus().Catch(ex => InvalidationFailed(ex, cacheType)).Start(); break; @@ -295,6 +308,11 @@ private void RepositoryManagerOnGitLogUpdated(List gitLogEntries) taskManager.RunInUI(() => cacheContainer.GitLogCache.Log = gitLogEntries); } + private void RepositoryManagerOnGitFileLogUpdated(GitFileLog gitFileLog) + { + taskManager.RunInUI(() => cacheContainer.GitFileLogCache.FileLog = gitFileLog); + } + private void RepositoryManagerOnGitLocksUpdated(List gitLocks) { taskManager.RunInUI(() => cacheContainer.GitLocksCache.GitLocks = gitLocks); @@ -360,6 +378,7 @@ public void Dispose() public string CurrentBranchName => CurrentConfigBranch?.Name; public GitRemote? CurrentRemote => cacheContainer.RepositoryInfoCache.CurrentGitRemote; public List CurrentLog => cacheContainer.GitLogCache.Log; + public GitFileLog CurrentFileLog => cacheContainer.GitFileLogCache.FileLog; public List CurrentLocks => cacheContainer.GitLocksCache.GitLocks; public string CurrentHead => cacheContainer.RepositoryInfoCache.CurrentHead; diff --git a/src/GitHub.Api/Git/RepositoryManager.cs b/src/GitHub.Api/Git/RepositoryManager.cs index d84db5db6..47a6039fb 100644 --- a/src/GitHub.Api/Git/RepositoryManager.cs +++ b/src/GitHub.Api/Git/RepositoryManager.cs @@ -13,6 +13,7 @@ public interface IRepositoryManager : IDisposable event Action GitStatusUpdated; event Action> GitLocksUpdated; event Action> GitLogUpdated; + event Action GitFileLogUpdated; event Action> LocalBranchesUpdated; event Action, Dictionary>> RemoteBranchesUpdated; event Action GitAheadBehindStatusUpdated; @@ -43,6 +44,8 @@ public interface IRepositoryManager : IDisposable ITask UpdateLocks(); ITask UpdateRepositoryInfo(); ITask UpdateBranches(); + ITask UpdateFileLog(NPath path); + int WaitForEvents(); @@ -136,6 +139,7 @@ class RepositoryManager : IRepositoryManager public event Action GitAheadBehindStatusUpdated; public event Action> GitLocksUpdated; public event Action> GitLogUpdated; + public event Action GitFileLogUpdated; public event Action> LocalBranchesUpdated; public event Action, Dictionary>> RemoteBranchesUpdated; @@ -354,6 +358,20 @@ public ITask UpdateGitLog() return HookupHandlers(task, false); } + public ITask UpdateFileLog(NPath path) + { + var task = GitClient.LogFile(path) + .Then((success, logEntries) => + { + if (success) + { + var gitFileLog = new GitFileLog(path, logEntries); + GitFileLogUpdated?.Invoke(gitFileLog); + } + }); + return HookupHandlers(task, false); + } + public ITask UpdateGitStatus() { var task = GitClient.Status() @@ -644,6 +662,7 @@ private void Dispose(bool disposing) GitStatusUpdated = null; GitAheadBehindStatusUpdated = null; GitLogUpdated = null; + GitFileLogUpdated = null; GitLocksUpdated = null; LocalBranchesUpdated = null; RemoteBranchesUpdated = null; diff --git a/src/GitHub.Api/GitHub.Api.45.csproj b/src/GitHub.Api/GitHub.Api.45.csproj index 6d3d8d514..7a322039a 100644 --- a/src/GitHub.Api/GitHub.Api.45.csproj +++ b/src/GitHub.Api/GitHub.Api.45.csproj @@ -79,6 +79,7 @@ + diff --git a/src/GitHub.Api/GitHub.Api.csproj b/src/GitHub.Api/GitHub.Api.csproj index 5b9441180..b7d31aea2 100644 --- a/src/GitHub.Api/GitHub.Api.csproj +++ b/src/GitHub.Api/GitHub.Api.csproj @@ -90,6 +90,7 @@ + diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/ApplicationCache.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/ApplicationCache.cs index a1fca0391..272566cf7 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/ApplicationCache.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/ApplicationCache.cs @@ -147,6 +147,7 @@ public IEnvironment Environment cacheContainer.SetCacheInitializer(CacheType.GitAheadBehind, () => GitAheadBehindCache.Instance); cacheContainer.SetCacheInitializer(CacheType.GitLocks, () => GitLocksCache.Instance); cacheContainer.SetCacheInitializer(CacheType.GitLog, () => GitLogCache.Instance); + cacheContainer.SetCacheInitializer(CacheType.GitFileLog, () => GitFileLogCache.Instance); cacheContainer.SetCacheInitializer(CacheType.GitStatus, () => GitStatusCache.Instance); cacheContainer.SetCacheInitializer(CacheType.GitUser, () => GitUserCache.Instance); cacheContainer.SetCacheInitializer(CacheType.RepositoryInfo, () => RepositoryInfoCache.Instance); @@ -622,6 +623,46 @@ public List Log public override TimeSpan DataTimeout { get { return TimeSpan.FromMinutes(1); } } } + [Location("cache/gitfilelog.yaml", LocationAttribute.Location.LibraryFolder)] + sealed class GitFileLogCache : ManagedCacheBase, IGitFileLogCache + { + [SerializeField] private GitFileLog fileLog = GitFileLog.Default; + + public GitFileLogCache() : base(CacheType.GitFileLog) + { } + + public GitFileLog FileLog + { + get + { + ValidateData(); + return fileLog; + } + set + { + var now = DateTimeOffset.Now; + var isUpdated = false; + + var shouldUpdate = forcedInvalidation; + + if (!shouldUpdate) + { + shouldUpdate = true; + } + + if (shouldUpdate) + { + fileLog = value; + isUpdated = true; + } + + SaveData(now, isUpdated); + } + } + + public override TimeSpan DataTimeout { get { return TimeSpan.FromMinutes(1); } } + } + [Location("cache/gittrackingstatus.yaml", LocationAttribute.Location.LibraryFolder)] sealed class GitAheadBehindCache : ManagedCacheBase, IGitAheadBehindCache { diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs index 4adfce9fd..6b88821d6 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ContextMenu.cs @@ -7,30 +7,6 @@ namespace GitHub.Unity { public class ContextMenu { - [MenuItem("Assets/Git/History", false)] - private static void GitFileHistory() - { - if (Selection.assetGUIDs != null) - { - int maxWindowsToOpen = 10; - int windowsOpened = 0; - foreach(var guid in Selection.assetGUIDs) - { - var assetPath = AssetDatabase.GUIDToAssetPath(guid); - FileHistoryWindow.OpenWindow(EntryPoint.ApplicationManager, assetPath); - windowsOpened++; - if (windowsOpened >= maxWindowsToOpen) - { - break; - } - } - } - } - - [MenuItem("Assets/Git/History", true)] - private static bool GitFileHistoryValidation() - { - return Selection.assetGUIDs != null && Selection.assetGUIDs.Length > 0; - } + } } diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index 73f05dba4..cfe97c615 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using UnityEditor; using UnityEngine; @@ -6,29 +7,39 @@ namespace GitHub.Unity { public class FileHistoryWindow : BaseWindow { + [MenuItem("Assets/Git/History", false)] + private static void GitFileHistory() + { + if (Selection.assetGUIDs != null) + { + var assetPath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs.First()) + .ToNPath(); + + var windowType = typeof(Window); + var fileHistoryWindow = GetWindow(windowType); + fileHistoryWindow.InitializeWindow(EntryPoint.ApplicationManager); + fileHistoryWindow.Open(assetPath); + fileHistoryWindow.Show(); + } + } + + [MenuItem("Assets/Git/History", true)] + private static bool GitFileHistoryValidation() + { + return Selection.assetGUIDs != null && Selection.assetGUIDs.Length > 0; + } + private const string Title = "File History"; [NonSerialized] private bool firstOnGUI = true; [SerializeField] private bool locked; - [SerializeField] private string assetPath; [SerializeField] private FileHistoryView fileHistoryView = new FileHistoryView(); - public static FileHistoryWindow OpenWindow(IApplicationManager applicationManager, string assetPath) + public void Open(NPath path) { - var fileHistoryWindow = CreateInstance(); - fileHistoryWindow.InitializeWindow(applicationManager); - - fileHistoryWindow.Open(assetPath); - fileHistoryWindow.Show(); - - return fileHistoryWindow; - } - - public void Open(string path) - { - assetPath = path; - fileHistoryView.SetPath(path); + Repository.UpdateFileLog(path) + .Start(); } public override void Initialize(IApplicationManager applicationManager) @@ -110,7 +121,11 @@ public override void OnUI() { base.OnUI(); - fileHistoryView.OnGUI(); + GUILayout.BeginVertical(Styles.HeaderStyle); + { + fileHistoryView.OnGUI(); + } + GUILayout.EndVertical(); } private void MaybeUpdateData() diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs index c1c102192..20ae007cc 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs @@ -371,10 +371,9 @@ protected void HistoryDetailsEntry(GitLogEntry entry) GUILayout.EndVertical(); } - protected void DoHistoryGui(Action historyControlRightClick = null, + protected void DoHistoryGui(Rect rect, Action historyControlRightClick = null, Action changesTreeRightClick = null) { - var rect = GUILayoutUtility.GetLastRect(); if (HistoryControl != null) { var historyControlRect = new Rect(0f, 0f, Position.width, Position.height - rect.height); @@ -602,7 +601,8 @@ protected override void MaybeUpdateData() public override void OnGUI() { - DoHistoryGui(entry => { + var lastRect = GUILayoutUtility.GetLastRect(); + DoHistoryGui(lastRect, entry => { GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("Revert"), false, RevertCommit); menu.ShowAsContext(); @@ -649,14 +649,16 @@ private GenericMenu CreateChangesTreeContextMenu(ChangesTreeNode node) [Serializable] class FileHistoryView : HistoryBase { - [SerializeField] private bool currentLogHasUpdate; - [SerializeField] private List logEntries = new List(); + [SerializeField] private bool currentFileLogHasUpdate; + + [SerializeField] private GitFileLog gitFileLog; [SerializeField] private HistoryControl historyControl; [SerializeField] private GitLogEntry selectedEntry = GitLogEntry.Default; [SerializeField] private ChangesTree treeChanges = new ChangesTree { DisplayRootNode = false }; [SerializeField] private Vector2 detailsScroll; - [SerializeField] private string filePath; + + [SerializeField] private CacheUpdateEvent lastFileLogChangedEvent; public override void Refresh() { @@ -665,12 +667,25 @@ public override void Refresh() Refresh(CacheType.GitAheadBehind); } + private void RepositoryOnFileLogChanged(CacheUpdateEvent cacheUpdateEvent) + { + if (!lastFileLogChangedEvent.Equals(cacheUpdateEvent)) + { + ReceivedEvent(cacheUpdateEvent.cacheType); + lastFileLogChangedEvent = cacheUpdateEvent; + currentFileLogHasUpdate = true; + Redraw(); + } + } + protected override void AttachHandlers(IRepository repository) { if (repository == null) { return; } + + repository.FileLogChanged += RepositoryOnFileLogChanged; } protected override void DetachHandlers(IRepository repository) @@ -679,10 +694,13 @@ protected override void DetachHandlers(IRepository repository) { return; } + + repository.FileLogChanged -= RepositoryOnFileLogChanged; } protected override void ValidateCachedData(IRepository repository) { + repository.CheckAndRaiseEventsIfCacheNewer(CacheType.GitFileLog, lastFileLogChangedEvent); } protected override void MaybeUpdateData() @@ -692,17 +710,19 @@ protected override void MaybeUpdateData() return; } - if (currentLogHasUpdate) + if (currentFileLogHasUpdate) { - currentLogHasUpdate = false; + currentFileLogHasUpdate = false; - BuildHistoryControl(0, new List()); + gitFileLog = Repository.CurrentFileLog; + + BuildHistoryControl(0, gitFileLog.LogEntries); } } public override void OnGUI() { - DoHistoryGui(); + DoHistoryGui(Rect.zero); } protected override HistoryControl HistoryControl @@ -728,10 +748,5 @@ protected override Vector2 DetailsScroll get { return detailsScroll; } set { detailsScroll = value; } } - - public void SetPath(string filePath) - { - this.filePath = filePath; - } } } From 64087c1097de07b927860b5af78932fe32d8a3a5 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Thu, 17 Jan 2019 14:40:54 -0500 Subject: [PATCH 10/19] Header and reactions to selected context --- .../GitHub.Unity/UI/FileHistoryWindow.cs | 75 +++++++++++++++---- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index cfe97c615..835d82b09 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -12,13 +12,14 @@ private static void GitFileHistory() { if (Selection.assetGUIDs != null) { - var assetPath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs.First()) - .ToNPath(); + var assetPath = + AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs.First()) + .ToNPath(); var windowType = typeof(Window); var fileHistoryWindow = GetWindow(windowType); fileHistoryWindow.InitializeWindow(EntryPoint.ApplicationManager); - fileHistoryWindow.Open(assetPath); + fileHistoryWindow.SetSelectedPath(assetPath); fileHistoryWindow.Show(); } } @@ -32,13 +33,31 @@ private static bool GitFileHistoryValidation() private const string Title = "File History"; [NonSerialized] private bool firstOnGUI = true; + [NonSerialized] private Texture selectedIcon; - [SerializeField] private bool locked; + [SerializeField] private bool locked = true; [SerializeField] private FileHistoryView fileHistoryView = new FileHistoryView(); + [SerializeField] private NPath selectedAssetPath; - public void Open(NPath path) + public void SetSelectedPath(NPath path) { - Repository.UpdateFileLog(path) + selectedAssetPath = path; + + Texture nodeIcon = null; + + if (selectedAssetPath != NPath.Default) + { + nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedAssetPath.ToString()); + } + + if (nodeIcon != null) + { + nodeIcon.hideFlags = HideFlags.HideAndDontSave; + } + + selectedIcon = nodeIcon; + + Repository.UpdateFileLog(selectedAssetPath) .Start(); } @@ -78,12 +97,6 @@ public override void OnDataUpdate() fileHistoryView.OnDataUpdate(); } - public override void OnFocusChanged() - { - if (fileHistoryView != null) - fileHistoryView.OnFocusChanged(); - } - public override void OnRepositoryChanged(IRepository oldRepository) { base.OnRepositoryChanged(oldRepository); @@ -106,6 +119,20 @@ public override void OnSelectionChange() base.OnSelectionChange(); if (fileHistoryView != null) fileHistoryView.OnSelectionChange(); + + if (!locked) + { + var assetGuid = Selection.assetGUIDs.FirstOrDefault(); + + selectedAssetPath = NPath.Default; + if (assetGuid != null) + { + selectedAssetPath = AssetDatabase.GUIDToAssetPath(assetGuid) + .ToNPath(); + } + + SetSelectedPath(selectedAssetPath); + } } public override void Refresh() @@ -113,7 +140,7 @@ public override void Refresh() base.Refresh(); if (fileHistoryView != null) fileHistoryView.Refresh(); - Refresh(CacheType.GitLocks); + Refresh(CacheType.GitFileLog); Redraw(); } @@ -123,6 +150,8 @@ public override void OnUI() GUILayout.BeginVertical(Styles.HeaderStyle); { + DoHeaderGUI(); + fileHistoryView.OnGUI(); } GUILayout.EndVertical(); @@ -160,5 +189,25 @@ private void ShowButton(Rect rect) this.OnSelectionChange(); } + + private void DoHeaderGUI() + { + GUILayout.BeginHorizontal(Styles.HeaderBoxStyle); + { + GUILayout.BeginVertical(); + { + GUILayout.Space(3); + + var iconWidth = 32; + var iconHeight = 32; + + GUILayout.Label(selectedIcon, GUILayout.Height(iconWidth), GUILayout.Width(iconHeight)); + + GUILayout.Label(selectedAssetPath, Styles.Label); + } + GUILayout.EndVertical(); + } + GUILayout.EndHorizontal(); + } } } From 0940957d5506186c001de100f6f36705971ae6df Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Thu, 17 Jan 2019 14:49:07 -0500 Subject: [PATCH 11/19] Dont default to locked --- .../Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index 835d82b09..5f89d132a 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -35,7 +35,7 @@ private static bool GitFileHistoryValidation() [NonSerialized] private bool firstOnGUI = true; [NonSerialized] private Texture selectedIcon; - [SerializeField] private bool locked = true; + [SerializeField] private bool locked; [SerializeField] private FileHistoryView fileHistoryView = new FileHistoryView(); [SerializeField] private NPath selectedAssetPath; From ae8e308ea04cbb58cf730467852d869005ca4619 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Wed, 23 Jan 2019 07:59:27 -0500 Subject: [PATCH 12/19] Using a folder icon when needed --- .../Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index 5f89d132a..71285a375 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -47,7 +47,14 @@ public void SetSelectedPath(NPath path) if (selectedAssetPath != NPath.Default) { - nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedAssetPath.ToString()); + if (selectedAssetPath.DirectoryExists()) + { + nodeIcon = Styles.FolderIcon; + } + else + { + nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedAssetPath.ToString()); + } } if (nodeIcon != null) From 1b3d0de00ba5a8c5b32d3f5f160a2ee59b9a268f Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Wed, 23 Jan 2019 09:22:32 -0500 Subject: [PATCH 13/19] Layout and functionality to find file in asset explorer --- .../Assets/Editor/GitHub.Unity/Misc/Styles.cs | 18 +++++- .../GitHub.Unity/UI/FileHistoryWindow.cs | 62 +++++++++++-------- 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/Misc/Styles.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/Misc/Styles.cs index 64d851201..2fbeaf7c3 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/Misc/Styles.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/Misc/Styles.cs @@ -65,6 +65,7 @@ class Styles headerBranchLabelStyle, headerUrlLabelStyle, headerRepoLabelStyle, + fileHistoryLogTitleStyle, headerTitleStyle, headerDescriptionStyle, toolbarButtonStyle, @@ -734,8 +735,7 @@ public static GUIStyle BoldCenteredLabel return boldCenteredLabel; } } - - + public static GUIStyle CommitDescriptionFieldStyle { get @@ -802,6 +802,20 @@ public static GUIStyle HyperlinkStyle } } + public static GUIStyle FileHistoryLogTitleStyle + { + get + { + if (fileHistoryLogTitleStyle == null) + { + fileHistoryLogTitleStyle = new GUIStyle(EditorStyles.largeLabel); + fileHistoryLogTitleStyle.name = "FileHistoryLogTitleStyle"; + fileHistoryLogTitleStyle.margin = new RectOffset(0, 0, 0, 0); + } + return fileHistoryLogTitleStyle; + } + } + public static Texture2D ActiveBranchIcon { get diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index 71285a375..0c4f108f1 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -37,34 +37,35 @@ private static bool GitFileHistoryValidation() [SerializeField] private bool locked; [SerializeField] private FileHistoryView fileHistoryView = new FileHistoryView(); - [SerializeField] private NPath selectedAssetPath; + [SerializeField] private UnityEngine.Object selectedObject; + [SerializeField] private NPath selectedObjectPath; public void SetSelectedPath(NPath path) { - selectedAssetPath = path; + selectedObjectPath = path; + selectedObject = null; Texture nodeIcon = null; - if (selectedAssetPath != NPath.Default) + if (selectedObjectPath != NPath.Default) { - if (selectedAssetPath.DirectoryExists()) + selectedObject = AssetDatabase.LoadMainAssetAtPath(path.ToString()); + + if (selectedObjectPath.DirectoryExists()) { nodeIcon = Styles.FolderIcon; } else { - nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedAssetPath.ToString()); + nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedObjectPath.ToString()); } - } - if (nodeIcon != null) - { nodeIcon.hideFlags = HideFlags.HideAndDontSave; } selectedIcon = nodeIcon; - Repository.UpdateFileLog(selectedAssetPath) + Repository.UpdateFileLog(selectedObjectPath) .Start(); } @@ -129,16 +130,15 @@ public override void OnSelectionChange() if (!locked) { - var assetGuid = Selection.assetGUIDs.FirstOrDefault(); - - selectedAssetPath = NPath.Default; - if (assetGuid != null) + selectedObject = Selection.activeObject; + selectedObjectPath = NPath.Default; + if (selectedObject != null) { - selectedAssetPath = AssetDatabase.GUIDToAssetPath(assetGuid) + selectedObjectPath = AssetDatabase.GetAssetPath(selectedObject) .ToNPath(); } - SetSelectedPath(selectedAssetPath); + SetSelectedPath(selectedObjectPath); } } @@ -155,13 +155,16 @@ public override void OnUI() { base.OnUI(); - GUILayout.BeginVertical(Styles.HeaderStyle); + if (selectedObject != null) { - DoHeaderGUI(); + GUILayout.BeginVertical(Styles.HeaderStyle); + { + DoHeaderGUI(); - fileHistoryView.OnGUI(); + fileHistoryView.OnGUI(); + } + GUILayout.EndVertical(); } - GUILayout.EndVertical(); } private void MaybeUpdateData() @@ -201,16 +204,23 @@ private void DoHeaderGUI() { GUILayout.BeginHorizontal(Styles.HeaderBoxStyle); { - GUILayout.BeginVertical(); - { - GUILayout.Space(3); + var iconWidth = 32; + var iconHeight = 32; + + GUILayout.Label(selectedIcon, GUILayout.Height(iconWidth), GUILayout.Width(iconHeight)); - var iconWidth = 32; - var iconHeight = 32; + GUILayout.Label(selectedObjectPath, Styles.FileHistoryLogTitleStyle); - GUILayout.Label(selectedIcon, GUILayout.Height(iconWidth), GUILayout.Width(iconHeight)); + GUILayout.FlexibleSpace(); + + GUILayout.BeginVertical(); + { + GUILayout.Space(16); - GUILayout.Label(selectedAssetPath, Styles.Label); + if (GUILayout.Button("Show in Project")) + { + EditorGUIUtility.PingObject(selectedObject); + } } GUILayout.EndVertical(); } From 9a5d0270d168ea42fbc87322d81316427b9a472c Mon Sep 17 00:00:00 2001 From: Sam Christiansen Date: Wed, 30 Jan 2019 09:45:39 -0800 Subject: [PATCH 14/19] refresh asset database after revert --- src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs index 20ae007cc..3cab7852d 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs @@ -349,6 +349,7 @@ protected void RevertCommit() EditorUtility.DisplayDialog(dialogTitle, "Error reverting commit: " + e.Message, Localization.Cancel); } + AssetDatabase.Refresh(); }) .Start(); } From 1b12912b52e6c05ddc73d1289ab46612619b0027 Mon Sep 17 00:00:00 2001 From: Sam Christiansen Date: Thu, 31 Jan 2019 13:54:00 -0800 Subject: [PATCH 15/19] added individual file revert; fixed domain reload bugs --- .../GitHub.Unity/UI/FileHistoryWindow.cs | 56 ++++++++++++++----- .../Editor/GitHub.Unity/UI/HistoryView.cs | 53 +++++++++++++++++- 2 files changed, 94 insertions(+), 15 deletions(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index 0c4f108f1..a00c12b9d 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -38,35 +38,52 @@ private static bool GitFileHistoryValidation() [SerializeField] private bool locked; [SerializeField] private FileHistoryView fileHistoryView = new FileHistoryView(); [SerializeField] private UnityEngine.Object selectedObject; - [SerializeField] private NPath selectedObjectPath; + [SerializeField] private NPath selectedObjectAssetPath; + [SerializeField] private string selectedObjectAssetPathStr; - public void SetSelectedPath(NPath path) + public void SetSelectedPath(NPath assetPath) { - selectedObjectPath = path; + var fullPath = Application.dataPath.ToNPath().Parent.Combine(assetPath); + this.fileHistoryView.SetFullPath(fullPath); + + selectedObjectAssetPathStr = assetPath; + selectedObjectAssetPath = assetPath; selectedObject = null; + if (selectedObjectAssetPath != NPath.Default) + { + selectedObject = AssetDatabase.LoadMainAssetAtPath(selectedObjectAssetPath.ToString()); + } + + InitializeAssetIcon(); + + // If we use selectedObjectAssetPath then this will break if the Unity project isn't located at the root + // of the git repository. + Repository.UpdateFileLog(fullPath) + .Start(); + } + + private void InitializeAssetIcon() + { Texture nodeIcon = null; - if (selectedObjectPath != NPath.Default) + if (selectedObjectAssetPath != NPath.Default) { - selectedObject = AssetDatabase.LoadMainAssetAtPath(path.ToString()); + selectedObject = AssetDatabase.LoadMainAssetAtPath(selectedObjectAssetPath.ToString()); - if (selectedObjectPath.DirectoryExists()) + if (selectedObjectAssetPath.DirectoryExists()) { nodeIcon = Styles.FolderIcon; } else { - nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedObjectPath.ToString()); + nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedObjectAssetPath.ToString()); } nodeIcon.hideFlags = HideFlags.HideAndDontSave; } selectedIcon = nodeIcon; - - Repository.UpdateFileLog(selectedObjectPath) - .Start(); } public override void Initialize(IApplicationManager applicationManager) @@ -131,14 +148,14 @@ public override void OnSelectionChange() if (!locked) { selectedObject = Selection.activeObject; - selectedObjectPath = NPath.Default; + selectedObjectAssetPath = NPath.Default; if (selectedObject != null) { - selectedObjectPath = AssetDatabase.GetAssetPath(selectedObject) + selectedObjectAssetPath = AssetDatabase.GetAssetPath(selectedObject) .ToNPath(); } - SetSelectedPath(selectedObjectPath); + SetSelectedPath(selectedObjectAssetPath); } } @@ -151,10 +168,21 @@ public override void Refresh() Redraw(); } + // Ideally we'd just call this in 'Initialize()' but that is too early in the domain reload and causes exceptions + private void RestoreFromDomainReload() + { + if (selectedObjectAssetPathStr != selectedObjectAssetPath && !string.IsNullOrEmpty(selectedObjectAssetPathStr)) + { + this.SetSelectedPath(selectedObjectAssetPathStr.ToNPath()); + } + } + public override void OnUI() { base.OnUI(); + RestoreFromDomainReload(); + if (selectedObject != null) { GUILayout.BeginVertical(Styles.HeaderStyle); @@ -209,7 +237,7 @@ private void DoHeaderGUI() GUILayout.Label(selectedIcon, GUILayout.Height(iconWidth), GUILayout.Width(iconHeight)); - GUILayout.Label(selectedObjectPath, Styles.FileHistoryLogTitleStyle); + GUILayout.Label(selectedObjectAssetPath, Styles.FileHistoryLogTitleStyle); GUILayout.FlexibleSpace(); diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs index 3cab7852d..8a11755a2 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs @@ -658,9 +658,16 @@ class FileHistoryView : HistoryBase [SerializeField] private GitLogEntry selectedEntry = GitLogEntry.Default; [SerializeField] private ChangesTree treeChanges = new ChangesTree { DisplayRootNode = false }; [SerializeField] private Vector2 detailsScroll; + [SerializeField] private NPath fullPath; [SerializeField] private CacheUpdateEvent lastFileLogChangedEvent; + public void SetFullPath(NPath inFullPath) + { + this.fullPath = inFullPath; + + } + public override void Refresh() { base.Refresh(); @@ -723,7 +730,14 @@ protected override void MaybeUpdateData() public override void OnGUI() { - DoHistoryGui(Rect.zero); + var lastRect = GUILayoutUtility.GetLastRect(); + DoHistoryGui(lastRect, entry => { + GenericMenu menu = new GenericMenu(); + string checkoutPrompt = string.Format("Checkout revision {0}", entry.ShortID); + menu.AddItem(new GUIContent(checkoutPrompt), false, () => { Checkout(entry); }); + menu.ShowAsContext(); + }, node => { + }); } protected override HistoryControl HistoryControl @@ -749,5 +763,42 @@ protected override Vector2 DetailsScroll get { return detailsScroll; } set { detailsScroll = value; } } + + private const string ConfirmCheckoutTitle = "Discard Changes?"; + private const string ConfirmCheckoutMessage = "You've made changes to file '{0}'. Overwrite these changes with the historical version?"; + private const string ConfirmCheckoutOK = "Overwrite"; + private const string ConfirmCheckoutCancel = "Cancel"; + + protected void Checkout(GitLogEntry entry) + { + GitClient.Status().ThenInUI((success, status) => + { + if (success) + { + bool promptUser = false; + + foreach (var e in status.Entries) + { + if (e.FullPath == this.fullPath) + { + // locally modified file; prompt user + promptUser = true; + break; + } + } + + if (!promptUser || EditorUtility.DisplayDialog(ConfirmCheckoutTitle, string.Format(ConfirmCheckoutMessage, this.fullPath), ConfirmCheckoutOK, ConfirmCheckoutCancel)) + { + GitClient.CheckoutVersion(entry.commitID, new string[] { this.fullPath }).ThenInUI((checkoutSuccess, result) => { + AssetDatabase.Refresh(); + }).Start(); + } + } + else + { + EditorUtility.DisplayDialog("Oops", "There was an error checking out this version of the file. Try again!", "OK"); + } + }).Start(); + } } } From 31127b044d5e4f920691dbd127406e1aadec8ab3 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Mon, 11 Feb 2019 17:46:49 -0500 Subject: [PATCH 16/19] Calling GitClient.CheckoutVersion through Repository --- src/GitHub.Api/Git/IRepository.cs | 1 + src/GitHub.Api/Git/Repository.cs | 1 + src/GitHub.Api/Git/RepositoryManager.cs | 8 ++++++++ .../Assets/Editor/GitHub.Unity/UI/HistoryView.cs | 6 +++--- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/GitHub.Api/Git/IRepository.cs b/src/GitHub.Api/Git/IRepository.cs index 90481b5b6..e762cf236 100644 --- a/src/GitHub.Api/Git/IRepository.cs +++ b/src/GitHub.Api/Git/IRepository.cs @@ -21,6 +21,7 @@ public interface IRepository : IEquatable, IDisposable, IBackedByCa ITask RequestLock(NPath file); ITask ReleaseLock(NPath file, bool force); ITask DiscardChanges(GitStatusEntry[] discardEntries); + ITask CheckoutVersion(string changeset, IList files); /// /// Gets the name of the repository. diff --git a/src/GitHub.Api/Git/Repository.cs b/src/GitHub.Api/Git/Repository.cs index 8c27f13fa..ba68c22e7 100644 --- a/src/GitHub.Api/Git/Repository.cs +++ b/src/GitHub.Api/Git/Repository.cs @@ -142,6 +142,7 @@ public ITask SetupRemote(string remote, string remoteUrl) public ITask RequestLock(NPath file) => repositoryManager.LockFile(file); public ITask ReleaseLock(NPath file, bool force) => repositoryManager.UnlockFile(file, force); public ITask DiscardChanges(GitStatusEntry[] gitStatusEntry) => repositoryManager.DiscardChanges(gitStatusEntry); + public ITask CheckoutVersion(string changeset, IList files) => repositoryManager.CheckoutVersion(changeset, files); public ITask RemoteAdd(string remote, string url) => repositoryManager.RemoteAdd(remote, url); public ITask RemoteRemove(string remote) => repositoryManager.RemoteRemove(remote); public ITask DeleteBranch(string branch, bool force) => repositoryManager.DeleteBranch(branch, force); diff --git a/src/GitHub.Api/Git/RepositoryManager.cs b/src/GitHub.Api/Git/RepositoryManager.cs index 47a6039fb..ea2d16a9a 100644 --- a/src/GitHub.Api/Git/RepositoryManager.cs +++ b/src/GitHub.Api/Git/RepositoryManager.cs @@ -38,6 +38,7 @@ public interface IRepositoryManager : IDisposable ITask LockFile(NPath file); ITask UnlockFile(NPath file, bool force); ITask DiscardChanges(GitStatusEntry[] gitStatusEntries); + ITask CheckoutVersion(string changeset, IList files); ITask UpdateGitLog(); ITask UpdateGitStatus(); ITask UpdateGitAheadBehindStatus(); @@ -345,6 +346,13 @@ public ITask DiscardChanges(GitStatusEntry[] gitStatusEntries) return HookupHandlers(task, true); } + public ITask CheckoutVersion(string changeset, IList files) + { + var task = GitClient.CheckoutVersion(changeset, files) + .Then(() => DataNeedsRefreshing?.Invoke(CacheType.GitStatus)); + return HookupHandlers(task, false); + } + public ITask UpdateGitLog() { var task = GitClient.Log() diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs index 8a11755a2..1e37f3ccb 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs @@ -789,9 +789,9 @@ protected void Checkout(GitLogEntry entry) if (!promptUser || EditorUtility.DisplayDialog(ConfirmCheckoutTitle, string.Format(ConfirmCheckoutMessage, this.fullPath), ConfirmCheckoutOK, ConfirmCheckoutCancel)) { - GitClient.CheckoutVersion(entry.commitID, new string[] { this.fullPath }).ThenInUI((checkoutSuccess, result) => { - AssetDatabase.Refresh(); - }).Start(); + Repository.CheckoutVersion(entry.commitID, new string[] { fullPath }) + .ThenInUI(AssetDatabase.Refresh) + .Start(); } } else From b2bb6ce60b8a133db2d996be4b271dace3ba0c33 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Mon, 11 Feb 2019 19:00:09 -0500 Subject: [PATCH 17/19] Using the cache objects to keep file Status --- .../GitHub.Unity/UI/FileHistoryWindow.cs | 74 ++++++++----------- .../Editor/GitHub.Unity/UI/HistoryView.cs | 68 ++++++++--------- 2 files changed, 62 insertions(+), 80 deletions(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index a00c12b9d..4445b917e 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -39,53 +39,27 @@ private static bool GitFileHistoryValidation() [SerializeField] private FileHistoryView fileHistoryView = new FileHistoryView(); [SerializeField] private UnityEngine.Object selectedObject; [SerializeField] private NPath selectedObjectAssetPath; - [SerializeField] private string selectedObjectAssetPathStr; public void SetSelectedPath(NPath assetPath) { - var fullPath = Application.dataPath.ToNPath().Parent.Combine(assetPath); - this.fileHistoryView.SetFullPath(fullPath); + NPath repositoryPath = NPath.Default; - selectedObjectAssetPathStr = assetPath; selectedObjectAssetPath = assetPath; selectedObject = null; if (selectedObjectAssetPath != NPath.Default) { selectedObject = AssetDatabase.LoadMainAssetAtPath(selectedObjectAssetPath.ToString()); + + repositoryPath = Environment.GetRepositoryPath(assetPath); } - InitializeAssetIcon(); + LoadSelectedIcon(); - // If we use selectedObjectAssetPath then this will break if the Unity project isn't located at the root - // of the git repository. - Repository.UpdateFileLog(fullPath) + Repository.UpdateFileLog(repositoryPath) .Start(); } - private void InitializeAssetIcon() - { - Texture nodeIcon = null; - - if (selectedObjectAssetPath != NPath.Default) - { - selectedObject = AssetDatabase.LoadMainAssetAtPath(selectedObjectAssetPath.ToString()); - - if (selectedObjectAssetPath.DirectoryExists()) - { - nodeIcon = Styles.FolderIcon; - } - else - { - nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedObjectAssetPath.ToString()); - } - - nodeIcon.hideFlags = HideFlags.HideAndDontSave; - } - - selectedIcon = nodeIcon; - } - public override void Initialize(IApplicationManager applicationManager) { base.Initialize(applicationManager); @@ -102,6 +76,8 @@ public override void OnEnable() { base.OnEnable(); + LoadSelectedIcon(); + if (fileHistoryView != null) fileHistoryView.OnEnable(); } @@ -153,9 +129,9 @@ public override void OnSelectionChange() { selectedObjectAssetPath = AssetDatabase.GetAssetPath(selectedObject) .ToNPath(); - } - SetSelectedPath(selectedObjectAssetPath); + SetSelectedPath(selectedObjectAssetPath); + } } } @@ -168,21 +144,10 @@ public override void Refresh() Redraw(); } - // Ideally we'd just call this in 'Initialize()' but that is too early in the domain reload and causes exceptions - private void RestoreFromDomainReload() - { - if (selectedObjectAssetPathStr != selectedObjectAssetPath && !string.IsNullOrEmpty(selectedObjectAssetPathStr)) - { - this.SetSelectedPath(selectedObjectAssetPathStr.ToNPath()); - } - } - public override void OnUI() { base.OnUI(); - RestoreFromDomainReload(); - if (selectedObject != null) { GUILayout.BeginVertical(Styles.HeaderStyle); @@ -216,6 +181,27 @@ private void DetachHandlers(IRepository repository) return; } + private void LoadSelectedIcon() + { + Texture nodeIcon = null; + + if (selectedObjectAssetPath != NPath.Default) + { + if (selectedObjectAssetPath.DirectoryExists()) + { + nodeIcon = Styles.FolderIcon; + } + else + { + nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedObjectAssetPath.ToString()); + } + + nodeIcon.hideFlags = HideFlags.HideAndDontSave; + } + + selectedIcon = nodeIcon; + } + private void ShowButton(Rect rect) { EditorGUI.BeginChangeCheck(); diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs index 1e37f3ccb..c4b326c1e 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs @@ -651,6 +651,7 @@ private GenericMenu CreateChangesTreeContextMenu(ChangesTreeNode node) class FileHistoryView : HistoryBase { [SerializeField] private bool currentFileLogHasUpdate; + [SerializeField] private bool currentStatusEntriesHasUpdate; [SerializeField] private GitFileLog gitFileLog; @@ -658,16 +659,11 @@ class FileHistoryView : HistoryBase [SerializeField] private GitLogEntry selectedEntry = GitLogEntry.Default; [SerializeField] private ChangesTree treeChanges = new ChangesTree { DisplayRootNode = false }; [SerializeField] private Vector2 detailsScroll; - [SerializeField] private NPath fullPath; + [SerializeField] private List gitStatusEntries = new List(); + [SerializeField] private CacheUpdateEvent lastStatusEntriesChangedEvent; [SerializeField] private CacheUpdateEvent lastFileLogChangedEvent; - public void SetFullPath(NPath inFullPath) - { - this.fullPath = inFullPath; - - } - public override void Refresh() { base.Refresh(); @@ -686,6 +682,17 @@ private void RepositoryOnFileLogChanged(CacheUpdateEvent cacheUpdateEvent) } } + private void RepositoryOnStatusEntriesChanged(CacheUpdateEvent cacheUpdateEvent) + { + if (!lastStatusEntriesChangedEvent.Equals(cacheUpdateEvent)) + { + ReceivedEvent(cacheUpdateEvent.cacheType); + lastStatusEntriesChangedEvent = cacheUpdateEvent; + currentStatusEntriesHasUpdate = true; + Redraw(); + } + } + protected override void AttachHandlers(IRepository repository) { if (repository == null) @@ -694,6 +701,7 @@ protected override void AttachHandlers(IRepository repository) } repository.FileLogChanged += RepositoryOnFileLogChanged; + repository.StatusEntriesChanged += RepositoryOnStatusEntriesChanged; } protected override void DetachHandlers(IRepository repository) @@ -704,6 +712,7 @@ protected override void DetachHandlers(IRepository repository) } repository.FileLogChanged -= RepositoryOnFileLogChanged; + repository.FileLogChanged -= RepositoryOnStatusEntriesChanged; } protected override void ValidateCachedData(IRepository repository) @@ -726,6 +735,13 @@ protected override void MaybeUpdateData() BuildHistoryControl(0, gitFileLog.LogEntries); } + + if (currentStatusEntriesHasUpdate) + { + currentStatusEntriesHasUpdate = false; + + gitStatusEntries = Repository.CurrentChanges; + } } public override void OnGUI() @@ -734,7 +750,7 @@ public override void OnGUI() DoHistoryGui(lastRect, entry => { GenericMenu menu = new GenericMenu(); string checkoutPrompt = string.Format("Checkout revision {0}", entry.ShortID); - menu.AddItem(new GUIContent(checkoutPrompt), false, () => { Checkout(entry); }); + menu.AddItem(new GUIContent(checkoutPrompt), false, () => Checkout(entry.commitID)); menu.ShowAsContext(); }, node => { }); @@ -769,36 +785,16 @@ protected override Vector2 DetailsScroll private const string ConfirmCheckoutOK = "Overwrite"; private const string ConfirmCheckoutCancel = "Cancel"; - protected void Checkout(GitLogEntry entry) + protected void Checkout(string commitId) { - GitClient.Status().ThenInUI((success, status) => - { - if (success) - { - bool promptUser = false; - - foreach (var e in status.Entries) - { - if (e.FullPath == this.fullPath) - { - // locally modified file; prompt user - promptUser = true; - break; - } - } + var promptUser = gitStatusEntries.Count > 0 && gitStatusEntries.Any(statusEntry => gitFileLog.Path.Equals(statusEntry.Path.ToNPath())); - if (!promptUser || EditorUtility.DisplayDialog(ConfirmCheckoutTitle, string.Format(ConfirmCheckoutMessage, this.fullPath), ConfirmCheckoutOK, ConfirmCheckoutCancel)) - { - Repository.CheckoutVersion(entry.commitID, new string[] { fullPath }) - .ThenInUI(AssetDatabase.Refresh) - .Start(); - } - } - else - { - EditorUtility.DisplayDialog("Oops", "There was an error checking out this version of the file. Try again!", "OK"); - } - }).Start(); + if (!promptUser || EditorUtility.DisplayDialog(ConfirmCheckoutTitle, string.Format(ConfirmCheckoutMessage, gitFileLog.Path), ConfirmCheckoutOK, ConfirmCheckoutCancel)) + { + Repository.CheckoutVersion(commitId, new string[] { gitFileLog.Path }) + .ThenInUI(AssetDatabase.Refresh) + .Start(); + } } } } From ae7548495bae72fa2f33d0b6f5469a3452836d28 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Tue, 12 Feb 2019 11:23:45 -0500 Subject: [PATCH 18/19] Using string over NPath; NPath is not serializable by Unity --- src/GitHub.Api/Git/GitClient.cs | 5 +-- src/GitHub.Api/Git/GitFileLog.cs | 8 ++--- src/GitHub.Api/Git/IRepository.cs | 2 +- src/GitHub.Api/Git/Repository.cs | 4 +-- src/GitHub.Api/Git/RepositoryManager.cs | 4 +-- src/GitHub.Api/Git/Tasks/GitLogTask.cs | 4 +-- .../GitHub.Unity/UI/FileHistoryWindow.cs | 35 ++++++++++--------- 7 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/GitHub.Api/Git/GitClient.cs b/src/GitHub.Api/Git/GitClient.cs index 50deee430..ecb9ec1e0 100644 --- a/src/GitHub.Api/Git/GitClient.cs +++ b/src/GitHub.Api/Git/GitClient.cs @@ -262,9 +262,10 @@ public interface IGitClient /// /// Executes `git log -- ` to get the history of a specific file. /// + /// /// A custom output processor instance /// of output - ITask> LogFile(NPath file, BaseOutputListProcessor processor = null); + ITask> LogFile(string file, BaseOutputListProcessor processor = null); /// /// Executes `git --version` to get the git version. @@ -358,7 +359,7 @@ public ITask> Log(BaseOutputListProcessor process } /// - public ITask> LogFile(NPath file, BaseOutputListProcessor processor = null) + public ITask> LogFile(string file, BaseOutputListProcessor processor = null) { if (file == NPath.Default) { diff --git a/src/GitHub.Api/Git/GitFileLog.cs b/src/GitHub.Api/Git/GitFileLog.cs index 053aff740..6795d6c4d 100644 --- a/src/GitHub.Api/Git/GitFileLog.cs +++ b/src/GitHub.Api/Git/GitFileLog.cs @@ -6,18 +6,18 @@ namespace GitHub.Unity [Serializable] public struct GitFileLog { - public static GitFileLog Default = new GitFileLog(NPath.Default, new List(0)); + public static GitFileLog Default = new GitFileLog(null, new List(0)); - public NPath path; + public string path; public List logEntries; - public GitFileLog(NPath path, List logEntries) + public GitFileLog(string path, List logEntries) { this.path = path; this.logEntries = logEntries; } - public NPath Path + public string Path { get { return path; } set { path = value; } diff --git a/src/GitHub.Api/Git/IRepository.cs b/src/GitHub.Api/Git/IRepository.cs index e762cf236..7bd579d37 100644 --- a/src/GitHub.Api/Git/IRepository.cs +++ b/src/GitHub.Api/Git/IRepository.cs @@ -81,8 +81,8 @@ public interface IRepository : IEquatable, IDisposable, IBackedByCa ITask DeleteBranch(string branch, bool force); ITask CreateBranch(string branch, string baseBranch); ITask SwitchBranch(string branch); + ITask UpdateFileLog(string path); void Refresh(CacheType cacheType); event Action OnProgress; - ITask UpdateFileLog(NPath path); } } diff --git a/src/GitHub.Api/Git/Repository.cs b/src/GitHub.Api/Git/Repository.cs index ba68c22e7..e4b2a3ddd 100644 --- a/src/GitHub.Api/Git/Repository.cs +++ b/src/GitHub.Api/Git/Repository.cs @@ -25,7 +25,7 @@ sealed class Repository : IEquatable, IRepository private HashSet cacheInvalidationRequests = new HashSet(); private Dictionary> cacheUpdateEvents; private ProgressReporter progressReporter = new ProgressReporter(); - private NPath lastFileLog = NPath.Default; + private string lastFileLog; public event Action LogChanged; public event Action FileLogChanged; @@ -148,7 +148,7 @@ public ITask SetupRemote(string remote, string remoteUrl) public ITask DeleteBranch(string branch, bool force) => repositoryManager.DeleteBranch(branch, force); public ITask CreateBranch(string branch, string baseBranch) => repositoryManager.CreateBranch(branch, baseBranch); public ITask SwitchBranch(string branch) => repositoryManager.SwitchBranch(branch); - public ITask UpdateFileLog(NPath path) + public ITask UpdateFileLog(string path) { lastFileLog = path; return repositoryManager.UpdateFileLog(path); diff --git a/src/GitHub.Api/Git/RepositoryManager.cs b/src/GitHub.Api/Git/RepositoryManager.cs index ea2d16a9a..d764fa010 100644 --- a/src/GitHub.Api/Git/RepositoryManager.cs +++ b/src/GitHub.Api/Git/RepositoryManager.cs @@ -45,7 +45,7 @@ public interface IRepositoryManager : IDisposable ITask UpdateLocks(); ITask UpdateRepositoryInfo(); ITask UpdateBranches(); - ITask UpdateFileLog(NPath path); + ITask UpdateFileLog(string path); int WaitForEvents(); @@ -366,7 +366,7 @@ public ITask UpdateGitLog() return HookupHandlers(task, false); } - public ITask UpdateFileLog(NPath path) + public ITask UpdateFileLog(string path) { var task = GitClient.LogFile(path) .Then((success, logEntries) => diff --git a/src/GitHub.Api/Git/Tasks/GitLogTask.cs b/src/GitHub.Api/Git/Tasks/GitLogTask.cs index a55e72e5c..e5d29dfab 100644 --- a/src/GitHub.Api/Git/Tasks/GitLogTask.cs +++ b/src/GitHub.Api/Git/Tasks/GitLogTask.cs @@ -16,7 +16,7 @@ public GitLogTask(IGitObjectFactory gitObjectFactory, arguments = baseArguments; } - public GitLogTask(NPath file, + public GitLogTask(string file, IGitObjectFactory gitObjectFactory, CancellationToken token, BaseOutputListProcessor processor = null) : base(token, processor ?? new LogEntryOutputProcessor(gitObjectFactory)) @@ -24,7 +24,7 @@ public GitLogTask(NPath file, Name = TaskName; arguments = baseArguments; arguments += " -- "; - arguments += " \"" + file.ToString(SlashMode.Forward) + "\""; + arguments += " \"" + file + "\""; } public override string ProcessArguments diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index 4445b917e..ec0094c6f 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -38,25 +38,28 @@ private static bool GitFileHistoryValidation() [SerializeField] private bool locked; [SerializeField] private FileHistoryView fileHistoryView = new FileHistoryView(); [SerializeField] private UnityEngine.Object selectedObject; - [SerializeField] private NPath selectedObjectAssetPath; + [SerializeField] private string selectedObjectAssetPath; + [SerializeField] private string selectedObjectRepositoryPath; - public void SetSelectedPath(NPath assetPath) + public void SetSelectedPath(string assetPath) { - NPath repositoryPath = NPath.Default; - - selectedObjectAssetPath = assetPath; selectedObject = null; + selectedObjectAssetPath = null; + selectedObjectRepositoryPath = null; if (selectedObjectAssetPath != NPath.Default) { - selectedObject = AssetDatabase.LoadMainAssetAtPath(selectedObjectAssetPath.ToString()); + selectedObjectAssetPath = assetPath; + selectedObject = AssetDatabase.LoadMainAssetAtPath(selectedObjectAssetPath); - repositoryPath = Environment.GetRepositoryPath(assetPath); + selectedObjectRepositoryPath = + Environment.GetRepositoryPath(assetPath.ToNPath()) + .ToString(SlashMode.Forward); } LoadSelectedIcon(); - Repository.UpdateFileLog(repositoryPath) + Repository.UpdateFileLog(selectedObjectRepositoryPath) .Start(); } @@ -124,14 +127,14 @@ public override void OnSelectionChange() if (!locked) { selectedObject = Selection.activeObject; - selectedObjectAssetPath = NPath.Default; + + string assetPath = null; if (selectedObject != null) { - selectedObjectAssetPath = AssetDatabase.GetAssetPath(selectedObject) - .ToNPath(); - - SetSelectedPath(selectedObjectAssetPath); + assetPath = AssetDatabase.GetAssetPath(selectedObject); } + + SetSelectedPath(assetPath); } } @@ -185,15 +188,15 @@ private void LoadSelectedIcon() { Texture nodeIcon = null; - if (selectedObjectAssetPath != NPath.Default) + if (!string.IsNullOrEmpty(selectedObjectAssetPath)) { - if (selectedObjectAssetPath.DirectoryExists()) + if (selectedObjectAssetPath.ToNPath().DirectoryExists()) { nodeIcon = Styles.FolderIcon; } else { - nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedObjectAssetPath.ToString()); + nodeIcon = UnityEditorInternal.InternalEditorUtility.GetIconForFile(selectedObjectAssetPath); } nodeIcon.hideFlags = HideFlags.HideAndDontSave; From a1ec31c8d9331a6d8395a1feb3404c9694a1bba9 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Wed, 13 Feb 2019 08:19:43 -0500 Subject: [PATCH 19/19] Design changes Co-authored-by: Don Okuda --- .../Editor/GitHub.Unity/UI/FileHistoryWindow.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs index ec0094c6f..6979c58dc 100644 --- a/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs +++ b/src/UnityExtension/Assets/Editor/GitHub.Unity/UI/FileHistoryWindow.cs @@ -225,19 +225,22 @@ private void DoHeaderGUI() var iconHeight = 32; GUILayout.Label(selectedIcon, GUILayout.Height(iconWidth), GUILayout.Width(iconHeight)); - - GUILayout.Label(selectedObjectAssetPath, Styles.FileHistoryLogTitleStyle); - - GUILayout.FlexibleSpace(); + GUILayout.Space(16); GUILayout.BeginVertical(); { - GUILayout.Space(16); + GUILayout.Label(selectedObjectAssetPath, Styles.FileHistoryLogTitleStyle); - if (GUILayout.Button("Show in Project")) + GUILayout.BeginHorizontal(); { - EditorGUIUtility.PingObject(selectedObject); + GUILayout.FlexibleSpace(); + + if (GUILayout.Button("Show in Project")) + { + EditorGUIUtility.PingObject(selectedObject); + } } + GUILayout.EndHorizontal(); } GUILayout.EndVertical(); }