Example #1
0
        /// <summary>
        /// Reads the text content of a file and determines its Encoding.
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="ignoreInsignificantWhiteSpace"></param>
        /// <param name="progress"></param>
        /// <returns></returns>
        public static FileContentInfo GetXmlText(string fileName,
                                                 bool ignoreInsignificantWhiteSpace,
                                                 IDiffProgress progress)
        {
            var contentInfo = new FileContentInfo();

//// This should be created from in-memory text to save IO and support editing
////			using (StreamReader reader = new StreamReader(fileName, Encoding.Default, true))
////			{
////				contentInfo.Lines = GetXmlTextLines(reader, ignoreInsignificantWhiteSpace, progress);
////			}

            // Read the RAW text content
            const int         DefaultBufferSize = 4096;
            const FileOptions DefaultOptions    = FileOptions.Asynchronous | FileOptions.SequentialScan;

            using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultBufferSize, DefaultOptions))
            {
                var bom = new byte[4];                               // Decode bom (if any) and continue to read text content
                stream.Read(bom, 0, 4);
                stream.Seek(0, SeekOrigin.Begin);

                contentInfo.TextEncoding = FileEx.GetEncoding(bom);

                using (StreamReader reader = new StreamReader(stream, contentInfo.TextEncoding))
                {
                    contentInfo.TextContent = reader.ReadToEnd();
                }
            }

            return(contentInfo);
        }
Example #2
0
 public static IList <string> GetFileTextLines(string fileName, IDiffProgress progress)
 {
     using (StreamReader reader = new StreamReader(fileName, Encoding.Default, true))
     {
         return(GetTextLines(reader, progress));
     }
 }
Example #3
0
        private static void GetTextLines(string textA, string textB, TextBinaryDiffArgs args,
                                         out IList <string> a, out IList <string> b,
                                         IDiffProgress progress)
        {
            a = null;
            b = null;
            CompareType compareType = args.CompareType;
            bool        isAuto      = compareType == CompareType.Auto;

            if (compareType == CompareType.Xml || isAuto)
            {
                a = TryGetXmlLines(DiffUtility.GetXmlTextLinesFromXml, "the left side text", textA, !isAuto, args, progress);

                // If A failed to parse with Auto, then there's no reason to try B.
                if (a != null)
                {
                    b = TryGetXmlLines(DiffUtility.GetXmlTextLinesFromXml, "the right side text", textB, !isAuto, args, progress);
                }

                // If we get here and the compare type was XML, then both
                // inputs parsed correctly, and both lists should be non-null.
                // If we get here and the compare type was Auto, then one
                // or both lists may be null, so we'll fallthrough to the text
                // handling logic.
            }

            if (a == null || b == null)
            {
                a = DiffUtility.GetStringTextLines(textA, progress);
                b = DiffUtility.GetStringTextLines(textB, progress);
            }
        }
Example #4
0
        private static IList <string> TryGetXmlLines(
            Func <string, bool, IDiffProgress, IList <string> > converter,
            string name,
            string input,
            bool throwOnError,
            TextBinaryDiffArgs args,
            IDiffProgress progress)
        {
            IList <string> result = null;

            try
            {
                result = converter(input, args.IgnoreXmlWhitespace, progress);
            }
            catch (XmlException ex)
            {
                if (throwOnError)
                {
                    StringBuilder sb = new StringBuilder("An XML comparison was attempted, but an XML exception occurred while parsing ");
                    sb.Append(name).AppendLine(".").AppendLine();
                    sb.AppendLine("Exception Message:").Append(ex.Message);

                    throw new XmlException(sb.ToString(), ex);
                }
            }

            return(result);
        }
Example #5
0
        public IList <string> TryGetXmlLines(
            Func <string, bool, IDiffProgress, IList <string> > converter,
            bool throwOnError,
            TextBinaryDiffArgs args,
            IDiffProgress progress)
        {
            IList <string> result = null;

            try
            {
                if (FileExists)
                {
                    result      = converter(FileNamePath, args.IgnoreXmlWhitespace, progress);
                    _typeOfFile = FileType.Xml;
                }
            }
            catch (XmlException ex)
            {
                if (throwOnError)
                {
                    StringBuilder sb = new StringBuilder("An XML comparison was attempted, but an XML exception occurred while parsing ");
                    sb.Append("'" + FileNamePath + "'").AppendLine(".").AppendLine();
                    sb.AppendLine("Exception Message:").Append(ex.Message);

                    throw new XmlException(sb.ToString(), ex);
                }
            }

            return(result);
        }
Example #6
0
 public static IList <string> GetStringTextLines(string text,
                                                 IDiffProgress progress)
 {
     using (StringReader reader = new StringReader(text))
     {
         return(GetTextLines(reader, progress));
     }
 }
