From 61ee0072669f015a8dbc73920eddbbf24c924ed8 Mon Sep 17 00:00:00 2001 From: Scott Doxey Date: Thu, 9 Jan 2020 19:28:01 -0500 Subject: [PATCH 1/4] Added locked icon. --- .../Scripts/CustomEditor/GitIcons.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitIcons.cs b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitIcons.cs index 6c753da..bfe05f9 100644 --- a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitIcons.cs +++ b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitIcons.cs @@ -63,6 +63,31 @@ public static Texture2D Untracked } + private static Texture2D _locked; + + public static Texture2D Locked + { + + get + { + if (_locked != null) + { + + return _locked; + + } + + _locked = new Texture2D(SIZE, SIZE); + + _locked.LoadImage(Convert.FromBase64String( + "iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAyVBMVEUtQZU6TJtte7WapMy6wdzZ3Ovq7PT19vr8/P0/UZ6GksLQ1ef9/f7///9BU5+psdP6+/ybpMz29/qAjL7x8vcxRZers9Q/Up7O0+ZSYqfo6vPn6vNAUp7n6fI0R5jS1ui4vtvb3u2cpc1qeLRWZqmPmcb5+fyiq9BIWaKvt9dEVqGrs9X3+Pt3hLpQYaZVZanp6/TCx+BUZKhMXaRserWkrdHj5fDx8/g8T5yMl8V/i749T52mrtLJzuPHzOKHksJjcrDv8PdNXqVWCyDhAAABVUlEQVR4AezS1YFbMQAEwDXjHp+Z8ZljZuy/qHxJZpaCmhoGfy/DMAzDMAzDsNkdTpfb4/W4XU6H3YZfy+cPBLkrGPD78Mu8vL7x2NvrC34J2/sHT/t4t0G/zy+e9/UJzb5DvCz0DZ3CEV4TCUOfaIzXxaPQJZHkLZIJ6JFK8zbpFLTIcF82ly+8fL8U8rks92WgQ5G7SmULW1a5xF1FqJfwcEelin3VCnd4ElCuxq16A8cadW7VoFrTSynWwimtH5S8TSjWpuTp4LSOh1IbanUpBXs4pxek1IVS75T6OK9PyQGlBhSGI5w3GlIYQCWL0hiXjClZUGhCwTvFJVMvhQkUmlGY47I5hRkUWlDw47IlhYWegytcttKzcE1hg8s2FNZQgAr8bHeOBQAAAAAG+VtPY0cRJCAgICAgICAgICAgICAgICAgICAgICAgICAgMA8AAAAQnY7wX9sqolIAAAAASUVORK5CYII=" + )); + + return _locked; + } + + } + } } From 2465e5a2522381df187c22ffc7d6b76aa96c26ee Mon Sep 17 00:00:00 2001 From: Scott Doxey Date: Thu, 9 Jan 2020 19:30:32 -0500 Subject: [PATCH 2/4] Added LockedFiles method. --- .../Scripts/CustomEditor/Git.cs | 32 +++++++++++++++ .../Scripts/CustomEditor/Locks.cs | 39 +++++++++++++++++++ .../Scripts/CustomEditor/Locks.cs.meta | 11 ++++++ 3 files changed, 82 insertions(+) create mode 100644 Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Locks.cs create mode 100644 Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Locks.cs.meta diff --git a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Git.cs b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Git.cs index 4ac6bce..6595d65 100644 --- a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Git.cs +++ b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Git.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.IO; using System.Threading.Tasks; +using UnityEngine; namespace CandyCoded.GitStatus { @@ -15,8 +16,12 @@ public static class Git #if UNITY_EDITOR_WIN private static string GitPath => @"C:\Program Files\Git\bin\git.exe"; + + private static string GitLFSPath => @"C:\Program Files\Git LFS\git-lfs.exe"; #else private static string GitPath => "/usr/local/bin/git"; + + private static string GitLFSPath => "/usr/local/bin/git-lfs"; #endif private static string RepoPath => $"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}"; @@ -117,6 +122,33 @@ public static async Task Init() } + public static async Task LockedFiles() + { + + var process = await GenerateProcessAsync(GitLFSPath, "locks --json"); + + process?.WaitForExit(); + + var locked = new List(); + + var locks = JsonUtility.FromJson($@"{{""locks"":{process?.StandardOutput.ReadToEnd()}}}").locks; + + if (locks != null) + { + + for (var i = 0; i < locks.Length; i += 1) + { + + locked.Add(locks[i].path); + + } + + } + + return locked.ToArray(); + + } + public static async Task Status() { diff --git a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Locks.cs b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Locks.cs new file mode 100644 index 0000000..f876dae --- /dev/null +++ b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Locks.cs @@ -0,0 +1,39 @@ +// Copyright (c) Scott Doxey. All Rights Reserved. Licensed under the MIT License. See LICENSE in the project root for license information. + +#if UNITY_EDITOR +using System; + +namespace CandyCoded.GitStatus +{ + + public struct Locks + { + + public Lock[] locks; + + } + + [Serializable] + public struct Lock + { + + [Serializable] + public struct Owner + { + + public string name; + + } + + public long id; + + public string path; + + public Owner owner; + + public string locked_at; + + } + +} +#endif diff --git a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Locks.cs.meta b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Locks.cs.meta new file mode 100644 index 0000000..16048e5 --- /dev/null +++ b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Locks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e74918d63584d4992f634c1f98de998 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From db99f2c36a7455e3c95ac6cd6fd344812be5c7a0 Mon Sep 17 00:00:00 2001 From: Scott Doxey Date: Thu, 9 Jan 2020 19:35:44 -0500 Subject: [PATCH 3/4] Added locked files to status panel and project panel. --- .../CandyCoded.GitStatus/Scripts/CustomEditor/GitStatus.cs | 3 +++ .../Scripts/CustomEditor/GitStatusPanel.cs | 1 + .../Scripts/CustomEditor/ProjectPanel.cs | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitStatus.cs b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitStatus.cs index 7588e0b..74e9862 100644 --- a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitStatus.cs +++ b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitStatus.cs @@ -22,6 +22,8 @@ public static class GitStatus public static string[] changedFiles = { }; + public static string[] lockedFiles = { }; + public static string[] untrackedFiles = { }; public static DateTime lastUpdated = DateTime.Now; @@ -66,6 +68,7 @@ public static async void UpdateAsync() branch = await Git.Branch(); branches = await Git.Branches(); changedFiles = await Git.ChangedFiles(); + lockedFiles = await Git.LockedFiles(); untrackedFiles = await Git.UntrackedFiles(); lastUpdated = DateTime.Now; diff --git a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitStatusPanel.cs b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitStatusPanel.cs index 365a8ee..fd58790 100644 --- a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitStatusPanel.cs +++ b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitStatusPanel.cs @@ -94,6 +94,7 @@ private void OnGUI() GUILayout.Label($"Number of Changes: {GitStatus.changedFiles?.Length}"); GUILayout.Label($"Untracked Files: {GitStatus.untrackedFiles?.Length}"); + GUILayout.Label($"Locked Files: {GitStatus.lockedFiles?.Length}"); GUILayout.Label($"Last Updated: {GitStatus.lastUpdated}"); if (GUILayout.Button("Refresh")) diff --git a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/ProjectPanel.cs b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/ProjectPanel.cs index d7893bb..f328993 100644 --- a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/ProjectPanel.cs +++ b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/ProjectPanel.cs @@ -63,6 +63,12 @@ private static void ProjectWindowItemOnGui(string guid, Rect selectionRect) GUI.DrawTexture(rect, GitIcons.Untracked, ScaleMode.ScaleToFit); } + else if (GitStatus.lockedFiles.Contains(path)) + { + + GUI.DrawTexture(rect, GitIcons.Locked, ScaleMode.ScaleToFit); + + } } From be89139aeda9fc07dff06a61cde08b0a374b03af Mon Sep 17 00:00:00 2001 From: Scott Doxey Date: Thu, 9 Jan 2020 19:42:55 -0500 Subject: [PATCH 4/4] Added lock, unlock and unlock force menu items. --- .../Scripts/CustomEditor/Git.cs | 38 +++++++ .../Scripts/CustomEditor/GitMenuItems.cs | 98 +++++++++++++++++-- 2 files changed, 130 insertions(+), 6 deletions(-) diff --git a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Git.cs b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Git.cs index 6595d65..8473ccd 100644 --- a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Git.cs +++ b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/Git.cs @@ -115,6 +115,17 @@ public static async Task DiscardChanges(string path) } + public static async Task ForceUnlockFile(string path) + { + + var process = + await GenerateProcessAsync(GitLFSPath, + $@"unlock ""{path.Replace(RepoPath, "")}"" --force"); + + process?.WaitForExit(); + + } + public static async Task Init() { @@ -149,6 +160,23 @@ public static async Task LockedFiles() } + public static async Task LockFile(string path) + { + + var process = await GenerateProcessAsync(GitLFSPath, + $@"lock ""{path.Replace(RepoPath, "")}"""); + + if (process?.StandardError.ReadLine() is string line && line.StartsWith("Lock failed: missing protocol")) + { + + throw new Exception("Locking requires git repo has been pushed to a remote."); + + } + + process?.WaitForExit(); + + } + public static async Task Status() { @@ -165,6 +193,16 @@ public static async Task Status() } + public static async Task UnlockFile(string path) + { + + var process = await GenerateProcessAsync(GitLFSPath, + $@"unlock ""{path.Replace(RepoPath, "")}"""); + + process?.WaitForExit(); + + } + public static async Task UntrackedFiles() { diff --git a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitMenuItems.cs b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitMenuItems.cs index a96e5ff..ef387bf 100644 --- a/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitMenuItems.cs +++ b/Assets/Plugins/CandyCoded.GitStatus/Scripts/CustomEditor/GitMenuItems.cs @@ -3,6 +3,7 @@ #if UNITY_EDITOR using System; using System.IO; +using System.Linq; using UnityEditor; namespace CandyCoded.GitStatus @@ -13,10 +14,17 @@ public static class GitMenuItems private const int PRIORITY = 5000; - private static string GetSelectedPath() + private static string GetSelectedAbsolutePath() { - return Path.Combine(Environment.CurrentDirectory, AssetDatabase.GetAssetPath(Selection.activeObject)); + return Path.Combine(Environment.CurrentDirectory, GetSelectedRelativePath()); + + } + + private static string GetSelectedRelativePath() + { + + return AssetDatabase.GetAssetPath(Selection.activeObject); } @@ -28,7 +36,7 @@ private static async void DiscardChanges() try { - await Git.DiscardChanges(GetSelectedPath()); + await Git.DiscardChanges(GetSelectedAbsolutePath()); } catch (Exception error) @@ -45,7 +53,8 @@ private static async void DiscardChanges() private static bool ValidateDiscardChanges() { - return Selection.activeObject && File.Exists(GetSelectedPath()); + return Selection.activeObject && File.Exists(GetSelectedAbsolutePath()) && + GitStatus.changedFiles.Contains(GetSelectedRelativePath()); } @@ -63,7 +72,7 @@ private static async void DiscardAllChanges() try { - await Git.DiscardChanges(GetSelectedPath()); + await Git.DiscardChanges(GetSelectedAbsolutePath()); } catch (Exception error) @@ -82,7 +91,84 @@ private static async void DiscardAllChanges() private static bool ValidateDiscardAllChanges() { - return Selection.activeObject && Directory.Exists(GetSelectedPath()); + return Selection.activeObject && Directory.Exists(GetSelectedAbsolutePath()); + + } + + [MenuItem("Git/Lock File", true, PRIORITY)] + [MenuItem("Assets/Lock File", true, PRIORITY)] + private static bool ValidateLockFile() + { + + return Selection.activeObject && File.Exists(GetSelectedAbsolutePath()) && + !GitStatus.lockedFiles.Contains(GetSelectedRelativePath()); + + } + + [MenuItem("Git/Lock File", false, PRIORITY)] + [MenuItem("Assets/Lock File", false, PRIORITY)] + private static async void LockFile() + { + + try + { + + await Git.LockFile(GetSelectedAbsolutePath()); + + } + catch (Exception error) + { + + EditorUtility.DisplayDialog("Error", error.Message, "Ok"); + + } + + } + + [MenuItem("Git/Unlock File", true, PRIORITY)] + [MenuItem("Assets/Unlock File", true, PRIORITY)] + private static bool ValidateUnlockFile() + { + + return Selection.activeObject && File.Exists(GetSelectedAbsolutePath()) && + GitStatus.lockedFiles.Contains(GetSelectedRelativePath()); + + } + + [MenuItem("Git/Unlock File", false, PRIORITY)] + [MenuItem("Assets/Unlock File", false, PRIORITY)] + private static async void UnlockFile() + { + + await Git.UnlockFile(GetSelectedAbsolutePath()); + + } + + [MenuItem("Git/Force Unlock File", true, PRIORITY)] + [MenuItem("Assets/Force Unlock File", true, PRIORITY)] + private static bool ValidateForceUnlockFile() + { + + return Selection.activeObject && File.Exists(GetSelectedAbsolutePath()) && + GitStatus.lockedFiles.Contains(GetSelectedRelativePath()); + + } + + [MenuItem("Git/Force Unlock File", false, PRIORITY)] + [MenuItem("Assets/Force Unlock File", false, PRIORITY)] + private static async void ForceUnlockFile() + { + + if (EditorUtility.DisplayDialog( + "Force unlock file", + $"Are you sure you want to force unlock {Selection.activeObject.name}?", + "Yes", + "Cancel")) + { + + await Git.ForceUnlockFile(GetSelectedAbsolutePath()); + + } }