Example #1
0
        /// <nodoc/>
        public GitFileChangeObservable(GitTreeDiffResponse changes, PathTable pathTable)
        {
            Contract.Requires(changes != null);
            Contract.Requires(pathTable != null);

            m_pathTable = pathTable;
            Changes     = ComputeChangedPathInfo(changes);
        }
Example #2
0
        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);
        }