Example #7
0
        public IList <T> GetLongestCommonSubsequence(IDiffProgress progress)
        {
            List <T> result = new List <T>();

            this.GetLcs(new SubArray <T>(this.listA), new SubArray <T>(this.listB), progress, result);

            return(result);
        }
Example #8
0
        /// <summary>Compare to files or string contents and return result via progress object.</summary>
        /// <param name="progress"></param>
        /// <param name="dataSource"></param>
        /// <returns></returns>
        public IDiffProgress ProcessDiff(IDiffProgress progress, IDataSource dataSource)
        {
            try
            {
                DiffBinaryTextResults result = null;

                if (_Args.DiffType == DiffType.File)
                {
                    var fileA = dataSource.CreateFile(_Args.A);
                    var fileB = dataSource.CreateFile(_Args.B);

                    result = GetFileLines(fileA, fileB, _Args, progress);
                }
                else
                {
                    // DiffType in-memory text content
                    result = GetTextLines(TextContentA, TextContentB, _Args, progress);
                }

                if (result.IsComparedAs == CompareType.Text || result.IsComparedAs == CompareType.Xml)
                {
                    // Render Text or XML lines from in-memory text content
                    if (_Args.DiffType == DiffType.File)
                    {
                        result = GetTextLines(result, _Args, progress);
                    }

                    // Assumption: Binary cannot be edit and RAW data cannot be stored in string
                    //             Therefore, binary lines are rendered only once directly from file
                    TextOriginalA = result.A.TextContent;
                    TextContentA  = result.A.TextContent;
                    TextEncodingA = result.A.TextEncoding;

                    TextOriginalB = result.B.TextContent;
                    TextContentB  = result.B.TextContent;
                    TextEncodingB = result.B.TextEncoding;
                }

                ListA = result.A.Lines;
                ListB = result.B.Lines;

                IsComparedAs         = result.IsComparedAs;
                IgnoreCase           = result.IgnoreCase;
                IgnoreTextWhitespace = result.IgnoreTextWhitespace;

                TextDiff diff = new TextDiff(_Args.HashType, IgnoreCase, IgnoreTextWhitespace,
                                             result.LeadingCharactersToIgnore, !_Args.ShowChangeAsDeleteInsert);

                Script = diff.Execute(ListA, ListB, progress);

                progress.ResultData = this;

                return(progress);
            }
            finally
            {
            }
        }
Example #9
0
 public static IList <string> GetXmlTextLines(string fileName,
                                              bool ignoreInsignificantWhiteSpace,
                                              IDiffProgress progress)
 {
     using (StreamReader reader = new StreamReader(fileName, Encoding.Default, true))
     {
         return(GetXmlTextLines(reader, ignoreInsignificantWhiteSpace, progress));
     }
 }
Example #10
0
 public static IList <string> GetXmlTextLinesFromXml(string xml,
                                                     bool ignoreInsignificantWhiteSpace,
                                                     IDiffProgress progress)
 {
     using (StringReader reader = new StringReader(xml))
     {
         return(GetXmlTextLines(reader, ignoreInsignificantWhiteSpace, progress));
     }
 }
Example #11
0
        private static void GetFileLines(string fileNameA, string fileNameB,
                                         out IList <string> a, out IList <string> b,
                                         out int leadingCharactersToIgnore,
                                         TextBinaryDiffArgs args,
                                         IDiffProgress progress)
        {
            a = null;
            b = null;
            leadingCharactersToIgnore = 0;
            CompareType compareType = args.CompareType;

            if (compareType == CompareType.Binary ||
                (args.IsAuto && (DiffUtility.IsBinaryFile(fileNameA) || DiffUtility.IsBinaryFile(fileNameB))))
            {
                using (FileStream fileA = File.OpenRead(fileNameA))
                    using (FileStream fileB = File.OpenRead(fileNameB))
                    {
                        BinaryDiff diff = new BinaryDiff
                        {
                            FootprintLength = args.BinaryFootprintLength
                        };

                        AddCopyCollection addCopy = diff.Execute(fileA, fileB);

                        BinaryDiffLines lines = new BinaryDiffLines(fileA, addCopy, args.BinaryFootprintLength);
                        a = lines.BaseLines;
                        b = lines.VersionLines;
                        leadingCharactersToIgnore = BinaryDiffLines.PrefixLength;
                    }
            }

            if (compareType == CompareType.Xml || (args.IsAuto && (a == null || b == null)))
            {
                a = TryGetXmlLines(DiffUtility.GetXmlTextLines, fileNameA, fileNameA, !args.IsAuto, args, progress);

                // If A failed to parse with Auto, then there's no reason to try B.
                if (a != null)
                {
                    b = TryGetXmlLines(DiffUtility.GetXmlTextLines, fileNameB, fileNameB, !args.IsAuto, args, progress);
                }

                // If we get here and the compare type was XML, then both
                // inputs parsed correctly, and both lists should be non-null.
                // If we get here and the compare type was Auto, then one
                // or both lists may be null, so we'll fallthrough to the text
                // handling logic.
            }

            if (a == null || b == null)
            {
                a = DiffUtility.GetFileTextLines(fileNameA, progress);
                b = DiffUtility.GetFileTextLines(fileNameB, progress);
            }
        }
