/// <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)); }