DependencyResolver.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using ET;
  7. using MongoDB.Bson.Serialization;
  8. using MongoDB.Bson.Serialization.Attributes;
  9. using UnityEditor;
  10. using UnityEditor.PackageManager;
  11. using PackageInfo = UnityEditor.PackageManager.PackageInfo;
  12. using UnityEditor.PackageManager.Requests;
  13. using Debug = UnityEngine.Debug;
  14. namespace Hibzz.DependencyResolver
  15. {
  16. [BsonIgnoreExtraElements]
  17. public class PackageGitDependency
  18. {
  19. public int Id;
  20. public string Name;
  21. public Dictionary<string, string> GitDependencies;
  22. }
  23. [InitializeOnLoad]
  24. public class DependencyResolver
  25. {
  26. static void MoveToPackage()
  27. {
  28. #if UNITY_EDITOR_WIN
  29. Process process = ProcessHelper.Run("powershell.exe", $"-NoExit -ExecutionPolicy Bypass -File .\\Scripts/MoveToPackages.ps1", waitExit: true);
  30. #else
  31. Process process = ProcessHelper.Run("pwsh", $"-NoExit -ExecutionPolicy Bypass -File ./Scripts/MoveToPackages.ps1", waitExit: true);
  32. #endif
  33. Debug.Log(process.StandardOutput.ReadToEnd());
  34. AssetDatabase.Refresh();
  35. }
  36. static AddAndRemoveRequest packageInstallationRequest;
  37. static DependencyResolver()
  38. {
  39. Events.registeredPackages += OnPackagesRegistered;
  40. }
  41. // Invoked when the package manager completes registering new packages
  42. static void OnPackagesRegistered(PackageRegistrationEventArgs packageRegistrationInfo)
  43. {
  44. if (packageRegistrationInfo.added.Count == 0)
  45. {
  46. return;
  47. }
  48. Debug.Log($"Packages Registered: {string.Join(" ", packageRegistrationInfo.added.Select(x=>x.name))}");
  49. // loop through all of the added packages and get their git
  50. // dependencies and add it to the list that contains all the
  51. // dependencies that need to be installed
  52. Dictionary<string, string> dependencies = new();
  53. List<PackageInfo> installedPackages = PackageInfo.GetAllRegisteredPackages().ToList();
  54. foreach (var package in packageRegistrationInfo.added)
  55. {
  56. if (!package.name.StartsWith("cn.etetet."))
  57. {
  58. continue;
  59. }
  60. // get the dependencies of the added package
  61. if (!GetDependencies(package, out PackageGitDependency packageDependencies))
  62. {
  63. continue;
  64. }
  65. foreach (var gitDependency in packageDependencies.GitDependencies)
  66. {
  67. if (IsInCollection(gitDependency.Key, installedPackages))
  68. {
  69. continue;
  70. }
  71. dependencies[gitDependency.Key] = gitDependency.Value;
  72. }
  73. }
  74. // Install the dependencies
  75. InstallDependencies(dependencies);
  76. }
  77. /// <summary>
  78. /// Request a list of git dependencies in the package
  79. /// </summary>
  80. /// <param name="packageInfo">The package to get the git dependencies from</param>
  81. /// <param name="dependencies">The retrieved list of git dependencies </param>
  82. /// <returns>Was the request successful?</returns>
  83. static bool GetDependencies(PackageInfo packageInfo, out PackageGitDependency dependencies)
  84. {
  85. // Read the contents of the package.json file
  86. string packageJsonPath = $"{packageInfo.resolvedPath}/packagegit.json";
  87. if (!File.Exists(packageJsonPath))
  88. {
  89. throw new Exception($"package already move to packages dir, please refresh your unity project! RepairDependencies retry please! {packageInfo.name} {packageJsonPath}");
  90. }
  91. string packageJsonContent = File.ReadAllText(packageJsonPath);
  92. PackageGitDependency packageGitDependency = BsonSerializer.Deserialize<PackageGitDependency>(packageJsonContent);
  93. // if no token with the key git-dependecies is found, failed to get git dependencies
  94. if (packageGitDependency.GitDependencies is null || packageGitDependency.GitDependencies.Count == 0)
  95. {
  96. dependencies = null;
  97. return false;
  98. }
  99. // convert the git dependency token to a list of strings...
  100. // maybe we should check for errors in this process? what if git-dependency isn't array of string?
  101. dependencies = packageGitDependency;
  102. return true;
  103. }
  104. /// <summary>
  105. /// Is the given dependency url found in the given collection
  106. /// </summary>
  107. /// <param name="dependency">The url the dependency to check for</param>
  108. /// <param name="collection">The collection to look through</param>
  109. /// <returns></returns>
  110. static bool IsInCollection(string dependency, List<PackageInfo> collection)
  111. {
  112. // when package collection given is null, it's inferred that the dependency is not in the collection
  113. if (collection == null)
  114. {
  115. return false;
  116. }
  117. // check if any of the installed package has the dependency
  118. foreach (var package in collection)
  119. {
  120. // the package id for a package installed with git is `package_name@package_giturl`
  121. // get the repo url by performing some string manipulation on the package id
  122. //string repourl = package.packageId.Substring(package.packageId.IndexOf('@') + 1);
  123. // Found!
  124. if (package.name == dependency)
  125. {
  126. return true;
  127. }
  128. }
  129. // the dependency wasn't found in the package collection
  130. return false;
  131. }
  132. /// <summary>
  133. /// Install all the given dependencies
  134. /// </summary>
  135. static void InstallDependencies(Dictionary<string, string> dependencies)
  136. {
  137. if (dependencies.Count == 0)
  138. {
  139. MoveToPackage();
  140. Debug.Log($"git Dependencies are all installed");
  141. return;
  142. }
  143. // before installing the packages, make sure that user knows what
  144. // the dependencies to install are... additionally, check if the
  145. // application is being run on batch mode so that we can skip the
  146. // installation dialog
  147. Debug.Log($"The following dependencies are required:\n{string.Join("\n", dependencies.Keys)}");
  148. // the user pressed install, perform the actual installation
  149. // (or the application was in batch mode)
  150. packageInstallationRequest = Client.AddAndRemove(dependencies.Values.ToArray());
  151. // show the progress bar till the installation is complete
  152. EditorUtility.DisplayProgressBar("Dependency Resolver", "Preparing installation of dependencies...", 0);
  153. EditorApplication.update += DisplayProgress;
  154. }
  155. /// <summary>
  156. /// Shows a progress bar till the AddAndRemoveRequest is completed
  157. /// </summary>
  158. static void DisplayProgress()
  159. {
  160. if (!packageInstallationRequest.IsCompleted)
  161. {
  162. return;
  163. }
  164. EditorUtility.ClearProgressBar();
  165. EditorApplication.update -= DisplayProgress;
  166. }
  167. [MenuItem("ET/RepairDependencies")]
  168. static void RepairDependencies()
  169. {
  170. MoveToPackage();
  171. Dictionary<string, string> dependencies = new();
  172. List<PackageInfo> installedPackages = PackageInfo.GetAllRegisteredPackages().ToList();
  173. foreach (var package in installedPackages)
  174. {
  175. if (!package.name.StartsWith("cn.etetet."))
  176. {
  177. continue;
  178. }
  179. if (!GetDependencies(package, out PackageGitDependency packageDependencies))
  180. {
  181. continue;
  182. }
  183. foreach (var gitDependency in packageDependencies.GitDependencies)
  184. {
  185. if (IsInCollection(gitDependency.Key, installedPackages))
  186. {
  187. continue;
  188. }
  189. if (dependencies.TryGetValue(gitDependency.Key, out string findV))
  190. {
  191. if (findV != gitDependency.Value)
  192. {
  193. Debug.Log($"package dup {gitDependency.Key} but git url diff: {findV} {gitDependency.Value}");
  194. }
  195. continue;
  196. }
  197. Debug.Log($"Dependency not found: {gitDependency.Key}");
  198. dependencies.Add(gitDependency.Key, gitDependency.Value);
  199. }
  200. }
  201. if (dependencies.Count == 0)
  202. {
  203. Debug.Log($"git Dependencies are all installed");
  204. return;
  205. }
  206. InstallDependencies(dependencies);
  207. }
  208. }
  209. }