Example #12
0
        public static IList <string> GetTextLines(TextReader reader,
                                                  IDiffProgress progress)
        {
            IList <string> result = new List <string>();

            while (reader.Peek() > -1)
            {
                progress.Token.ThrowIfCancellationRequested();

                string line = reader.ReadLine();
                result.Add(line);
            }

            return(result);
        }
Example #13
0
        public static FileContentInfo GetXmlTextFromXml(string xml,
                                                        bool ignoreInsignificantWhiteSpace,
                                                        IDiffProgress progress)
        {
            var result = new FileContentInfo();

            result.TextContent = xml;

            using (StringReader reader = new StringReader(xml))
            {
                result.Lines = GetXmlTextLines(reader, ignoreInsignificantWhiteSpace, progress);
            }

            return(result);
        }
Example #14
0
        /// <summary>
        /// Gets an <see cref="EditScript"/> for comparing a list of right and left strings
        /// (sometimes also refered to as stringA and stringB or sequenceA and sequenceB).
        /// </summary>
        /// <param name="listA">sequenceA</param>
        /// <param name="listB">sequenceB</param>
        public EditScript Execute(IList <string> listA, IList <string> listB
                                  , IDiffProgress progress)
        {
            // Convert input string lists into arrays of integer hash values
            int[] hashA = this.HashStringList(listA);
            int[] hashB = this.HashStringList(listB);

            // Construct MyersDiff<int> object from arrays of int hash values that represent the original string input
            MyersDiff <int> diff = new MyersDiff <int>(hashA, hashB, this.supportChangeEditType);

            // Gets an EditScript instance that describes all Edits necessary to transform ListA into ListB.
            EditScript result = diff.Execute(progress);

            return(result);
        }
Example #15
0
        /// <summary>
        /// Gets an edit script instance that gives all the Edits necessary to transform A into B.
        /// </summary>
        /// <returns>The edit script which is a list of <see cref="Edit"/> objects that describes the transformation.</returns>
        public EditScript Execute(IDiffProgress progress)
        {
            List <Point> matchPoints = new List <Point>();

            SubArray <T> subArrayA = new SubArray <T>(this.listA);
            SubArray <T> subArrayB = new SubArray <T>(this.listB);

            this.GetMatchPoints(subArrayA, subArrayB, matchPoints, progress);
            Debug.Assert(matchPoints.Count == this.GetLongestCommonSubsequenceLength(), "The number of match points must equal the LCS length.");

            EditScript result = this.ConvertMatchPointsToEditScript(subArrayA.Length, subArrayB.Length, matchPoints);

            Debug.Assert(result.TotalEditLength == this.GetShortestEditScriptLength(), "The total edit length must equal the SES length.");

            return(result);
        }
Example #16
0
        /// <summary>
        /// Compares <paramref name="directoryA"/> with <paramref name="directoryB"/> using the comparison
        /// options as defined in the constructor of this class.
        /// </summary>
        /// <param name="directoryA"></param>
        /// <param name="directoryB"></param>
        /// <returns>Null if an unkown error occured or if either directory cannot be accessed
        /// (or does not exist), otherwise returns a <see cref="IDiffProgress"/> object
        /// where the <see cref="IDiffProgress.ResultData"/> property contains a
        /// <see cref="IDirectoryDiffRoot"/> data structure that describes the directory
        /// differences in detail.</returns>
        public IDiffProgress Execute(string directoryA,
                                     string directoryB,
                                     IDiffProgress progress)
        {
            try
            {
                var dirA = new DirectoryInfo(directoryA);
                var dirB = new DirectoryInfo(directoryB);

                return(this.Execute(dirA, dirB, progress));
            }
            catch
            {
                return(null);
            }
        }
