Skip to content

Commit

Permalink
Merge pull request #1 from ultraleap/feature/git-missing-ref-lookup
Browse files Browse the repository at this point in the history
Add missing ref lookup via libgit2sharp
  • Loading branch information
Craig-J authored Jun 28, 2022
2 parents 3f7d7b3 + 885a7b5 commit d09af38
Show file tree
Hide file tree
Showing 16 changed files with 375 additions and 29 deletions.
20 changes: 17 additions & 3 deletions Editor/DependencyBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using UnityEditor.PackageManager;
using UnityEngine;

namespace Leap.Unity
namespace Leap.Unity.Dependency
{
internal class DependencyBrowser : EditorWindow
{
Expand Down Expand Up @@ -45,6 +45,11 @@ internal class DependencyBrowser : EditorWindow
private bool filterToOnlyUnused;
private bool filterToAssetsMissingRefs;
private bool showExternalPackages;

private int repositoryLookupCommitLimit;
private string repositoryLookupCommitLimitKey = "UltraleapDependencyBrowserGitRepoLookupCommitLimit";
private string repositoryLookupRoot;
private readonly string repositoryLookupRootKey = "UltraleapDependencyBrowserGitRepoLookupRoot";

private event Action resizeOccurred;

Expand Down Expand Up @@ -81,7 +86,8 @@ private void OnEnable()
currentVerticalDistance = windowSize.y / 2f;
horizontalResizeInteractionRect = new Rect(currentHorizontalDistance, 0f, 8f, windowSize.y);
verticalResizeInteractionRect = new Rect(currentHorizontalDistance + resizerSpacing, currentVerticalDistance, windowSize.x - currentHorizontalDistance - resizerSpacing, 8f);

repositoryLookupRoot = EditorPrefs.GetString(repositoryLookupRootKey, Environment.CurrentDirectory);
repositoryLookupCommitLimit = EditorPrefs.GetInt(repositoryLookupCommitLimitKey, 500);

void UpdateResizeInteractionRects()
{
Expand Down Expand Up @@ -112,7 +118,15 @@ void DrawLeftColumn()
filterToAssetsMissingRefs = GUILayout.Toggle(filterToAssetsMissingRefs, "Filter to assets with missing references");
showExternalPackages = GUILayout.Toggle(showExternalPackages, "Show external packages");
editor.DrawSortPopup();


repositoryLookupRoot = GUILayout.TextField(repositoryLookupRoot);
EditorPrefs.SetString(repositoryLookupRootKey, repositoryLookupRoot);
GUILayout.BeginHorizontal();
repositoryLookupCommitLimit = EditorGUILayout.IntField(repositoryLookupCommitLimit);
EditorPrefs.SetInt(repositoryLookupCommitLimitKey, repositoryLookupCommitLimit);
editor.DrawGitLookupMissingRefButton(repositoryLookupRoot, repositoryLookupCommitLimit);
GUILayout.EndHorizontal();

GUILayout.Label($"Current selection: {editor.Selected}");
GUILayout.Label("Select an asset or folder");
_selectionTreeViewDrawer ??= editor.CreateNodeViewDrawer(
Expand Down
2 changes: 1 addition & 1 deletion Editor/DependencyFolderNode.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Linq;

namespace Leap.Unity
namespace Leap.Unity.Dependency
{
internal class DependencyFolderNode : DependencyNodeBase
{
Expand Down
53 changes: 52 additions & 1 deletion Editor/DependencyGuiUtilities.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using LibGit2Sharp;
using UnityEngine;
using Tree = LibGit2Sharp.Tree;

namespace Leap.Unity
namespace Leap.Unity.Dependency
{
internal static class DependencyGuiUtilities
{
Expand Down Expand Up @@ -80,5 +84,52 @@ public static string BytesToString(long byteCount)
double num = Math.Round(bytes / Math.Pow(1024, place), 1);
return (Math.Sign(byteCount) * num) + suf[place];
}

public static Dictionary<DependencyNode, List<string>> LookupMissingReferences(IReadOnlyList<DependencyNode> missingReferences, string repositoryDiscoverRootPath, int commitLimit)
{
if (!(Repository.Discover(repositoryDiscoverRootPath) is { } repoDirectory)) return null;
var repo = new Repository(repoDirectory);
var checkedBlobs = new HashSet<string>();
var possibleFiles = new Dictionary<DependencyNode, HashSet<string>>();

void RecurseTree(Tree commitTree)
{
foreach (var entry in commitTree)
{
switch (entry.Target)
{
case Blob blob:
if (!entry.Name.EndsWith(".meta")) continue; // Only care about meta files
if (blob.IsBinary) continue; // Why is it not text? Log this?
if (!checkedBlobs.Add(blob.Sha)) continue; // Already checked this blob
var filepath = $"{repo.Info.WorkingDirectory}{entry.Path}";

var content = blob.GetContentText();
foreach (var missingRef in missingReferences)
{
if (!content.Contains(missingRef.Guid)) continue;
if (!possibleFiles.TryGetValue(missingRef, out var missingRefPossibleFiles))
{
missingRefPossibleFiles = possibleFiles[missingRef] = new HashSet<string>();
}

missingRefPossibleFiles.Add(filepath);
}

break;
case Tree t:
RecurseTree(t);
break;
}
}
}

foreach (var commit in repo.Commits.Take(commitLimit))
{
RecurseTree(commit.Tree);
}

return possibleFiles.ToDictionary(pair => pair.Key, pair => pair.Value.ToList());
}
}
}
7 changes: 3 additions & 4 deletions Editor/DependencyNode.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Leap.Unity
namespace Leap.Unity.Dependency
{
using UnityEngine;
using System.Collections.Generic;

internal class DependencyNode : DependencyNodeBase
{
public enum NodeKind
Expand Down
2 changes: 1 addition & 1 deletion Editor/DependencyNodeBase.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using UnityEditor.PackageManager;

namespace Leap.Unity
namespace Leap.Unity.Dependency
{
/// <summary>
/// Base class for nodes.
Expand Down
25 changes: 16 additions & 9 deletions Editor/DependencyTree.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Leap.Unity
namespace Leap.Unity.Dependency
{
using UnityEngine;
using UnityEditor;
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections.Generic;

internal class DependencyTree : ScriptableObject
{
[Serializable]
Expand All @@ -34,6 +33,13 @@ public class StaticAnalysisResults
public List<string> missingGuidReferences = new List<string>();
}

[Serializable]
public class MissingReferenceLookup
{
public string guid;
public List<string> foundFiles;
}

/// <summary>
/// This class is used to bundle up information required for tree generation
/// </summary>
Expand Down Expand Up @@ -329,6 +335,7 @@ private static (DependencyFolderNode, Dictionary<string, DependencyNode>)? Build
};
public List<AssetReference> RawTree = new List<AssetReference>();
public StaticAnalysisResults AnalysisResults;
public List<MissingReferenceLookup> MissingReferenceLookups = new List<MissingReferenceLookup>();
[NonSerialized] public DependencyFolderNode RootNode;
[NonSerialized] public Dictionary<string, DependencyNode> NodesByGuid;

Expand Down
64 changes: 54 additions & 10 deletions Editor/DependencyTreeEditor.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
namespace Leap.Unity
{
using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace Leap.Unity.Dependency
{
[CustomEditor(typeof(DependencyTree))]
internal class DependencyTreeEditor : Editor
{
Expand Down Expand Up @@ -261,9 +261,21 @@ bool DrawNode(DependencyNodeBase node, Predicate<DependencyNodeBase> filter)
selectionChanged = true;
}

var dependencyNode = node as DependencyNode;

GUILayout.Space(4 + (12 * indent));
var nodeText = $"{node.Name} ({DependencyGuiUtilities.BytesToString(node.GetSize())}){(node is DependencyNode n ? $" [{n.Dependants.Count} refs, {n.Dependencies.Count} deps]" : string.Empty)}";
var nodeText = $"{node.Name} ({DependencyGuiUtilities.BytesToString(node.GetSize())}){(dependencyNode != null ? $" [{dependencyNode.Dependants.Count} refs, {dependencyNode.Dependencies.Count} deps]" : string.Empty)}";

void DrawGoToButton()
{
if (dependencyNode != null && GUILayout.Button("Go To", GUILayout.Width(50f)))
{
var objectToSelect = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(AssetDatabase.GUIDToAssetPath(dependencyNode.Guid));
Selection.activeObject = objectToSelect;
EditorGUIUtility.PingObject(objectToSelect);
}
}

IEnumerable<DependencyNodeBase> children = Enumerable.Empty<DependencyNodeBase>();
if (node is DependencyFolderNode folderNode)
{
Expand All @@ -284,15 +296,33 @@ bool DrawNode(DependencyNodeBase node, Predicate<DependencyNodeBase> filter)
{
children = folderNode.Children;
}
DrawGoToButton();
EditorGUILayout.EndHorizontal();
}
else if (dependencyNode is { Kind: DependencyNode.NodeKind.Missing })
{
GUI.color = DependencyGuiUtilities.GetColor(node, selectedNode);
EditorGUILayout.LabelField(nodeText);
DrawGoToButton();
EditorGUILayout.EndHorizontal();
var missingRefDetails = ((DependencyTree)target).MissingReferenceLookups.FirstOrDefault(lookup => lookup.guid == dependencyNode.Guid);
foreach (var foundFile in missingRefDetails?.foundFiles ?? Enumerable.Empty<string>())
{
EditorGUILayout.BeginHorizontal();
GUILayout.Space(20 + 4 + (12 * indent));
EditorGUILayout.LabelField(foundFile);
EditorGUILayout.EndHorizontal();
}
GUI.color = Color.white;
}
else
{
GUI.color = DependencyGuiUtilities.GetColor(node, selectedNode);
EditorGUILayout.LabelField(nodeText);
GUI.color = Color.white;
DrawGoToButton();
EditorGUILayout.EndHorizontal();
}

EditorGUILayout.EndHorizontal();

foreach (var child in (Sort switch
{
Expand All @@ -311,5 +341,19 @@ bool DrawNode(DependencyNodeBase node, Predicate<DependencyNodeBase> filter)
return selectionChanged;
}
}

public void DrawGitLookupMissingRefButton(string lookupRoot, int commitLimit)
{
if (GUILayout.Button("Git Lookup Missing Refs"))
{
var missingRefNodes = _missingReferencesNode.Children.Cast<DependencyNode>().ToArray();
var lookup = DependencyGuiUtilities.LookupMissingReferences(missingRefNodes, lookupRoot, commitLimit);
((DependencyTree)target).MissingReferenceLookups = lookup.Select(pair => new DependencyTree.MissingReferenceLookup
{
guid = pair.Key.Guid,
foundFiles = pair.Value
}).ToList();
}
}
}
}
96 changes: 96 additions & 0 deletions Markdown/images/dependency-browser.png.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d09af38

Please sign in to comment.