/// <summary> /// Generates a sequence of DiffItems representing differences in rawDiffStream. /// </summary> /// <param name="includeUnchangedBlocks"> /// Indicates whether to generate DiffItems for unchanged blocks. /// </param> /// <returns>A DiffItem generator.</returns> public static IEnumerable<DiffItem> EnumerateDifferences( StreamCombiner rawDiffStream, bool includeUnchangedBlocks) { DiffItem prevItem = null; DiffItem item = null; string line = null; do { line = rawDiffStream == null ? null : rawDiffStream.ReadLine(); if (line != null && line.StartsWith("<")) { ++item.BaseLineCount; } else if (line != null && line.StartsWith("-")) { continue; } else if (line != null && line.StartsWith(">")) { ++item.DiffLineCount; } else if (line != null && line.Equals("\\ No newline at end of file")) { // This is a very annoying perforce thing. But we have to account for it. continue; } else { if (item != null) { if (item.DiffLineCount == 0) item.DiffType = DiffType.Deleted; else if (item.BaseLineCount == 0) item.DiffType = DiffType.Added; else item.DiffType = DiffType.Changed; yield return item; prevItem = item; item = null; } if (line != null) { item = new DiffItem(); Match m = DiffDecoder.Match(line); if (!m.Success) yield break; item.BaseStartLineNumber = Int32.Parse(m.Groups[1].Value); // 'a' adds AFTER the line, but we do processing once we get to the line. // So we need to really get to the next line. if (m.Groups[3].Value.Equals("a")) item.BaseStartLineNumber += 1; } if (includeUnchangedBlocks) { var unchangedItem = new DiffItem(); unchangedItem.DiffType = DiffType.Unchanged; unchangedItem.BaseStartLineNumber = prevItem == null ? 1 : prevItem.BaseStartLineNumber + prevItem.BaseLineCount; unchangedItem.BaseLineCount = item == null ? int.MaxValue : item.BaseStartLineNumber - unchangedItem.BaseStartLineNumber; unchangedItem.DiffLineCount = unchangedItem.BaseLineCount; if (unchangedItem.BaseLineCount != 0) yield return unchangedItem; } } } while (line != null); }