Example #17
0
        /// <summary>
        /// Compares <paramref name="directoryA"/> with <paramref name="directoryB"/> using the comparison
        /// options as defined in the constructor of this class.
        /// </summary>
        /// <param name="directoryA"></param>
        /// <param name="directoryB"></param>
        /// <param name="progress"></param>
        /// <param name="source"></param>
        /// <returns>Null if an unkown error occured or if either directory cannot be accessed
        /// (or does not exist), otherwise returns a <see cref="IDiffProgress"/> object
        /// where the <see cref="IDiffProgress.ResultData"/> property contains a
        /// <see cref="IDirectoryDiffRoot"/> data structure that describes the directory
        /// differences in detail.</returns>
        public IDiffProgress Execute(string directoryA,
                                     string directoryB,
                                     IDiffProgress progress,
                                     IDataSource source)
        {
            try
            {
                var dirA = source.CreateDirectory(directoryA);
                var dirB = source.CreateDirectory(directoryB);

                return(this.Execute(dirA, dirB, progress, source));
            }
            catch
            {
                return(null);
            }
        }
Example #18
0
        public IDiffProgress ProcessDiff(IDiffProgress progress)
        {
            progress.ShowIndeterminatedProgress();

            try
            {
                if (System.IO.File.Exists(_Args.A) == false ||
                    System.IO.File.Exists(_Args.B) == false)
                {
                    return(progress);
                }

                IList <string> a, b;
                int            leadingCharactersToIgnore = 0;

                if (_Args.DiffType == DiffType.File)
                {
                    GetFileLines(_Args.A, _Args.B, out a, out b, out leadingCharactersToIgnore, _Args, progress);
                }
                else
                {
                    GetTextLines(_Args.A, _Args.B, _Args, out a, out b, progress);
                }

                IsBinaryCompare      = leadingCharactersToIgnore > 0;
                IgnoreCase           = IsBinaryCompare ? false : _Args.IgnoreCase;
                IgnoreTextWhitespace = IsBinaryCompare ? false : _Args.IgnoreTextWhitespace;
                TextDiff diff = new TextDiff(_Args.HashType, IgnoreCase, IgnoreTextWhitespace, leadingCharactersToIgnore, !_Args.ShowChangeAsDeleteInsert);

                ListA  = a;
                ListB  = b;
                Script = diff.Execute(a, b);

                progress.ResultData = this;

                return(progress);
            }
            finally
            {
                progress.ProgressDisplayOff();
            }
        }
Example #19
0
        private static IList <string> GetXmlTextLines(TextReader textReader,
                                                      bool ignoreInsignificantWhitespace,
                                                      IDiffProgress progress)
        {
            XmlReaderSettings settings = new XmlReaderSettings
            {
                CheckCharacters  = false,
                CloseInput       = true,
                DtdProcessing    = DtdProcessing.Ignore,
                IgnoreWhitespace = ignoreInsignificantWhitespace,
                ValidationFlags  = System.Xml.Schema.XmlSchemaValidationFlags.None,
                ValidationType   = ValidationType.None,
                XmlResolver      = null
            };

            using (XmlReader xmlReader = XmlReader.Create(textReader, settings))
            {
                IList <string> result = GetXmlTextLines(xmlReader, progress);
                return(result);
            }
        }
Example #20
0
        private DiffBinaryTextResults GetTextLines(string textA, string textB
                                                   , TextBinaryDiffArgs args
                                                   , IDiffProgress progress)
        {
            FileContentInfo af = null, bf = null;

            bool isAuto = args.CompareType == CompareType.Auto;

            if (args.CompareType == CompareType.Xml || isAuto)
            {
                af = TryGetXmlText(DiffUtility.GetXmlTextFromXml, "the left side text", textA, !isAuto, args, progress);

                // If A failed to parse with Auto, then there's no reason to try B.
                if (af != null)
                {
                    bf = TryGetXmlText(DiffUtility.GetXmlTextFromXml, "the right side text", textB, !isAuto, args, progress);
                }

                // If we get here and the compare type was XML, then both
                // inputs parsed correctly, and both lists should be non-null.
                // If we get here and the compare type was Auto, then one
                // or both lists may be null, so we'll fallthrough to the text
                // handling logic.
            }

            if (af == null || bf == null)
            {
                af = new FileContentInfo();
                bf = new FileContentInfo();

                af.Lines = DiffUtility.GetStringTextLines(textA, progress);
                bf.Lines = DiffUtility.GetStringTextLines(textB, progress);
            }

            af.TextContent = textA;
            bf.TextContent = textB;
            DiffBinaryTextResults result = new DiffBinaryTextResults(CompareType.Text, af, bf);

            return(result);
        }
