UnityDiffTree.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using System.Collections.Generic;
  2. using Codice.Client.Commands;
  3. using Codice.Client.Common;
  4. using Codice.Utils;
  5. using PlasticGui;
  6. using PlasticGui.WorkspaceWindow.Diff;
  7. namespace Unity.PlasticSCM.Editor.Views.Diff
  8. {
  9. internal class UnityDiffTree
  10. {
  11. internal UnityDiffTree()
  12. {
  13. mInnerTree = new DiffTree();
  14. mMetaCache = new MetaCache();
  15. }
  16. internal void BuildCategories(
  17. List<ClientDiff> diffs,
  18. BranchResolver brResolver,
  19. bool skipMergeTracking)
  20. {
  21. mInnerTree.BuildCategories(diffs, brResolver, skipMergeTracking);
  22. mMetaCache.Build(mInnerTree.GetNodes());
  23. }
  24. internal List<IDiffCategory> GetNodes()
  25. {
  26. return mInnerTree.GetNodes();
  27. }
  28. internal bool HasMeta(ClientDiffInfo difference)
  29. {
  30. return mMetaCache.ContainsMeta(difference);
  31. }
  32. internal ClientDiffInfo GetMetaDiff(ClientDiffInfo diff)
  33. {
  34. return mMetaCache.GetExistingMeta(diff);
  35. }
  36. internal void FillWithMeta(List<ClientDiffInfo> diffs)
  37. {
  38. diffs.AddRange(
  39. mMetaCache.GetExistingMeta(diffs));
  40. }
  41. internal void Sort(string key, bool sortAscending)
  42. {
  43. mInnerTree.Sort(key, sortAscending);
  44. }
  45. internal void Filter(Filter filter, List<string> columnNames)
  46. {
  47. mInnerTree.Filter(filter, columnNames);
  48. }
  49. MetaCache mMetaCache = new MetaCache();
  50. DiffTree mInnerTree;
  51. class MetaCache
  52. {
  53. internal void Build(List<IDiffCategory> categories)
  54. {
  55. mCache.Clear();
  56. HashSet<string> indexedKeys = BuildIndexedKeys(
  57. GetClientDiffInfos.FromCategories(categories));
  58. for (int i = 0; i < categories.Count; i++)
  59. {
  60. ExtractToMetaCache(
  61. (ITreeViewNode)categories[i],
  62. i,
  63. mCache,
  64. indexedKeys);
  65. }
  66. }
  67. internal bool ContainsMeta(ClientDiffInfo diff)
  68. {
  69. return mCache.ContainsKey(
  70. BuildKey.ForMetaDiff(diff));
  71. }
  72. internal ClientDiffInfo GetExistingMeta(ClientDiffInfo diff)
  73. {
  74. ClientDiffInfo result;
  75. if (!mCache.TryGetValue(BuildKey.ForMetaDiff(diff), out result))
  76. return null;
  77. return result;
  78. }
  79. internal List<ClientDiffInfo> GetExistingMeta(List<ClientDiffInfo> diffs)
  80. {
  81. List<ClientDiffInfo> result = new List<ClientDiffInfo>();
  82. foreach (ClientDiffInfo diff in diffs)
  83. {
  84. string key = BuildKey.ForMetaDiff(diff);
  85. ClientDiffInfo metaDiff;
  86. if (!mCache.TryGetValue(key, out metaDiff))
  87. continue;
  88. result.Add(metaDiff);
  89. }
  90. return result;
  91. }
  92. static void ExtractToMetaCache(
  93. ITreeViewNode node,
  94. int nodeIndex,
  95. Dictionary<string, ClientDiffInfo> cache,
  96. HashSet<string> indexedKeys)
  97. {
  98. if (node is ClientDiffInfo)
  99. {
  100. ClientDiffInfo diff = (ClientDiffInfo)node;
  101. string path = diff.DiffWithMount.Difference.Path;
  102. if (!MetaPath.IsMetaPath(path))
  103. return;
  104. string realPath = MetaPath.GetPathFromMetaPath(path);
  105. if (!indexedKeys.Contains(BuildKey.BuildCacheKey(
  106. BuildKey.GetMergeCategory(diff),
  107. BuildKey.GetChangeCategory(diff),
  108. realPath)))
  109. return;
  110. // found foo.c and foo.c.meta
  111. // with the same chage types - move .meta to cache
  112. cache.Add(BuildKey.ForDiff(diff), diff);
  113. ((ChangeCategory)node.GetParent()).RemoveDiffAt(nodeIndex);
  114. }
  115. for (int i = node.GetChildrenCount() - 1; i >= 0; i--)
  116. {
  117. ExtractToMetaCache(
  118. node.GetChild(i),
  119. i,
  120. cache,
  121. indexedKeys);
  122. }
  123. }
  124. HashSet<string> BuildIndexedKeys(List<ClientDiffInfo> diffs)
  125. {
  126. HashSet<string> result = new HashSet<string>();
  127. foreach (ClientDiffInfo diff in diffs)
  128. {
  129. if (MetaPath.IsMetaPath(diff.DiffWithMount.Difference.Path))
  130. continue;
  131. result.Add(BuildKey.ForDiff(diff));
  132. }
  133. return result;
  134. }
  135. Dictionary<string, ClientDiffInfo> mCache =
  136. new Dictionary<string, ClientDiffInfo>();
  137. static class BuildKey
  138. {
  139. internal static string ForDiff(
  140. ClientDiffInfo diff)
  141. {
  142. return BuildCacheKey(
  143. GetMergeCategory(diff),
  144. GetChangeCategory(diff),
  145. diff.DiffWithMount.Difference.Path);
  146. }
  147. internal static string ForMetaDiff(
  148. ClientDiffInfo diff)
  149. {
  150. return BuildCacheKey(
  151. GetMergeCategory(diff),
  152. GetChangeCategory(diff),
  153. MetaPath.GetMetaPath(diff.DiffWithMount.Difference.Path));
  154. }
  155. internal static string BuildCacheKey(
  156. MergeCategory mergeCategory,
  157. ChangeCategory changeCategory,
  158. string path)
  159. {
  160. string result = string.Concat(changeCategory.Type, ":", path);
  161. if (mergeCategory == null)
  162. return result;
  163. return string.Concat(mergeCategory.GetCategoryNameSingular(), ":", result);
  164. }
  165. internal static ChangeCategory GetChangeCategory(ClientDiffInfo diff)
  166. {
  167. return (ChangeCategory)diff.GetParent();
  168. }
  169. internal static MergeCategory GetMergeCategory(ClientDiffInfo diff)
  170. {
  171. ChangeCategory changeCategory = GetChangeCategory(diff);
  172. ITreeViewNode mergeCategory = changeCategory.GetParent();
  173. if (mergeCategory == null)
  174. return null;
  175. return (MergeCategory)mergeCategory;
  176. }
  177. }
  178. }
  179. }
  180. }