예제 #1
0
        /// <summary>
        /// Method to apply a .diff file to a new Roslyn source file. A small amount of "fuzziness" is
        /// accepted to take into account that the new file may have been updated in a new revision.
        /// But the lines noted as unchanged and removed must not have been changed by the revision.
        /// </summary>
        private static void DoFuzzyPatch(string diffFileFilename, string newFileFilename)
        {
            // Read the two files into storage as lines of text
            string[] diffLines = File.ReadAllLines(diffFileFilename);
            NewFile  newFile   = new NewFile(File.ReadAllLines(newFileFilename));

            // Check the "new" file has not already been updated once. (This assumes .cs files will
            //  have C# comments and/or identifier names that include "Yacks", and .csproj files will
            //  reference the YacksCore assembly.)
            if (newFile.NewFileLines.Exists((string x) => x.Contains("Yacks")))
            {
                Console.WriteLine("File has already been updated once: " + newFileFilename);
                return;
            }

            // Check first two lines in .diff file look like they should, "---" and "+++"
            if (diffLines.Length < 3 || diffLines[0].Substring(0, 3) != "---" ||
                diffLines[1].Substring(0, 3) != "+++")
            {
                DisplayErrorOrInfo("Corrupt .diff file, invalid prefix lines: " + diffFileFilename);
                return;
            }
            int diffIndex = 2;              // Current zero-based location in the .diff file

            // Loop to process the "hunks" in the .diff file
            while (true)
            {
                // Find and check the next "hunk" in the .diff file
                DiffHunk diffHunk = GetNextDiffHunk(diffFileFilename, diffLines, ref diffIndex);
                if (diffHunk == null)
                {
                    return;                      // Error encountered
                }
                if (diffHunk.DiffLines == null)
                {
                    break;                      // No more hunks in .diff file
                }
                // Try to find the location in the new file that matches this hunk
                int newFileIndex = newFile.FindHunkLocation(diffHunk);
                if (newFileIndex == -1)
                {
                    DisplayErrorOrInfo("Unable to find location to apply .diff file 'hunk' at line " +
                                       diffHunk.DiffLineIndex + " for file " + diffFileFilename);
                    return;
                }

                // Apply the .diff file "hunk"
                newFile.ApplyHunk(diffHunk, newFileIndex);
            }

            // Processing was successful if we get to here. Write the result to the disk and display
            //  some info on the console.
            WriteToDisk(newFileFilename, newFile.NewFileLines);
            Console.WriteLine("File in new revision updated: " + newFileFilename);
            Console.WriteLine(string.Format(CultureInfo.InvariantCulture,
                                            "  Lines removed = {0}, lines added = {1}, displacement = {2}.",
                                            newFile.LinesRemoved, newFile.LinesAdded, newFile.DisplacementFactor));
        }