Package.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using UnityEngine;
  6. namespace UnityEditor.PackageManager.UI
  7. {
  8. // History of a single package
  9. internal class Package : IEquatable<Package>
  10. {
  11. static public bool ShouldProposeLatestVersions
  12. {
  13. get
  14. {
  15. // Until we figure out a way to test this properly, alway show standard behavior
  16. // return InternalEditorUtility.IsUnityBeta() && !Unsupported.IsDeveloperMode();
  17. return false;
  18. }
  19. }
  20. // There can only be one package add/remove operation.
  21. private static IBaseOperation addRemoveOperationInstance;
  22. public static bool AddRemoveOperationInProgress
  23. {
  24. get { return addRemoveOperationInstance != null && !addRemoveOperationInstance.IsCompleted; }
  25. }
  26. internal const string packageManagerUIName = "com.unity.package-manager-ui";
  27. private readonly string packageName;
  28. private IEnumerable<PackageInfo> source;
  29. internal Package(string packageName, IEnumerable<PackageInfo> infos)
  30. {
  31. if (string.IsNullOrEmpty(packageName))
  32. throw new ArgumentException("Cannot be empty or null", "packageName");
  33. if (!infos.Any())
  34. throw new ArgumentException("Cannot be empty", "infos");
  35. this.packageName = packageName;
  36. UpdateSource(infos);
  37. }
  38. internal void UpdateSource(IEnumerable<PackageInfo> source)
  39. {
  40. this.source = source;
  41. #if UNITY_2018_3_OR_NEWER
  42. if (IsPackageManagerUI)
  43. this.source = this.source.Where(p => p != null && p.Version.Major >= 2);
  44. #endif
  45. }
  46. public PackageInfo Current { get { return Versions.FirstOrDefault(package => package.IsCurrent); } }
  47. // This is the latest verified or official release (eg: 1.3.2). Not necessarily the latest verified release (eg: 1.2.4) or that latest candidate (eg: 1.4.0-beta)
  48. public PackageInfo LatestUpdate
  49. {
  50. get
  51. {
  52. // We want to show the absolute latest when in beta mode
  53. if (ShouldProposeLatestVersions)
  54. return Latest;
  55. // Override with current when it's version locked
  56. var current = Current;
  57. if (current != null && current.IsVersionLocked)
  58. return current;
  59. // Get all the candidates versions (verified, release, preview) that are newer than current
  60. var verified = Verified;
  61. var latestRelease = LatestRelease;
  62. var latestPreview = Versions.LastOrDefault(package => package.IsPreview);
  63. var candidates = new List<PackageInfo>
  64. {
  65. verified,
  66. latestRelease,
  67. latestPreview,
  68. }.Where(package => package != null && (current == null || current == package || current.Version < package.Version)).ToList();
  69. if (candidates.Contains(verified))
  70. return verified;
  71. if ((current == null || !current.IsVerified) && candidates.Contains(latestRelease))
  72. return latestRelease;
  73. if ((current == null || current.IsPreview) && candidates.Contains(latestPreview))
  74. return latestPreview;
  75. // Show current if it exists, otherwise latest user visible, and then otherwise show the absolute latest
  76. return current ?? Latest;
  77. }
  78. }
  79. public PackageInfo LatestPatch
  80. {
  81. get
  82. {
  83. if (Current == null)
  84. return null;
  85. // Get all version that have the same Major/Minor
  86. var versions = Versions.Where(package => package.Version.Major == Current.Version.Major && package.Version.Minor == Current.Version.Minor);
  87. return versions.LastOrDefault();
  88. }
  89. }
  90. // This is the very latest version, including pre-releases (eg: 1.4.0-beta).
  91. internal PackageInfo Latest { get { return Versions.FirstOrDefault(package => package.IsLatest) ?? Versions.LastOrDefault(); } }
  92. // Returns the current version if it exist, otherwise returns the latest user visible version.
  93. internal PackageInfo VersionToDisplay { get { return Current ?? LatestUpdate; } }
  94. // Every version available for this package
  95. internal IEnumerable<PackageInfo> Versions { get { return source.OrderBy(package => package.Version); } }
  96. // Every version that's not a pre-release (eg: not beta/alpha/preview).
  97. internal IEnumerable<PackageInfo> ReleaseVersions
  98. {
  99. get { return Versions.Where(package => !package.IsPreRelease); }
  100. }
  101. internal PackageInfo LatestRelease { get {return ReleaseVersions.LastOrDefault();}}
  102. internal PackageInfo Verified { get {return Versions.FirstOrDefault(package => package.IsVerified);}}
  103. internal bool IsAfterCurrentVersion(PackageInfo packageInfo) { return Current == null || (packageInfo != null && packageInfo.Version > Current.Version); }
  104. internal bool IsBuiltIn {get { return Versions.Any() && Versions.First().IsBuiltIn; }}
  105. internal bool IsUnityPackage { get { return VersionToDisplay.IsUnityPackage; } }
  106. public string Name { get { return packageName; } }
  107. public bool IsPackageManagerUI
  108. {
  109. get { return Name == packageManagerUIName; }
  110. }
  111. public bool Equals(Package other)
  112. {
  113. if (other == null)
  114. return false;
  115. return packageName == other.packageName;
  116. }
  117. public override int GetHashCode()
  118. {
  119. return packageName.GetHashCode();
  120. }
  121. [SerializeField]
  122. internal readonly OperationSignal<IAddOperation> AddSignal = new OperationSignal<IAddOperation>();
  123. private Action OnAddOperationFinalizedEvent;
  124. internal void Add(PackageInfo packageInfo)
  125. {
  126. if (packageInfo == Current || AddRemoveOperationInProgress)
  127. return;
  128. var operation = OperationFactory.Instance.CreateAddOperation();
  129. addRemoveOperationInstance = operation;
  130. OnAddOperationFinalizedEvent = () =>
  131. {
  132. AddSignal.Operation = null;
  133. operation.OnOperationFinalized -= OnAddOperationFinalizedEvent;
  134. PackageCollection.Instance.FetchListOfflineCache(true);
  135. };
  136. operation.OnOperationFinalized += OnAddOperationFinalizedEvent;
  137. AddSignal.SetOperation(operation);
  138. operation.AddPackageAsync(packageInfo);
  139. }
  140. internal void Update()
  141. {
  142. Add(Latest);
  143. }
  144. internal static void AddFromLocalDisk(string path)
  145. {
  146. if (AddRemoveOperationInProgress)
  147. return;
  148. var packageJson = PackageJsonHelper.Load(path);
  149. if (null == packageJson)
  150. {
  151. Debug.LogError(string.Format("Invalid package path: cannot find \"{0}\".", path));
  152. return;
  153. }
  154. var operation = OperationFactory.Instance.CreateAddOperation();
  155. addRemoveOperationInstance = operation;
  156. operation.AddPackageAsync(packageJson.PackageInfo);
  157. }
  158. [SerializeField]
  159. internal readonly OperationSignal<IRemoveOperation> RemoveSignal = new OperationSignal<IRemoveOperation>();
  160. private Action OnRemoveOperationFinalizedEvent;
  161. public void Remove()
  162. {
  163. if (Current == null || AddRemoveOperationInProgress)
  164. return;
  165. var operation = OperationFactory.Instance.CreateRemoveOperation();
  166. addRemoveOperationInstance = operation;
  167. OnRemoveOperationFinalizedEvent = () =>
  168. {
  169. RemoveSignal.Operation = null;
  170. operation.OnOperationFinalized -= OnRemoveOperationFinalizedEvent;
  171. PackageCollection.Instance.FetchListOfflineCache(true);
  172. };
  173. operation.OnOperationFinalized += OnRemoveOperationFinalizedEvent;
  174. RemoveSignal.SetOperation(operation);
  175. operation.RemovePackageAsync(Current);
  176. }
  177. }
  178. }