Example #21
0
        private DiffBinaryTextResults GetTextLines(DiffBinaryTextResults src
                                                   , TextBinaryDiffArgs args
                                                   , IDiffProgress progress)
        {
            IList <string> a = null, b = null;

            bool isAuto = args.CompareType == CompareType.Auto;

            if (args.CompareType == CompareType.Xml || isAuto)
            {
                a = TryGetXmlText(DiffUtility.GetXmlTextLinesFromXml, "the left side text", src.A.TextContent, !isAuto, args, progress);

                // If A failed to parse with Auto, then there's no reason to try B.
                if (a != null)
                {
                    b = TryGetXmlText(DiffUtility.GetXmlTextLinesFromXml, "the right side text", src.B.TextContent, !isAuto, args, progress);
                }

                // If we get here and the compare type was XML, then both
                // inputs parsed correctly, and both lists should be non-null.
                // If we get here and the compare type was Auto, then one
                // or both lists may be null, so we'll fallthrough to the text
                // handling logic.
            }

            if (a == null || b == null)
            {
                a = DiffUtility.GetStringTextLines(src.A.TextContent, progress);
                b = DiffUtility.GetStringTextLines(src.B.TextContent, progress);
            }
            else
            {
                src.IsComparedAs = CompareType.Xml;
            }

            src.A.Lines = a;
            src.B.Lines = b;

            return(src);
        }
Example #22
0
        private void GetLcs(SubArray <T> subArrayA, SubArray <T> subArrayB
                            , IDiffProgress progress
                            , List <T> output)
        {
            if (subArrayA.Length > 0 && subArrayB.Length > 0)
            {
                // Find the length D and the middle snake from (x,y) to (u,v)
                int x, u, k;
                int d = this.FindMiddleSnake(subArrayA, subArrayB, progress, out x, out u, out k);
                int y = x - k;
                int v = u - k;

                if (d > 1)
                {
                    this.GetLcs(new SubArray <T>(subArrayA, 1, x), new SubArray <T>(subArrayB, 1, y), progress, output);

                    for (int i = x + 1; i <= u; i++)
                    {
                        output.Add(subArrayA[i]);
                    }

                    this.GetLcs(new SubArray <T>(subArrayA, u + 1, subArrayA.Length - u),
                                new SubArray <T>(subArrayB, v + 1, subArrayB.Length - v), progress, output);
                }
                else if (subArrayB.Length > subArrayA.Length)
                {
                    for (int i = 1; i <= subArrayA.Length; i++)
                    {
                        output.Add(subArrayA[i]);
                    }
                }
                else
                {
                    for (int i = 1; i <= subArrayB.Length; i++)
                    {
                        output.Add(subArrayB[i]);
                    }
                }
            }
        }
Example #23
0
        public static IList <string> GetXmlTextLines(XmlReader reader, IDiffProgress progress)
        {
            XmlWriterSettings settings = new XmlWriterSettings
            {
                CheckCharacters     = false,
                CloseOutput         = true,
                Indent              = true,
                IndentChars         = "\t",
                NewLineOnAttributes = true
            };

            StringBuilder sb = new StringBuilder();

            using (XmlWriter writer = XmlWriter.Create(sb, settings))
            {
                writer.WriteNode(reader, false);
            }

            IList <string> result = GetStringTextLines(sb.ToString(), progress);

            return(result);
        }
Example #24
0
        /// <summary>
        /// Compares <paramref name="directoryA"/> with <paramref name="directoryB"/> using the comparison
        /// options as defined in the constructor of this class.
        /// </summary>
        /// <param name="directoryA"></param>
        /// <param name="directoryB"></param>
        /// <param name="progress"></param>
        /// <param name="source"></param>
        /// <returns>Null if an unkown error occured or if either directory cannot be accessed
        /// (or does not exist), otherwise returns a <see cref="IDiffProgress"/> object
        /// where the <see cref="IDiffProgress.ResultData"/> property contains a
        /// <see cref="IDirectoryDiffRoot"/> data structure that describes the directory
        /// differences in detail.</returns>
        public IDiffProgress Execute(IDirectoryInfo directoryA,
                                     IDirectoryInfo directoryB,
                                     IDiffProgress progress,
                                     IDataSource source)
        {
            try
            {
                // Create a faux base entry to pass to Execute
                var diffRoot = new DirectoryDiffRoot(directoryA.FullName,
                                                     directoryB.FullName,
                                                     _Recursive, _Filter, _DiffMode, source);

                progress.ResultData = diffRoot;
                progress.ShowIndeterminatedProgress();

                if (directoryA.Exists == false || directoryB.Exists == false)
                {
                    return(null);
                }

                // directory diff match
                int directories = this.BuildSubDirs(directoryA, directoryB,
                                                    _Recursive, _Filter, diffRoot);

                progress.ShowDeterminatedProgress(0, 0, directories);
                this.AddFiles(diffRoot, progress);

                return(progress);
            }
            catch (Exception exp)
            {
                progress.LogException(exp);
                return(null);
            }
            finally
            {
                progress.ProgressDisplayOff();
            }
        }
