185 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System.Collections.Generic;
 | |
| 
 | |
| using Codice;
 | |
| using Codice.Client.Commands.WkTree;
 | |
| using Codice.Client.Common;
 | |
| using Codice.Client.Common.Locks;
 | |
| using Codice.Client.Common.Threading;
 | |
| using Codice.Client.Common.WkTree;
 | |
| using Codice.CM.Common;
 | |
| using Codice.CM.Common.Mount;
 | |
| using Codice.Utils;
 | |
| using PlasticGui.WorkspaceWindow;
 | |
| using PlasticGui.WorkspaceWindow.Items.Locks;
 | |
| using Unity.PlasticSCM.Editor.AssetUtils;
 | |
| 
 | |
| namespace Unity.PlasticSCM.Editor.AssetsOverlays.Cache
 | |
| {
 | |
|     internal class LockStatusCache
 | |
|     {
 | |
|         internal LockStatusCache(
 | |
|             WorkspaceInfo wkInfo)
 | |
|         {
 | |
|             mWkInfo = wkInfo;
 | |
|         }
 | |
| 
 | |
|         internal AssetStatus GetStatus(string fullPath)
 | |
|         {
 | |
|             LockStatusData lockStatusData = GetLockStatusData(fullPath);
 | |
| 
 | |
|             if (lockStatusData == null)
 | |
|                 return AssetStatus.None;
 | |
| 
 | |
|             return lockStatusData.Status;
 | |
|         }
 | |
| 
 | |
|         internal LockStatusData GetLockStatusData(string fullPath)
 | |
|         {
 | |
|             lock (mLock)
 | |
|             {
 | |
|                 if (mStatusByPathCache == null)
 | |
|                 {
 | |
|                     mStatusByPathCache = BuildPathDictionary.ForPlatform<LockStatusData>();
 | |
| 
 | |
|                     mCurrentCancelToken.Cancel();
 | |
|                     mCurrentCancelToken = new CancelToken();
 | |
|                     AsyncCalculateStatus(mCurrentCancelToken);
 | |
| 
 | |
|                     return null;
 | |
|                 }
 | |
| 
 | |
|                 LockStatusData result;
 | |
| 
 | |
|                 if (mStatusByPathCache.TryGetValue(fullPath, out result))
 | |
|                     return result;
 | |
| 
 | |
|                 return null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal void Clear()
 | |
|         {
 | |
|             lock (mLock)
 | |
|             {
 | |
|                 mCurrentCancelToken.Cancel();
 | |
| 
 | |
|                 mStatusByPathCache = null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal void Cancel()
 | |
|         {
 | |
|             lock (mLock)
 | |
|             {
 | |
|                 mCurrentCancelToken.Cancel();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void AsyncCalculateStatus(CancelToken cancelToken)
 | |
|         {
 | |
|             Dictionary<string, LockStatusData> statusByPathCache = null;
 | |
| 
 | |
|             IThreadWaiter waiter = ThreadWaiter.GetWaiter(50);
 | |
|             waiter.Execute(
 | |
|                 /*threadOperationDelegate*/ delegate
 | |
|                 {
 | |
|                     Dictionary<MountPointWithPath, List<WorkspaceTreeNode>> lockCandidates =
 | |
|                         new Dictionary<MountPointWithPath, List<WorkspaceTreeNode>>();
 | |
| 
 | |
|                     FillLockCandidates.ForTree(mWkInfo, lockCandidates);
 | |
| 
 | |
|                     if (cancelToken.IsCancelled())
 | |
|                         return;
 | |
| 
 | |
|                     Dictionary<WorkspaceTreeNode, LockInfo> lockInfoByNode =
 | |
|                         SearchLocks.GetLocksInfo(mWkInfo, lockCandidates);
 | |
| 
 | |
|                     if (cancelToken.IsCancelled())
 | |
|                         return;
 | |
| 
 | |
|                     statusByPathCache = BuildStatusByNodeCache.
 | |
|                         ForLocks(mWkInfo.ClientPath, lockInfoByNode);
 | |
|                 },
 | |
|                 /*afterOperationDelegate*/ delegate
 | |
|                 {
 | |
|                     if (cancelToken.IsCancelled())
 | |
|                         return;
 | |
| 
 | |
|                     if (waiter.Exception != null)
 | |
|                     {
 | |
|                         ExceptionsHandler.LogException(
 | |
|                             "LockStatusCache",
 | |
|                             waiter.Exception);
 | |
|                         return;
 | |
|                     }
 | |
| 
 | |
|                     lock (mLock)
 | |
|                     {
 | |
|                         mStatusByPathCache = statusByPathCache;
 | |
|                     }
 | |
| 
 | |
|                     RepaintEditor.AllWindowsWithOverlays();
 | |
|                 });
 | |
|         }
 | |
| 
 | |
|         static class BuildStatusByNodeCache
 | |
|         {
 | |
|             internal static Dictionary<string, LockStatusData> ForLocks(
 | |
|                 string wkPath,
 | |
|                 Dictionary<WorkspaceTreeNode, LockInfo> lockInfoByNode)
 | |
|             {
 | |
|                 Dictionary<string, LockStatusData> result =
 | |
|                     BuildPathDictionary.ForPlatform<LockStatusData>();
 | |
| 
 | |
|                 LockOwnerNameResolver nameResolver = new LockOwnerNameResolver();
 | |
| 
 | |
|                 foreach (WorkspaceTreeNode node in lockInfoByNode.Keys)
 | |
|                 {
 | |
|                     LockStatusData lockStatusData = BuildLockStatusData(
 | |
|                        node, lockInfoByNode[node], nameResolver);
 | |
| 
 | |
|                     string nodeWkPath = WorkspacePath.GetWorkspacePathFromCmPath(
 | |
|                         wkPath,
 | |
|                         WorkspaceNodeOperations.GetCmPath(node),
 | |
|                         PathHelper.GetDirectorySeparatorChar(wkPath));
 | |
| 
 | |
|                     result.Add(nodeWkPath, lockStatusData);
 | |
|                 }
 | |
| 
 | |
|                 return result;
 | |
|             }
 | |
| 
 | |
|             static LockStatusData BuildLockStatusData(
 | |
|                 WorkspaceTreeNode node,
 | |
|                 LockInfo lockInfo,
 | |
|                 LockOwnerNameResolver nameResolver)
 | |
|             {
 | |
|                 return new LockStatusData(
 | |
|                     GetAssetStatus(node, lockInfo),
 | |
|                     nameResolver.GetSeidName(lockInfo.SEIDData),
 | |
|                     BranchInfoCache.GetProtectedBranchName(
 | |
|                         node.RepSpec, lockInfo.HolderBranchId));
 | |
|             }
 | |
| 
 | |
|             static AssetStatus GetAssetStatus(
 | |
|                 WorkspaceTreeNode node,
 | |
|                 LockInfo lockInfo)
 | |
|             {
 | |
|                 if (lockInfo.Status == LockInfo.LockStatus.Retained)
 | |
|                     return AssetStatus.Retained;
 | |
| 
 | |
|                 return CheckWorkspaceTreeNodeStatus.IsCheckedOut(node) ?
 | |
|                     AssetStatus.Locked : AssetStatus.LockedRemote;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         CancelToken mCurrentCancelToken = new CancelToken();
 | |
| 
 | |
|         Dictionary<string, LockStatusData> mStatusByPathCache;
 | |
| 
 | |
|         readonly WorkspaceInfo mWkInfo;
 | |
| 
 | |
|         static object mLock = new object();
 | |
|     }
 | |
| }
 |