Пример #1
0
 private IEnumerable<DiffLineViewModel> ConvertLines(DiffHunk h)
 {
     int leftLine = h.OriginalLocation.Line;
     int rightLine = h.ModifiedLocation.Line;
     int index = 0;
     foreach(var line in h.Lines)
     {
         DiffLineViewModel newLine = new DiffLineViewModel()
         {
             Index = index++,
             Type = line.Type,
             Text = line.Content
         };
         switch (line.Type)
         {
             case LineDiffType.Same:
                 newLine.LeftLine = leftLine++;
                 newLine.RightLine = rightLine++;
                 break;
             case LineDiffType.Added:
                 newLine.RightLine = rightLine++;
                 break;
             case LineDiffType.Removed:
                 newLine.LeftLine = leftLine++;
                 break;
         }
         yield return newLine;
     }
 }
Пример #2
0
            /// <summary>
            /// Method to apply a .diff file "hunk" to the new file. At this point everything has been
            /// checked and there should not be any possible error situations.
            /// </summary>
            public void ApplyHunk(DiffHunk diffHunk, int newFileIndex)
            {
                for (int i = diffHunk.DiffLineIndex;
                     i < diffHunk.DiffLineIndex + diffHunk.HunkLines; i++)
                {
                    string s = diffHunk.DiffLines[i];
                    if (s.StartsWith(" ", StringComparison.Ordinal))
                    {
                        if (NewFileLines[newFileIndex] != s.Substring(1))
                        {
                            throw new InvalidOperationException("Programming error.");
                        }
                        newFileIndex++;
                    }
                    else if (s.StartsWith("-", StringComparison.Ordinal))
                    {
                        if (NewFileLines[newFileIndex] != s.Substring(1))
                        {
                            throw new InvalidOperationException("Programming error.");
                        }
                        NewFileLines.RemoveAt(newFileIndex);
                        LinesRemoved++;
                    }
                    else if (s.StartsWith("+", StringComparison.Ordinal))
                    {
                        NewFileLines.Insert(newFileIndex, s.Substring(1));
                        newFileIndex++;
                        LinesAdded++;
                    }
                }

                _fenceIndex = newFileIndex - 1;
            }
Пример #3
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));
        }
Пример #4
0
 private string WriteHunk(DiffHunk arg)
 {
     return String.Format(
         "@@ -{0},{1} +{2},{3} @@{4}",
         arg.OriginalLocation.Line,
         arg.OriginalLocation.Column,
         arg.ModifiedLocation.Line,
         arg.ModifiedLocation.Column,
         String.IsNullOrEmpty(arg.Comment) ? "" : (" " + arg.Comment)) +
         Environment.NewLine +
         String.Join(Environment.NewLine, arg.Lines.Select(WriteLine));
 }
Пример #5
0
            /// <summary>
            /// Method to find the location where the "hunk" from the .diff file should be applied to
            /// the new file.
            /// </summary>
            /// <returns>zero-based index, or -1 for not found</returns>
            public int FindHunkLocation(DiffHunk diffHunk)
            {
                // As a "first guess", assume specified start line (-1 to make zero-based) is correct,
                //  adjusted for the application of previous hunks
                int  firstGuessIndex = diffHunk.FromFileLineNumber - 1 - LinesRemoved + LinesAdded;
                bool hunkFound       = false;

                // Search forward to try to find the hunk, on the assumption it is more likely that
                //  lines have been added to the new file than that lines have been removed
                int testIndex = firstGuessIndex;

                for (; testIndex < NewFileLines.Count; testIndex++)
                {
                    if (TestHunkForMatch(diffHunk, testIndex))
                    {
                        hunkFound = true;
                        break;
                    }
                }

                // If not found via forward search try searching backwards, but only to the "fence
                //  index", so the search does not get back into lines that have already been updated
                if (!hunkFound)
                {
                    testIndex = firstGuessIndex - 1;
                    for (; testIndex > _fenceIndex; testIndex--)
                    {
                        if (TestHunkForMatch(diffHunk, testIndex))
                        {
                            hunkFound = true;
                            break;
                        }
                    }
                }

                // Indicate result of the search, and adjust the "displacement factor"
                if (!hunkFound)
                {
                    return(-1);
                }

                DisplacementFactor += Math.Abs(firstGuessIndex - testIndex);
                return(testIndex);
            }
Пример #6
0
        private DiffLine GetLine(int num, out DiffHunk hunk)
        {
            int offset = 0;
            int i      = 0;

            if (_diffFile.HunkCount == 0)
            {
                hunk = null;
                return(null);
            }
            while (_diffFile[i].LineCount <= num)
            {
                int lc = _diffFile[i].LineCount;
                offset += lc;
                num    -= lc;
                ++i;
            }
            hunk = _diffFile[i];
            return(hunk[num]);
        }
Пример #7
0
            /// <summary>
            /// Method to compare the lines in a .diff hunk with some lines in the new file to see if
            /// they match. Added lines are ignored, but unchanged and removed lines must match
            /// exactly, and there must be at least one unchanged or removed line to ensure a match.
            /// </summary>
            private bool TestHunkForMatch(DiffHunk diffHunk, int testIndex)
            {
                bool toReturn = false;                  // In case no unchanged or removed lines

                for (int i = diffHunk.DiffLineIndex;
                     i < diffHunk.DiffLineIndex + diffHunk.HunkLines; i++)
                {
                    string s = diffHunk.DiffLines[i];
                    if (s.StartsWith("+", StringComparison.Ordinal))
                    {
                        continue;
                    }
                    if (testIndex >= NewFileLines.Count ||
                        NewFileLines[testIndex] != s.Substring(1))
                    {
                        return(false);
                    }
                    toReturn = true;
                    testIndex++;
                }

                return(toReturn);
            }
Пример #8
0
 private DiffLine GetLine(int num, out DiffHunk hunk)
 {
     int offset = 0;
     int i = 0;
     if(_diffFile.HunkCount == 0)
     {
         hunk = null;
         return null;
     }
     while(_diffFile[i].LineCount <= num)
     {
         int lc = _diffFile[i].LineCount;
         offset += lc;
         num -= lc;
         ++i;
     }
     hunk = _diffFile[i];
     return hunk[num];
 }
Пример #9
0
        private static DiffHunk ReadHunk(LineReader reader)
        {
            // Read hunk header
            string header = reader.Current;
            if (String.IsNullOrEmpty(header))
            {
                return null;
            }
            Match m = HunkHeaderRegex.Match(header);
            if (!m.Success)
            {
                // End of file diff
                return null;
            }
            reader.NextLine();

            SourceCoordinate original = ReadSourceCoord(m.Groups["l1"].Value, m.Groups["c1"].Value);
            SourceCoordinate modified = ReadSourceCoord(m.Groups["l2"].Value, m.Groups["c2"].Value);
            string comment = m.Groups["c"].Value.Trim();
            DiffHunk hunk = new DiffHunk(original, modified, comment);

            LineDiff line;
            while ((line = ReadLine(reader)) != null)
            {
                hunk.Lines.Add(line);
            }
            return hunk;
        }