233 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			233 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System.Collections.Generic; | |||
|  | 
 | |||
|  | using Codice.Client.Commands; | |||
|  | using Codice.Client.Common; | |||
|  | using Codice.CM.Common; | |||
|  | using Codice.Utils; | |||
|  | using PlasticGui; | |||
|  | using PlasticGui.Diff; | |||
|  | using PlasticGui.WorkspaceWindow.Diff; | |||
|  | 
 | |||
|  | namespace Unity.PlasticSCM.Editor.Views.Diff | |||
|  | { | |||
|  |     internal class UnityDiffTree | |||
|  |     { | |||
|  |         internal UnityDiffTree() | |||
|  |         { | |||
|  |             mInnerTree = new DiffTree(); | |||
|  |             mMetaCache = new MetaCache(); | |||
|  |         } | |||
|  | 
 | |||
|  |         internal void BuildCategories( | |||
|  |             WorkspaceInfo wkInfo, | |||
|  |             List<ClientDiff> diffs, | |||
|  |             BranchResolver brResolver, | |||
|  |             bool skipMergeTracking) | |||
|  |         { | |||
|  |             mInnerTree.BuildCategories( | |||
|  |                 RevisionInfoCodeReviewAdapter.CalculateCodeReviewEntries( | |||
|  |                         wkInfo, | |||
|  |                         diffs, | |||
|  |                         brResolver, | |||
|  |                         skipMergeTracking), | |||
|  |                 brResolver); | |||
|  |             mMetaCache.Build(mInnerTree.GetNodes()); | |||
|  |         } | |||
|  | 
 | |||
|  |         internal List<IDiffCategory> GetNodes() | |||
|  |         { | |||
|  |             return mInnerTree.GetNodes(); | |||
|  |         } | |||
|  | 
 | |||
|  |         internal bool HasMeta(ClientDiffInfo difference) | |||
|  |         { | |||
|  |             return mMetaCache.ContainsMeta(difference); | |||
|  |         } | |||
|  | 
 | |||
|  |         internal ClientDiffInfo GetMetaDiff(ClientDiffInfo diff) | |||
|  |         { | |||
|  |             return mMetaCache.GetExistingMeta(diff); | |||
|  |         } | |||
|  | 
 | |||
|  |         internal void FillWithMeta(List<ClientDiffInfo> diffs) | |||
|  |         { | |||
|  |             diffs.AddRange( | |||
|  |                 mMetaCache.GetExistingMeta(diffs)); | |||
|  |         } | |||
|  | 
 | |||
|  |         internal void Sort(string key, bool sortAscending) | |||
|  |         { | |||
|  |             mInnerTree.Sort(key, sortAscending); | |||
|  |         } | |||
|  | 
 | |||
|  |         internal void Filter(Filter filter, List<string> columnNames) | |||
|  |         { | |||
|  |             mInnerTree.Filter(filter, columnNames); | |||
|  |         } | |||
|  | 
 | |||
|  |         MetaCache mMetaCache = new MetaCache(); | |||
|  |         DiffTree mInnerTree; | |||
|  | 
 | |||
|  |         class MetaCache | |||
|  |         { | |||
|  |             internal void Build(List<IDiffCategory> categories) | |||
|  |             { | |||
|  |                 mCache.Clear(); | |||
|  | 
 | |||
|  |                 HashSet<string> indexedKeys = BuildIndexedKeys( | |||
|  |                     GetClientDiffInfos.FromCategories(categories)); | |||
|  | 
 | |||
|  |                 for (int i = 0; i < categories.Count; i++) | |||
|  |                 { | |||
|  |                     ExtractToMetaCache( | |||
|  |                         (ITreeViewNode)categories[i], | |||
|  |                         i, | |||
|  |                         mCache, | |||
|  |                         indexedKeys); | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             internal bool ContainsMeta(ClientDiffInfo diff) | |||
|  |             { | |||
|  |                 return mCache.ContainsKey( | |||
|  |                     BuildKey.ForMetaDiff(diff)); | |||
|  |             } | |||
|  | 
 | |||
|  |             internal ClientDiffInfo GetExistingMeta(ClientDiffInfo diff) | |||
|  |             { | |||
|  |                 ClientDiffInfo result; | |||
|  | 
 | |||
|  |                 if (!mCache.TryGetValue(BuildKey.ForMetaDiff(diff), out result)) | |||
|  |                     return null; | |||
|  | 
 | |||
|  |                 return result; | |||
|  |             } | |||
|  | 
 | |||
|  |             internal List<ClientDiffInfo> GetExistingMeta(List<ClientDiffInfo> diffs) | |||
|  |             { | |||
|  |                 List<ClientDiffInfo> result = new List<ClientDiffInfo>(); | |||
|  | 
 | |||
|  |                 foreach (ClientDiffInfo diff in diffs) | |||
|  |                 { | |||
|  |                     string key = BuildKey.ForMetaDiff(diff); | |||
|  | 
 | |||
|  |                     ClientDiffInfo metaDiff; | |||
|  |                     if (!mCache.TryGetValue(key, out metaDiff)) | |||
|  |                         continue; | |||
|  | 
 | |||
|  |                     result.Add(metaDiff); | |||
|  |                 } | |||
|  | 
 | |||
|  |                 return result; | |||
|  |             } | |||
|  | 
 | |||
|  |             static void ExtractToMetaCache( | |||
|  |                 ITreeViewNode node, | |||
|  |                 int nodeIndex, | |||
|  |                 Dictionary<string, ClientDiffInfo> cache, | |||
|  |                 HashSet<string> indexedKeys) | |||
|  |             { | |||
|  |                 if (node is ClientDiffInfo) | |||
|  |                 { | |||
|  |                     ClientDiffInfo diff = (ClientDiffInfo)node; | |||
|  | 
 | |||
|  |                     string path = diff.DiffWithMount.Difference.Path; | |||
|  | 
 | |||
|  |                     if (!MetaPath.IsMetaPath(path)) | |||
|  |                         return; | |||
|  | 
 | |||
|  |                     string realPath = MetaPath.GetPathFromMetaPath(path); | |||
|  | 
 | |||
|  |                     if (!indexedKeys.Contains(BuildKey.BuildCacheKey( | |||
|  |                         BuildKey.GetCategoryGroup(diff), | |||
|  |                         BuildKey.GetChangeCategory(diff), | |||
|  |                         realPath))) | |||
|  |                         return; | |||
|  | 
 | |||
|  |                     // found foo.c and foo.c.meta | |||
|  |                     // with the same chage types - move .meta to cache | |||
|  |                     cache.Add(BuildKey.ForDiff(diff), diff); | |||
|  |                     ((ChangeCategory)node.GetParent()).RemoveDiffAt(nodeIndex); | |||
|  |                 } | |||
|  | 
 | |||
|  |                 for (int i = node.GetChildrenCount() - 1; i >= 0; i--) | |||
|  |                 { | |||
|  |                     ExtractToMetaCache( | |||
|  |                         node.GetChild(i), | |||
|  |                         i, | |||
|  |                         cache, | |||
|  |                         indexedKeys); | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             HashSet<string> BuildIndexedKeys(List<ClientDiffInfo> diffs) | |||
|  |             { | |||
|  |                 HashSet<string> result = new HashSet<string>(); | |||
|  | 
 | |||
|  |                 foreach (ClientDiffInfo diff in diffs) | |||
|  |                 { | |||
|  |                     if (MetaPath.IsMetaPath(diff.DiffWithMount.Difference.Path)) | |||
|  |                         continue; | |||
|  | 
 | |||
|  |                     result.Add(BuildKey.ForDiff(diff)); | |||
|  |                 } | |||
|  | 
 | |||
|  |                 return result; | |||
|  |             } | |||
|  | 
 | |||
|  |             Dictionary<string, ClientDiffInfo> mCache = | |||
|  |                 new Dictionary<string, ClientDiffInfo>(); | |||
|  | 
 | |||
|  |             static class BuildKey | |||
|  |             { | |||
|  |                 internal static string ForDiff( | |||
|  |                     ClientDiffInfo diff) | |||
|  |                 { | |||
|  |                     return BuildCacheKey( | |||
|  |                         GetCategoryGroup(diff), | |||
|  |                         GetChangeCategory(diff), | |||
|  |                         diff.DiffWithMount.Difference.Path); | |||
|  |                 } | |||
|  | 
 | |||
|  |                 internal static string ForMetaDiff( | |||
|  |                     ClientDiffInfo diff) | |||
|  |                 { | |||
|  |                     return BuildCacheKey( | |||
|  |                         GetCategoryGroup(diff), | |||
|  |                         GetChangeCategory(diff), | |||
|  |                         MetaPath.GetMetaPath(diff.DiffWithMount.Difference.Path)); | |||
|  |                 } | |||
|  | 
 | |||
|  |                 internal static string BuildCacheKey( | |||
|  |                     CategoryGroup categoryGroup, | |||
|  |                     ChangeCategory changeCategory, | |||
|  |                     string path) | |||
|  |                 { | |||
|  |                     string result = string.Concat(changeCategory.Type, ":", path); | |||
|  | 
 | |||
|  |                     if (categoryGroup == null) | |||
|  |                         return result; | |||
|  | 
 | |||
|  |                     return string.Concat(categoryGroup.GetHeaderText(), ":", result); | |||
|  |                 } | |||
|  | 
 | |||
|  |                 internal static ChangeCategory GetChangeCategory(ClientDiffInfo diff) | |||
|  |                 { | |||
|  |                     return (ChangeCategory)diff.GetParent(); | |||
|  |                 } | |||
|  | 
 | |||
|  |                 internal static CategoryGroup GetCategoryGroup(ClientDiffInfo diff) | |||
|  |                 { | |||
|  |                     ChangeCategory changeCategory = GetChangeCategory(diff); | |||
|  | 
 | |||
|  |                     ITreeViewNode categoryGroup = changeCategory.GetParent(); | |||
|  | 
 | |||
|  |                     if (categoryGroup == null) | |||
|  |                         return null; | |||
|  | 
 | |||
|  |                     return (CategoryGroup)categoryGroup; | |||
|  |                 } | |||
|  |             } | |||
|  |         } | |||
|  |     } | |||
|  | } |