/// <nodoc/> public GitFileChangeObservable(GitTreeDiffResponse changes, PathTable pathTable) { Contract.Requires(changes != null); Contract.Requires(pathTable != null); m_pathTable = pathTable; Changes = ComputeChangedPathInfo(changes); }
private List <ChangedPathInfo> ComputeChangedPathInfo(GitTreeDiffResponse changes) { var result = new List <ChangedPathInfo>(); // Renames and object type changes are returned as delete on the old object and add on the new object. // So we compute the set of changes for a given path to determine and report type changes var objectTypePerPath = new Dictionary <string, List <GitObjectType> >(); foreach (var change in changes.TreeDiff.DiffEntries) { if (objectTypePerPath.TryGetValue(change.Path, out var objectTypes)) { objectTypes.Add(change.ObjectType); } else { objectTypePerPath[change.Path] = new List <GitObjectType> { change.ObjectType }; } } foreach (var change in changes.TreeDiff.DiffEntries) { PathChanges pathChanges; switch (change.ChangeType) { case VersionControlChangeType.Add: pathChanges = PathChanges.NewlyPresent; break; case VersionControlChangeType.Edit: pathChanges = PathChanges.DataOrMetadataChanged; break; case VersionControlChangeType.Delete: pathChanges = PathChanges.Removed; break; default: throw new NotImplementedException(I($"Change kind '{change.ChangeType}' is not supported")); } // Analyze the type changes now to detect file -> directory and directory -> file var objectTypes = objectTypePerPath[change.Path]; Contract.Assert(objectTypes.Count > 0); if (objectTypes.Count > 1) { var firstType = objectTypes[0]; var lastType = objectTypes[objectTypes.Count - 1]; if (firstType == GitObjectType.Blob && lastType == GitObjectType.Tree) { pathChanges |= PathChanges.NewlyPresentAsDirectory; } else if (firstType == GitObjectType.Tree && lastType == GitObjectType.Blob) { pathChanges |= PathChanges.NewlyPresentAsFile; } } // This assumes BuildXL ran with subst. // TODO: revisit result.Add(new ChangedPathInfo("B:" + change.Path, pathChanges)); // Now trigger membership changes events if the type of change was add or delete if (change.ChangeType == VersionControlChangeType.Add || change.ChangeType == VersionControlChangeType.Delete) { AddAllAssociatedMemebershipChanges(change.Path, result); } } return(result); }