Example #1
0
        private IEnumerable <PathData> EnumerateFiles(ExtendedState oldState, string rootDirectory, string directory)
        {
            if (Directory.Exists(directory))
            {
                foreach (var d in Directory.EnumerateDirectories(directory))
                {
                    if (!this.IsCurrent(oldState))
                    {
                        break;
                    }

                    foreach (var e in this.EnumerateFiles(oldState, rootDirectory, d))
                    {
                        yield return(e);
                    }
                }

                foreach (var f in Directory.EnumerateFiles(directory))
                {
                    if (!this.IsCurrent(oldState))
                    {
                        break;
                    }

                    var path = new PathData(rootDirectory, f);

                    if (oldState.PassesFilters(path.RelativePath))
                    {
                        yield return(path);
                    }
                }
            }
        }
Example #2
0
        private FileDifference CompareFiles(ExtendedState oldState, string left, string right)
        {
            try
            {
                using (var leftStream = new FileStream(left, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    using (var rightStream = new FileStream(right, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        bool areDifferentInWhiteSpace = false;
                        bool leftWasWhiteSpace        = true;
                        bool rightWasWhiteSpace       = true;
                        bool skipRead = false;
                        int  l        = -1;
                        int  r        = -1;
                        while (true)
                        {
                            if (!this.IsCurrent(oldState))
                            {
                                return(FileDifference.Identical);
                            }

                            if (skipRead)
                            {
                                skipRead = false;
                            }
                            else
                            {
                                l = leftStream.ReadByte();
                                r = rightStream.ReadByte();
                            }

                            if (l != r)
                            {
                                if (l == -1)
                                {
                                    return(AreThereNonWhiteSpaceCharactersAtEndOfStream(r, rightStream) ? FileDifference.DifferentExcludingWhiteSpace : FileDifference.DifferentInWhiteSpaceOnly);
                                }
                                else if (r == -1)
                                {
                                    return(AreThereNonWhiteSpaceCharactersAtEndOfStream(l, leftStream) ? FileDifference.DifferentExcludingWhiteSpace : FileDifference.DifferentInWhiteSpaceOnly);
                                }

                                areDifferentInWhiteSpace = true;

                                bool leftIsWhiteSpace  = char.IsWhiteSpace((char)l);
                                bool rightIsWhiteSpace = char.IsWhiteSpace((char)r);

                                if (!(leftIsWhiteSpace && rightIsWhiteSpace))
                                {
                                    if (leftIsWhiteSpace)
                                    {
                                        if (!rightWasWhiteSpace)
                                        {
                                            return(FileDifference.DifferentExcludingWhiteSpace);
                                        }

                                        skipRead = true;
                                        l        = ConsumeWhitespace(leftStream);
                                    }
                                    else if (rightIsWhiteSpace)
                                    {
                                        if (!leftWasWhiteSpace)
                                        {
                                            return(FileDifference.DifferentExcludingWhiteSpace);
                                        }

                                        skipRead = true;
                                        r        = ConsumeWhitespace(rightStream);
                                    }
                                    else
                                    {
                                        return(FileDifference.DifferentExcludingWhiteSpace);
                                    }
                                }

                                leftWasWhiteSpace  = leftIsWhiteSpace;
                                rightWasWhiteSpace = rightIsWhiteSpace;
                            }
                            else if (l == -1)
                            {
                                return(areDifferentInWhiteSpace ? FileDifference.DifferentInWhiteSpaceOnly : FileDifference.Identical);
                            }
                            else
                            {
                                leftWasWhiteSpace = rightWasWhiteSpace = char.IsWhiteSpace((char)l);
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                return(FileDifference.Identical);
            }
        }
Example #3
0
 private bool IsCurrent(ExtendedState state)
 {
     return(_state == state.State);
 }
Example #4
0
        private async Task CalculateDiffs()
        {
            var oldState = new ExtendedState(Volatile.Read(ref _state));

            while (true)
            {
                await this.PostResults(null, "... <working> ...");

                TreeNode root = new TreeNode(null, null, null, string.Empty, FileDifference.All);

                if (oldState.LeftDirectoryExists && oldState.RightDirectoryExists)
                {
                    // Abandon the calculation if _state != oldState (which will cause the CompareExchange call below to fail and
                    // we'll try and compute the differences on the new version of _state;
                    var leftFiles  = new List <PathData>(EnumerateFiles(oldState, oldState.LeftPath, oldState.LeftPath));
                    var rightFiles = new List <PathData>(EnumerateFiles(oldState, oldState.RightPath, oldState.RightPath));

                    var allRightFiles = new HashSet <string>(rightFiles.Select(p => p.RelativePath), StringComparer.OrdinalIgnoreCase);

                    int count      = 0;
                    int leftIndex  = 0;
                    int rightIndex = 0;
                    while (((leftIndex < leftFiles.Count) || (rightIndex < rightFiles.Count)) && this.IsCurrent(oldState))
                    {
                        if (!this.IsCurrent(oldState))
                        {
                            break;
                        }

                        var leftFile  = (leftIndex < leftFiles.Count) ? leftFiles[leftIndex] : _empty;
                        var rightFile = (rightIndex < rightFiles.Count) ? rightFiles[rightIndex] : _empty;

                        if (StringComparer.OrdinalIgnoreCase.Equals(leftFile.RelativePath, rightFile.RelativePath))
                        {
                            root.AddToTree(leftFiles[leftIndex].FullPath, rightFiles[rightIndex].FullPath, rightFile.RelativePath,
                                           CompareFiles(oldState, leftFiles[leftIndex].FullPath, rightFiles[rightIndex].FullPath),
                                           splitlabel: true);

                            ++leftIndex;
                            ++rightIndex;
                        }
                        else if ((leftIndex >= leftFiles.Count) || allRightFiles.Contains(leftFile.RelativePath))
                        {
                            root.AddToTree(null, rightFiles[rightIndex].FullPath, rightFile.RelativePath + " (right only)",
                                           FileDifference.RightOnly, splitlabel: true);
                            ++rightIndex;
                        }
                        else
                        {
                            root.AddToTree(leftFiles[leftIndex].FullPath, null, leftFile.RelativePath + " (left only)",
                                           FileDifference.LeftOnly, splitlabel: true);
                            ++leftIndex;
                        }

                        if ((++count) % 100 == 0)
                        {
                            await this.PostResults(null, "... <working> (" + ((100 * (leftIndex + rightIndex)) / (leftFiles.Count + rightFiles.Count)).ToString() + "%) ...");
                        }
                    }
                }
                else if (oldState.LeftFileExists && oldState.RightFileExists)
                {
                    var leftFile  = Path.GetFileName(oldState.LeftPath);
                    var rightFile = Path.GetFileName(oldState.RightPath);
                    var label     = StringComparer.OrdinalIgnoreCase.Equals(leftFile, rightFile) ? rightFile : (leftFile + " " + rightFile);
                    root.AddToTree(oldState.LeftPath, oldState.RightPath, label,
                                   CompareFiles(oldState, oldState.LeftPath, oldState.RightPath),
                                   splitlabel: true);
                }
                else
                {
                    root.AddToTree(null, null, oldState.LeftPath + Suffix(oldState.LeftFileExists, oldState.LeftDirectoryExists),
                                   FileDifference.DifferentExcludingWhiteSpace, splitlabel: false);
                    root.AddToTree(null, null, oldState.RightPath + Suffix(oldState.RightFileExists, oldState.RightDirectoryExists),
                                   FileDifference.DifferentExcludingWhiteSpace, splitlabel: false);
                }

                await this.PostResults(root, oldState.LeftPath + " .vs. " + oldState.RightPath);

                var result = Interlocked.CompareExchange(ref _state, null, oldState.State);
                if (result == oldState.State)
                {
                    break;
                }

                oldState = new ExtendedState(result);
            }
        }
Example #5
0
        public ExtendedState(State state)
        {
            this.State = state;

            var leftPath  = ExtendedState.GetFullPath(state.LeftPath);
            var rightPath = ExtendedState.GetFullPath(state.RightPath);

            if (Directory.Exists(leftPath))
            {
                leftPath = ExtendedState.GetNormalizedDirectoryName(leftPath);

                this.LeftDirectoryExists = true;
            }
            else if (File.Exists(leftPath))
            {
                this.LeftFileExists = true;
            }

            this.LeftPath = leftPath;

            if (Directory.Exists(rightPath))
            {
                rightPath = ExtendedState.GetNormalizedDirectoryName(rightPath);

                this.RightDirectoryExists = true;
            }
            else if (File.Exists(rightPath))
            {
                this.RightFileExists = true;
            }

            this.RightPath = rightPath;

            if (!string.IsNullOrWhiteSpace(state.Filters))
            {
                foreach (var extension in state.Filters.Split(';'))
                {
                    if (extension.Length != 0)
                    {
                        if (extension[0] == '-')
                        {
                            if (_excluded == null)
                            {
                                _excluded = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                            }

                            _excluded.Add(extension.Substring(1));
                        }
                        else
                        {
                            if (_included == null)
                            {
                                _included = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                            }

                            _included.Add(extension);
                        }
                    }
                }
            }
        }