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