private static string ReadLine(IStringReader reader) { // read line: var line = reader.ReadLine(); if (line == null) { return(null); } var result = new StringBuilder(line); StringHelper.Trim(result); if (result.Length == 0) { return(null); } // is this line split to several lines, as it ends with '\\' char: bool isMultiline = CheckIfMultiLine(result); if (isMultiline) { result.Remove(result.Length - 1, 1); var buffer = new StringBuilder(); while (isMultiline) { var nextLine = reader.ReadLine(); if (nextLine == null) { break; } buffer.Append(nextLine); StringHelper.Trim(buffer); isMultiline = CheckIfMultiLine(buffer); if (isMultiline) { buffer.Remove(buffer.Length - 1, 1); } result.Append(buffer); buffer.Remove(0, buffer.Length); } } return(result.ToString()); }
private static void VerifyReadingByLines(IStringReader reader) { var line = reader.ReadLine(); Assert.IsNotNull(reader); Assert.AreEqual(string.Empty, line); Assert.AreEqual('\n', reader.CurrentChar); Assert.AreEqual(0, reader.Line); Assert.AreEqual(0, reader.LineOffset); line = reader.ReadLine(); Assert.AreEqual(string.Empty, line); Assert.AreEqual('\n', reader.CurrentChar); Assert.AreEqual(1, reader.Line); Assert.AreEqual(1, reader.LineOffset); }
internal static void ParseSummary(IStringReader reader, ChangeSetDetail detail) { reader.SkipWhitespace(); while (!reader.Done) { string line = reader.ReadLine(); if (ParserHelpers.IsSingleNewLine(line)) { break; } else if (line.Contains('\t')) { // n n path string[] parts = line.Split('\t'); int insertions; Int32.TryParse(parts[0], out insertions); int deletions; Int32.TryParse(parts[1], out deletions); string path = parts[2].TrimEnd(); detail.Files[path] = new FileInfo { Insertions = insertions, Deletions = deletions, Binary = parts[0] == "-" && parts[1] == "-" }; } else { // n files changed, n insertions(+), n deletions(-) ParserHelpers.ParseSummaryFooter(line, detail); } } }
private static void VerifyEmptyReadingByLines(IStringReader reader) { Assert.IsNotNull(reader); Assert.IsTrue(reader.IsEmpty); Assert.AreEqual(null, reader.ReadLine()); Assert.AreEqual(0, reader.Line); Assert.AreEqual(-1, reader.LineOffset); Assert.AreEqual(char.MinValue, reader.CurrentChar); }
private static FileDiff ParseDiffHeader(IStringReader reader, ChangeSetDetail merge) { string fileName = ParseFileName(reader.ReadLine()); bool binary = false; while (!reader.Done) { string line = reader.ReadLine(); if (line.StartsWith("@@", StringComparison.Ordinal)) { reader.PutBack(line.Length); break; } else if (line.StartsWith("GIT binary patch", StringComparison.Ordinal)) { binary = true; } } if (binary) { // Skip binary files reader.ReadToEnd(); } var diff = new FileDiff(fileName) { Binary = binary }; // Skip files from merged changesets if (merge != null && merge.Files.ContainsKey(fileName)) { return(null); } return(diff); }
internal static IEnumerable <FileStatus> ParseStatus(IStringReader reader) { reader.SkipWhitespace(); while (!reader.Done) { var subReader = reader.ReadLine().AsReader(); string status = subReader.ReadUntilWhitespace().Trim(); string path = subReader.ReadLine().Trim(); yield return(new FileStatus(path, ConvertStatus(status))); reader.SkipWhitespace(); } }
internal static void ParseSummary(IStringReader reader, ChangeSetDetail detail) { while (!reader.Done) { string line = reader.ReadLine(); if (line.Contains('|')) { string[] parts = line.Split('|'); string path = parts[0].Trim(); // TODO: Figure out a way to get this information detail.Files[path] = new FileInfo(); } else { // n files changed, n insertions(+), n deletions(-) ParserHelpers.ParseSummaryFooter(line, detail); } } }
internal static void PopulateStatus(IStringReader reader, ChangeSetDetail detail) { while (!reader.Done) { string line = reader.ReadLine(); // Status lines contain tabs if (!line.Contains("\t")) { continue; } var lineReader = line.AsReader(); string status = lineReader.ReadUntilWhitespace(); lineReader.SkipWhitespace(); string name = lineReader.ReadToEnd().TrimEnd(); lineReader.SkipWhitespace(); FileInfo file; if (detail.Files.TryGetValue(name, out file)) { file.Status = ConvertStatus(status); } } }
internal static IEnumerable <FileDiff> ParseDiff(IStringReader reader) { var builder = new StringBuilder(); // If this was a merge change set then we'll parse the details out of the // first diff ChangeSetDetail merge = null; do { string line = reader.ReadLine(); // If we see a new diff header then process the previous diff if any if ((reader.Done || IsDiffHeader(line)) && builder.Length > 0) { if (reader.Done) { builder.Append(line); } string diffChunk = builder.ToString(); FileDiff diff = ParseDiffChunk(diffChunk.AsReader(), ref merge); if (diff != null) { yield return(diff); } builder.Clear(); } if (!reader.Done) { builder.Append(line); } } while (!reader.Done); }
internal static ChangeSet ParseCommit(IStringReader reader) { // commit hash reader.ReadUntilWhitespace(); reader.SkipWhitespace(); string id = reader.ReadUntilWhitespace(); // Merges will have (from hash) so we're skipping that reader.ReadLine(); string author = null; string email = null; string date = null; while (!reader.Done) { string line = reader.ReadLine(); if (ParserHelpers.IsSingleNewLine(line)) { break; } var subReader = line.AsReader(); string key = subReader.ReadUntil(':'); // Skip : subReader.Skip(); subReader.SkipWhitespace(); string value = subReader.ReadToEnd().Trim(); if (key.Equals("Author", StringComparison.OrdinalIgnoreCase)) { // Author <email> var authorReader = value.AsReader(); author = authorReader.ReadUntil('<').Trim(); authorReader.Skip(); email = authorReader.ReadUntil('>'); } else if (key.Equals("Date", StringComparison.OrdinalIgnoreCase)) { date = value; } } var messageBuilder = new StringBuilder(); while (!reader.Done) { string line = reader.ReadLine(); if (ParserHelpers.IsSingleNewLine(line)) { break; } messageBuilder.Append(line); } string message = messageBuilder.ToString().Trim(); return(new ChangeSet(id, author, email, message, DateTimeOffset.ParseExact(date, "ddd MMM d HH:mm:ss yyyy zzz", CultureInfo.InvariantCulture))); }
private static FileDiff ParseDiffHeader(IStringReader reader, ChangeSetDetail merge) { string fileName = ParseFileName(reader.ReadLine()); bool binary = false; while (!reader.Done) { string line = reader.ReadLine(); if (line.StartsWith("@@", StringComparison.Ordinal)) { reader.PutBack(line.Length); break; } else if (line.StartsWith("GIT binary patch", StringComparison.Ordinal)) { binary = true; } } if (binary) { // Skip binary files reader.ReadToEnd(); } var diff = new FileDiff(fileName) { Binary = binary }; // Skip files from merged changesets if (merge != null && merge.Files.ContainsKey(fileName)) { return null; } return diff; }
internal static IEnumerable<FileStatus> ParseStatus(IStringReader reader) { reader.SkipWhitespace(); while (!reader.Done) { var subReader = reader.ReadLine().AsReader(); string status = subReader.ReadUntilWhitespace().Trim(); string path = subReader.ReadLine().Trim(); yield return new FileStatus(path, ConvertStatus(status)); reader.SkipWhitespace(); } }
internal static FileDiff ParseDiffChunk(IStringReader reader, ref ChangeSetDetail merge) { var diff = ParseDiffHeader(reader, merge); if (diff == null) { return null; } // Current diff range DiffRange currentRange = null; int? leftCounter = null; int? rightCounter = null; // Parse the file diff while (!reader.Done) { int? currentLeft = null; int? currentRight = null; string line = reader.ReadLine(); if (line.Equals(@"\ No newline at end of file", StringComparison.OrdinalIgnoreCase)) { continue; } bool isDiffRange = line.StartsWith("@@", StringComparison.Ordinal); ChangeType? changeType = null; if (line.StartsWith("+", StringComparison.Ordinal)) { changeType = ChangeType.Added; currentRight = ++rightCounter; currentLeft = null; } else if (line.StartsWith("-", StringComparison.Ordinal)) { changeType = ChangeType.Deleted; currentLeft = ++leftCounter; currentRight = null; } else if (IsCommitHeader(line)) { reader.PutBack(line.Length); merge = ParseCommitAndSummary(reader); } else { if (!isDiffRange) { currentLeft = ++leftCounter; currentRight = ++rightCounter; } changeType = ChangeType.None; } if (changeType != null) { var lineDiff = new LineDiff(changeType.Value, line); if (!isDiffRange) { lineDiff.LeftLine = currentLeft; lineDiff.RightLine = currentRight; } diff.Lines.Add(lineDiff); } if (isDiffRange) { // Parse the new diff range currentRange = DiffRange.Parse(line.AsReader()); leftCounter = currentRange.LeftFrom - 1; rightCounter = currentRange.RightFrom - 1; } } return diff; }
internal static IEnumerable<FileDiff> ParseDiff(IStringReader reader) { var builder = new StringBuilder(); // If this was a merge change set then we'll parse the details out of the // first diff ChangeSetDetail merge = null; do { string line = reader.ReadLine(); // If we see a new diff header then process the previous diff if any if ((reader.Done || IsDiffHeader(line)) && builder.Length > 0) { if (reader.Done) { builder.Append(line); } string diffChunk = builder.ToString(); FileDiff diff = ParseDiffChunk(diffChunk.AsReader(), ref merge); if (diff != null) { yield return diff; } builder.Clear(); } if (!reader.Done) { builder.Append(line); } } while (!reader.Done); }
internal static ChangeSet ParseCommit(IStringReader reader) { // commit hash reader.ReadUntilWhitespace(); reader.SkipWhitespace(); string id = reader.ReadUntilWhitespace(); // Merges will have (from hash) so we're skipping that reader.ReadLine(); string author = null; string email = null; string date = null; while (!reader.Done) { string line = reader.ReadLine(); if (ParserHelpers.IsSingleNewLine(line)) { break; } var subReader = line.AsReader(); string key = subReader.ReadUntil(':'); // Skip : subReader.Skip(); subReader.SkipWhitespace(); string value = subReader.ReadToEnd().Trim(); if (key.Equals("Author", StringComparison.OrdinalIgnoreCase)) { // Author <email> var authorReader = value.AsReader(); author = authorReader.ReadUntil('<').Trim(); authorReader.Skip(); email = authorReader.ReadUntil('>'); } else if (key.Equals("Date", StringComparison.OrdinalIgnoreCase)) { date = value; } } var messageBuilder = new StringBuilder(); while (!reader.Done) { string line = reader.ReadLine(); if (ParserHelpers.IsSingleNewLine(line)) { break; } messageBuilder.Append(line); } string message = messageBuilder.ToString(); return new ChangeSet(id, author, email, message, DateTimeOffset.ParseExact(date, "ddd MMM d HH:mm:ss yyyy zzz", CultureInfo.InvariantCulture)); }
private static int Parse(IStringReader input, object o, string startTag, string endTag, Callback onText, Callback onMarker) { if (input == null) { throw new ArgumentNullException("input"); } if (string.IsNullOrEmpty(startTag)) { throw new ArgumentNullException("startTag"); } if (string.IsNullOrEmpty(endTag)) { throw new ArgumentNullException("endTag"); } if (onText == null && onMarker == null) { throw new ArgumentNullException("onText"); } if (input.IsEmpty) { return(0); } string line; string substring; int processingStart; int startIndex; int endIndex; int result = 0; StringBuilder text = new StringBuilder(); StringBuilder content = new StringBuilder(); bool insideTag = false; bool continueProcessing; while ((line = input.ReadLine()) != null) { processingStart = 0; do { // is there any tag in current line: startIndex = insideTag ? -1 : line.IndexOf(startTag, processingStart, StringComparison.Ordinal); continueProcessing = false; if (startIndex < 0) { if (insideTag) { endIndex = line.IndexOf(endTag, processingStart, StringComparison.Ordinal); if (endIndex < 0) { // add content of the tag content.Append(processingStart > 0 ? line.Substring(processingStart) : line).Append("\r\n"); } else { // was there any text before if (text.Length > 0) { if (onText != null) { onText(o, text.ToString()); } #if NET_2_COMPATIBLE || SILVERLIGHT text.Remove(0, text.Length); #else text.Clear(); #endif } // append beginning as a tag if (content.Length > 0) { substring = content.Append(line.Substring(processingStart, endIndex - processingStart)).ToString(); #if NET_2_COMPATIBLE || SILVERLIGHT content.Remove(0, content.Length); #else content.Clear(); #endif } else { substring = line.Substring(processingStart, endIndex - processingStart); } if (onMarker != null) { onMarker(o, substring); } result++; insideTag = false; continueProcessing = true; processingStart = endIndex + endTag.Length; } } else { // add the whole line into the buffer, so we minimize the number of notifications text.Append(processingStart > 0 ? line.Substring(processingStart) : line); if (!input.IsEof) { text.Append("\r\n"); } } } else { // text before tag if (startIndex > processingStart || text.Length > 0) { if (text.Length > 0) { substring = text.Append(line.Substring(processingStart, startIndex - processingStart)).ToString(); #if NET_2_COMPATIBLE || SILVERLIGHT text.Remove(0, text.Length); #else text.Clear(); #endif } else { substring = line.Substring(processingStart, startIndex - processingStart); } if (onText != null) { onText(o, substring); } } // tag: endIndex = line.IndexOf(endTag, startIndex + startTag.Length, StringComparison.Ordinal); if (endIndex < 0) { // add rest of the line as the content of the tag content.Append(line.Substring(startIndex + startTag.Length)).Append("\r\n"); insideTag = true; } else { if (content.Length > 0) { substring = content.Append(line.Substring(startIndex + startTag.Length, endIndex - startIndex - endTag.Length)).ToString(); #if NET_2_COMPATIBLE || SILVERLIGHT content.Remove(0, content.Length); #else content.Clear(); #endif } else { substring = line.Substring(startIndex + startTag.Length, endIndex - startIndex - endTag.Length); } if (onMarker != null) { onMarker(o, substring); } result++; insideTag = false; continueProcessing = true; processingStart = endIndex + endTag.Length; } } } while (continueProcessing); } if (insideTag || content.Length > 0) { throw new FormatException(string.Concat("Unclosed tag with content: '", content, "'")); } if (onText != null && text.Length > 0) { onText(o, text.ToString()); } return(result); }
private static int Parse(IStringReader input, object o, string startTag, string endTag, Callback onText, Callback onMarker) { if (input == null) throw new ArgumentNullException("input"); if (string.IsNullOrEmpty(startTag)) throw new ArgumentNullException("startTag"); if (string.IsNullOrEmpty(endTag)) throw new ArgumentNullException("endTag"); if (onText == null && onMarker == null) throw new ArgumentNullException("onText"); if (input.IsEmpty) return 0; string line; string substring; int processingStart; int startIndex; int endIndex; int result = 0; StringBuilder text = new StringBuilder(); StringBuilder content = new StringBuilder(); bool insideTag = false; bool continueProcessing; while ((line = input.ReadLine()) != null) { processingStart = 0; do { // is there any tag in current line: startIndex = insideTag ? -1 : line.IndexOf(startTag, processingStart, StringComparison.Ordinal); continueProcessing = false; if (startIndex < 0) { if (insideTag) { endIndex = line.IndexOf(endTag, processingStart, StringComparison.Ordinal); if (endIndex < 0) { // add content of the tag content.Append(processingStart > 0 ? line.Substring(processingStart) : line).Append("\r\n"); } else { // was there any text before if (text.Length > 0) { if (onText != null) onText(o, text.ToString()); #if NET_2_COMPATIBLE || SILVERLIGHT text.Remove(0, text.Length); #else text.Clear(); #endif } // append beginning as a tag if (content.Length > 0) { substring = content.Append(line.Substring(processingStart, endIndex - processingStart)).ToString(); #if NET_2_COMPATIBLE || SILVERLIGHT content.Remove(0, content.Length); #else content.Clear(); #endif } else { substring = line.Substring(processingStart, endIndex - processingStart); } if (onMarker != null) onMarker(o, substring); result++; insideTag = false; continueProcessing = true; processingStart = endIndex + endTag.Length; } } else { // add the whole line into the buffer, so we minimize the number of notifications text.Append(processingStart > 0 ? line.Substring(processingStart) : line); if (!input.IsEof) text.Append("\r\n"); } } else { // text before tag if (startIndex > processingStart || text.Length > 0) { if (text.Length > 0) { substring = text.Append(line.Substring(processingStart, startIndex - processingStart)).ToString(); #if NET_2_COMPATIBLE || SILVERLIGHT text.Remove(0, text.Length); #else text.Clear(); #endif } else substring = line.Substring(processingStart, startIndex - processingStart); if (onText != null) onText(o, substring); } // tag: endIndex = line.IndexOf(endTag, startIndex + startTag.Length, StringComparison.Ordinal); if (endIndex < 0) { // add rest of the line as the content of the tag content.Append(line.Substring(startIndex + startTag.Length)).Append("\r\n"); insideTag = true; } else { if (content.Length > 0) { substring = content.Append(line.Substring(startIndex + startTag.Length, endIndex - startIndex - endTag.Length)).ToString(); #if NET_2_COMPATIBLE || SILVERLIGHT content.Remove(0, content.Length); #else content.Clear(); #endif } else { substring = line.Substring(startIndex + startTag.Length, endIndex - startIndex - endTag.Length); } if (onMarker != null) onMarker(o, substring); result++; insideTag = false; continueProcessing = true; processingStart = endIndex + endTag.Length; } } } while (continueProcessing); } if (insideTag || content.Length > 0) throw new FormatException(string.Concat("Unclosed tag with content: '", content, "'")); if (onText != null && text.Length > 0) onText(o, text.ToString()); return result; }
internal static FileDiff ParseDiffChunk(IStringReader reader, ref ChangeSetDetail merge) { var diff = ParseDiffHeader(reader, merge); if (diff == null) { return(null); } // Current diff range DiffRange currentRange = null; int? leftCounter = null; int? rightCounter = null; // Parse the file diff while (!reader.Done) { int? currentLeft = null; int? currentRight = null; string line = reader.ReadLine(); if (line.Equals(@"\ No newline at end of file", StringComparison.OrdinalIgnoreCase)) { continue; } bool isDiffRange = line.StartsWith("@@", StringComparison.Ordinal); ChangeType?changeType = null; if (line.StartsWith("+", StringComparison.Ordinal)) { changeType = ChangeType.Added; currentRight = ++rightCounter; currentLeft = null; } else if (line.StartsWith("-", StringComparison.Ordinal)) { changeType = ChangeType.Deleted; currentLeft = ++leftCounter; currentRight = null; } else if (IsCommitHeader(line)) { reader.PutBack(line.Length); merge = ParseCommitAndSummary(reader); } else { if (!isDiffRange) { currentLeft = ++leftCounter; currentRight = ++rightCounter; } changeType = ChangeType.None; } if (changeType != null) { var lineDiff = new LineDiff(changeType.Value, line); if (!isDiffRange) { lineDiff.LeftLine = currentLeft; lineDiff.RightLine = currentRight; } diff.Lines.Add(lineDiff); } if (isDiffRange) { // Parse the new diff range currentRange = DiffRange.Parse(line.AsReader()); leftCounter = currentRange.LeftFrom - 1; rightCounter = currentRange.RightFrom - 1; } } return(diff); }