UnityDiffTree.cs 6.8 KB

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