A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3
4using Codice.Client.BaseCommands;
5using Codice.Client.Commands;
6using Codice.Client.Common;
7using Codice.Client.Common.Threading;
8using Codice.Client.GameUI;
9using Codice.Client.GameUI.Update;
10using Codice.CM.Common;
11using Codice.CM.Common.Merge;
12using Codice.CM.Common.Mount;
13using Codice.CM.Common.Partial;
14using Codice.CM.Common.Update.Partial;
15using Codice.Utils;
16using GluonGui.WorkspaceWindow.Views;
17
18namespace Unity.PlasticSCM.Editor.AssetsOverlays.Cache
19{
20 internal class RemoteStatusCache
21 {
22 internal RemoteStatusCache(
23 WorkspaceInfo wkInfo,
24 bool isGluonMode,
25 Action repaintProjectWindow,
26 Action repaintInspector)
27 {
28 mWkInfo = wkInfo;
29 mIsGluonMode = isGluonMode;
30 mRepaintProjectWindow = repaintProjectWindow;
31 mRepaintInspector = repaintInspector;
32 }
33
34 internal AssetStatus GetStatus(string fullPath)
35 {
36 if (!mIsGluonMode)
37 return AssetStatus.UpToDate;
38
39 lock(mLock)
40 {
41 if (mStatusByPathCache == null)
42 {
43 mStatusByPathCache = BuildPathDictionary.ForPlatform<AssetStatus>();
44
45 mCurrentCancelToken.Cancel();
46 mCurrentCancelToken = new CancelToken();
47 AsyncCalculateStatus(mCurrentCancelToken);
48
49 return AssetStatus.UpToDate;
50 }
51
52 AssetStatus result;
53 if (mStatusByPathCache.TryGetValue(fullPath, out result))
54 return result;
55
56 return AssetStatus.UpToDate;
57 }
58 }
59
60 internal void Clear()
61 {
62 lock (mLock)
63 {
64 mCurrentCancelToken.Cancel();
65 mStatusByPathCache = null;
66 }
67 }
68
69 internal void Cancel()
70 {
71 lock (mLock)
72 {
73 mCurrentCancelToken.Cancel();
74 }
75 }
76
77 void AsyncCalculateStatus(CancelToken cancelToken)
78 {
79 Dictionary<string, AssetStatus> statusByPathCache = null;
80
81 IThreadWaiter waiter = ThreadWaiter.GetWaiter(50);
82 waiter.Execute(
83 /*threadOperationDelegate*/ delegate
84 {
85 OutOfDateItems outOfDateItems =
86 OutOfDateUpdater.CalculateOutOfDateItems(
87 mWkInfo, new List<ErrorMessage>(),
88 OutOfDateCalculator.Options.IsIncomingChanges);
89
90 if (cancelToken.IsCancelled())
91 return;
92
93 statusByPathCache = BuildStatusByPathCache.
94 ForOutOfDateItems(outOfDateItems, mWkInfo.ClientPath);
95 },
96 /*afterOperationDelegate*/ delegate
97 {
98 if (cancelToken.IsCancelled())
99 return;
100
101 if (waiter.Exception != null)
102 {
103 ExceptionsHandler.LogException(
104 "RemoteStatusCache",
105 waiter.Exception);
106 return;
107 }
108
109 lock (mLock)
110 {
111 mStatusByPathCache = statusByPathCache;
112 }
113
114 mRepaintProjectWindow();
115 mRepaintInspector();
116 });
117 }
118
119 static class BuildStatusByPathCache
120 {
121 internal static Dictionary<string, AssetStatus> ForOutOfDateItems(
122 OutOfDateItems outOfDateItems,
123 string wkPath)
124 {
125 Dictionary<string, AssetStatus> result =
126 BuildPathDictionary.ForPlatform<AssetStatus>();
127
128 if (outOfDateItems == null)
129 return result;
130
131 foreach (OutOfDateItemsByMount diffs in
132 outOfDateItems.GetOutOfDateItemsByMountList(PathHelper.GetPathSorter()))
133 {
134 foreach (Difference diff in diffs.Changed)
135 {
136 if (diff is DiffXlinkChanged)
137 continue;
138
139 string path = GetPathForDiff(wkPath, diffs.Mount, diff.Path);
140 result.Add(path, AssetStatus.OutOfDate);
141 }
142
143 foreach (Difference diff in diffs.Deleted)
144 {
145 string path = GetPathForDiff(wkPath, diffs.Mount, diff.Path);
146 result.Add(path, AssetStatus.DeletedOnServer);
147 }
148 }
149
150 foreach (GluonFileConflict fileConflict in
151 outOfDateItems.GetFileConflicts())
152 {
153 string path = GetPathForConflict(wkPath, fileConflict.CmPath);
154 result.Add(path, AssetStatus.Conflicted);
155 }
156
157 return result;
158 }
159
160 static string GetPathForDiff(
161 string wkPath,
162 MountPointWithPath mountPoint,
163 string cmSubPath)
164 {
165 return WorkspacePath.GetWorkspacePathFromCmPath(
166 wkPath,
167 WorkspacePath.ComposeMountPath(mountPoint.MountPath, cmSubPath),
168 PathHelper.GetDirectorySeparatorChar(wkPath));
169 }
170
171 static string GetPathForConflict(
172 string wkPath,
173 string cmPath)
174 {
175 return WorkspacePath.GetWorkspacePathFromCmPath(
176 wkPath, cmPath,
177 PathHelper.GetDirectorySeparatorChar(wkPath));
178 }
179 }
180
181 CancelToken mCurrentCancelToken = new CancelToken();
182
183 Dictionary<string, AssetStatus> mStatusByPathCache;
184
185 readonly Action mRepaintInspector;
186 readonly Action mRepaintProjectWindow;
187 readonly bool mIsGluonMode;
188 readonly WorkspaceInfo mWkInfo;
189
190 static object mLock = new object();
191 }
192}