Example #25
0
        /// <summary>
        /// Compares two files using binary or text comparison methods.
        /// </summary>
        /// <param name="fileA"></param>
        /// <param name="fileB"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="args"></param>
        /// <param name="progress"></param>
        private DiffBinaryTextResults GetFileLines(IFileInfo fileA
                                                   , IFileInfo fileB
                                                   , TextBinaryDiffArgs args
                                                   , IDiffProgress progress)
        {
            // Nothing to compare if both files do not exist
            if (fileA.FileExists == false && fileB.FileExists == false)
            {
                return(new DiffBinaryTextResults(CompareType.Text, new FileContentInfo(), new FileContentInfo()));
            }

            if (args.CompareType == CompareType.Binary ||
                (args.IsAuto && fileA.Is == FileType.Binary || fileB.Is == FileType.Binary))
            {
                return(GetBinaryFileLines(fileA, fileB, args, progress));
            }

            FileContentInfo af = null, bf = null;

            if (fileA.FileExists)
            {
                af = AsyncPump.Run(() => FileEx.GetFileTextAsync(fileA.FullName));
            }
            else
            {
                af = new FileContentInfo();
            }

            if (fileB.FileExists)
            {
                bf = AsyncPump.Run(() => FileEx.GetFileTextAsync(fileB.FullName));
            }
            else
            {
                bf = new FileContentInfo();
            }

            return(new DiffBinaryTextResults(CompareType.Text, af, bf));
        }
Example #26
0
        public static IList <string> GetTextLines(TextReader reader,
                                                  IDiffProgress progress)
        {
            IList <string> result = new List <string>();

            try
            {
                while (reader.Peek() > -1)
                {
                    progress.Token.ThrowIfCancellationRequested();

                    string line = reader.ReadLine();
                    result.Add(line);
                }
            }
            catch
            {
                // Not catching this but returning at default empty list
            }

            return(result);
        }
Example #27
0
        /// <summary>
        /// Adds files into a given <paramref name="root"/> directory structure of sub-directories
        /// and re-evaluates their status in terms of difference.
        ///
        /// The algorithm used implements a Post-Order traversal algorithm which also allows us
        /// to aggregate results (sub-directory is different, size) up-wards through the hierarchy.
        /// </summary>
        /// <param name="root"></param>
        private void AddFiles(DirectoryDiffRoot root,
                              IDiffProgress progress)
        {
            int CountDirs = 0;

            // If the base paths are the same, we don't need to check for file differences.
            bool checkIfFilesAreDifferent = string.Compare(root.RootPathA, root.RootPathB, true) != 0;

            var toVisit          = new Stack <IDirectoryDiffEntry>();
            var visitedAncestors = new Stack <IDirectoryDiffEntry>();

            toVisit.Push(root.RootEntry);
            while (toVisit.Count > 0)
            {
                if (progress != null)
                {
                    if (progress.Token.IsCancellationRequested)
                    {
                        progress.Token.ThrowIfCancellationRequested();
                    }
                }

                var node = toVisit.Peek();
                if (node.CountSubDirectories() > 0)
                {
                    if (PeekOrDefault(visitedAncestors) != node)
                    {
                        visitedAncestors.Push(node);
                        PushReverse(toVisit, node.Subentries.ToList());
                        continue;
                    }

                    visitedAncestors.Pop();
                }

                // Load files only if either directory is available and recursion is on
                // -> Load files only for root directory if recursion is turned off
                if ((node.InA == true || node.InB == true) && (this._Recursive || string.IsNullOrEmpty(node.BasePath)))
                {
                    if (node.CountSubDirectories() > 0)
                    {
                        foreach (var item in node.Subentries)                         // Aggregate size of sub-directories up
                        {
                            if (progress != null)
                            {
                                if (progress.Token.IsCancellationRequested)
                                {
                                    progress.Token.ThrowIfCancellationRequested();
                                }
                            }

                            CountDirs++;
                            if (progress != null)
                            {
                                if (progress != null)
                                {
                                    progress.UpdateDeterminatedProgress(CountDirs);
                                }
                            }

                            if (node.InA == true)
                            {
                                node.LengthA += item.LengthA;
                            }

                            if (node.InB == true)
                            {
                                node.LengthB += item.LengthB;
                            }
                        }
                    }

                    string         sDirA, sDirB;
                    IDirectoryInfo dirA = null, dirB = null;
                    bool           dirA_Exists = false;
                    bool           dirB_Exists = false;

                    try
                    {
                        if (node.InA)
                        {
                            sDirA       = root.Source.Combine(root.RootPathA, node.BasePath);
                            dirA        = root.Source.CreateDirectory(sDirA);
                            dirA_Exists = dirA.Exists;
                        }
                    }
                    catch                    // This may throw on non-existing, authorization issues
                    {                        // So, we catch it it and ignore these for now
                        dirA_Exists = false;
                    }

                    try
                    {
                        if (node.InB)
                        {
                            sDirB       = root.Source.Combine(root.RootPathB, node.BasePath);
                            dirB        = root.Source.CreateDirectory(sDirB);
                            dirB_Exists = dirB.Exists;
                        }
                    }
                    catch                    // This may throw on non-existing, authorization issues
                    {                        // So, we catch it it and ignore these for now
                        dirB_Exists = false;
                    }

                    if (dirA_Exists == true || dirB_Exists == true)
                    {
                        // Get the arrays of files and merge them into 1 list
                        IFileInfo[]      filesA, filesB;
                        Merge.MergeIndex mergeIdx = null;
                        if (root.Filter == null)
                        {
                            if (dirA_Exists)
                            {
                                filesA = dirA.GetFiles();
                            }
                            else
                            {
                                filesA = null;
                            }

                            if (dirB_Exists)
                            {
                                filesB = dirB.GetFiles();
                            }
                            else
                            {
                                filesB = null;
                            }

                            mergeIdx = new Merge.MergeIndex(filesA, filesB, false, _ShowOnlyInA, _ShowOnlyInB);
                        }
                        else
                        {
                            if (dirA_Exists)
                            {
                                filesA = root.Filter.Filter(dirA);
                            }
                            else
                            {
                                filesA = null;
                            }

                            if (dirB_Exists)
                            {
                                filesB = root.Filter.Filter(dirB);
                            }
                            else
                            {
                                filesB = null;
                            }

                            // Assumption: Filter generates sorted entries
                            mergeIdx = new Merge.MergeIndex(filesA, filesB, true, _ShowOnlyInA, _ShowOnlyInB);
                        }

                        // Merge and Diff them
                        mergeIdx.Merge();

                        double lengthSumA, lengthSumB;
                        DiffFiles(root, mergeIdx, node, checkIfFilesAreDifferent, out lengthSumA, out lengthSumB);

                        // Add size of files to size of this directory (which includes size of sub-directories)
                        if (dirA_Exists)
                        {
                            node.LengthA += lengthSumA;
                        }

                        if (dirB_Exists)
                        {
                            node.LengthB += lengthSumB;
                        }

                        node.SetDiffBasedOnChildren(_IgnoreDirectoryComparison);
                    }
                }

                toVisit.Pop();
            }
        }
Example #28
0
        private static void GetBinaryFileLines(FileCompInfo fileA, FileCompInfo fileB,
                                               TextBinaryDiffArgs args,
                                               IDiffProgress progress,
                                               out IList <string> a, out IList <string> b,
                                               out int leadingCharactersToIgnore)
        {
            a = new List <string>();
            b = new List <string>();
            leadingCharactersToIgnore = BinaryDiffLines.PrefixLength;

            // Neither left nor right file exist or cannot be accessed
            if (fileA.FileExists == false && fileB.FileExists == false)
            {
                return;
            }

            Stream fileStreamA = null, fileStreamB = null;

            try
            {
                // Open the file or an internal empty stream to compare against
                if (fileA.FileExists)
                {
                    fileStreamA = File.OpenRead(fileA.FileNamePath);
                }
                else
                {
                    fileStreamA = Assembly.GetExecutingAssembly().GetManifestResourceStream("AehnlichLib.Binaries.Resources.NonExistingFile.bin");
                }

                // Open the file or an internal empty stream to compare against
                if (fileB.FileExists)
                {
                    fileStreamB = File.OpenRead(fileB.FileNamePath);
                }
                else
                {
                    fileStreamB = Assembly.GetExecutingAssembly().GetManifestResourceStream("AehnlichLib.Binaries.Resources.NonExistingFile.bin");
                }

                BinaryDiff diff = new BinaryDiff
                {
                    FootprintLength = args.BinaryFootprintLength
                };

                AddCopyCollection addCopy = diff.Execute(fileStreamA, fileStreamB, progress);

                BinaryDiffLines lines = new BinaryDiffLines(fileStreamA, addCopy, args.BinaryFootprintLength);
                a = lines.BaseLines;
                b = lines.VersionLines;
                leadingCharactersToIgnore = BinaryDiffLines.PrefixLength;
            }
            finally
            {
                if (fileStreamA != null)
                {
                    fileStreamA.Dispose();
                }

                if (fileStreamB != null)
                {
                    fileStreamB.Dispose();
                }
            }

            return;
        }
Example #29
0
        private static void GetFileLines(FileCompInfo fileA,
                                         FileCompInfo fileB,
                                         out IList <string> a, out IList <string> b,
                                         out int leadingCharactersToIgnore,
                                         TextBinaryDiffArgs args,
                                         IDiffProgress progress)
        {
            a = null;
            b = null;
            leadingCharactersToIgnore = 0;
            CompareType compareType = args.CompareType;

            // Nothing to compare if both files do not exist
            if (fileA.FileExists == false && fileB.FileExists == false)
            {
                a = new List <string>();
                b = new List <string>();
                return;
            }

            if (compareType == CompareType.Binary ||
                (args.IsAuto && fileA.Is == FileType.Binary || fileB.Is == FileType.Binary))
            {
                GetBinaryFileLines(fileA, fileB, args, progress, out a, out b, out leadingCharactersToIgnore);
                return;
            }

            if (compareType == CompareType.Xml || (args.IsAuto && (a == null || b == null)))
            {
                a = fileA.TryGetXmlLines(DiffUtility.GetXmlTextLines, !args.IsAuto, args, progress);

                // If A failed to parse with Auto, then there's no reason to try B.
                if (fileA.Is == FileType.Xml)
                {
                    b = fileB.TryGetXmlLines(DiffUtility.GetXmlTextLines, !args.IsAuto, args, progress);
                }

                // If we get here and the compare type was XML, then both
                // inputs parsed correctly, and both lists should be non-null.
                // If we get here and the compare type was Auto, then one
                // or both lists may be null, so we'll fallthrough to the text
                // handling logic.
            }

            if (fileA.Is != FileType.Xml || fileB.Is != FileType.Xml)
            {
                if (fileA.FileExists)
                {
                    a = DiffUtility.GetFileTextLines(fileA.FileNamePath, progress);
                }
                else
                {
                    a = new List <string>();
                }

                if (fileB.FileExists)
                {
                    b = DiffUtility.GetFileTextLines(fileB.FileNamePath, progress);
                }
                else
                {
                    b = new List <string>();
                }
            }
        }
Example #30
0
        private void GetMatchPoints(SubArray <T> subArrayA, SubArray <T> subArrayB, List <Point> matchPoints,
                                    IDiffProgress progress)
        {
            if (progress != null)
            {
                progress.Token.ThrowIfCancellationRequested();
            }

            if (subArrayA.Length > 0 && subArrayB.Length > 0)
            {
                // Find the middle snake from (x,y) to (u,v)
                int x, u, k;
                int d = this.FindMiddleSnake(subArrayA, subArrayB, progress, out x, out u, out k);
                int y = x - k;
                int v = u - k;

                if (d > 1)
                {
                    this.GetMatchPoints(new SubArray <T>(subArrayA, 1, x), new SubArray <T>(subArrayB, 1, y), matchPoints, progress);

                    for (int i = x + 1; i <= u; i++)
                    {
                        // Output absolute X and Y (not relative to the current subarray)
                        matchPoints.Add(new Point(i + subArrayA.Offset, i - k + subArrayB.Offset));
                    }

                    this.GetMatchPoints(
                        new SubArray <T>(subArrayA, u + 1, subArrayA.Length - u),
                        new SubArray <T>(subArrayB, v + 1, subArrayB.Length - v),
                        matchPoints, progress);
                }
                else
                {
                    // If there are no differences, we have to output all of the points.
                    // If there's only one difference, we have to output all of the
                    // match points, skipping the single point that is different.
                    Debug.Assert(d == 0 || Math.Abs(subArrayA.Length - subArrayB.Length) == 1, "A and B's lengths must differ by 1 if D == 1");

                    // Only go to the minimum of the two lengths since that's the
                    // most that can possibly match between the two subsequences.
                    int n = subArrayA.Length;
                    int m = subArrayB.Length;
                    if (m > n)
                    {
                        // Output A[1..N] as match points
                        int currentY = 1;
                        for (int i = 1; i <= n; i++)
                        {
                            // We must skip the one difference when we hit it
                            if (subArrayA[i].CompareTo(subArrayB[currentY]) != 0)
                            {
                                currentY++;
                            }

                            matchPoints.Add(new Point(i + subArrayA.Offset, currentY + subArrayB.Offset));
                            currentY++;
                        }
                    }
                    else
                    {
                        // Output B[1..M] as match points
                        int currentX = 1;
                        for (int i = 1; i <= m; i++)
                        {
                            // We must skip the one difference when we hit it
                            if (subArrayA[currentX].CompareTo(subArrayB[i]) != 0)
                            {
                                currentX++;
                            }

                            matchPoints.Add(new Point(currentX + subArrayA.Offset, i + subArrayB.Offset));
                            currentX++;
                        }
                    }
                }
            }
        }