コード例 #1
0
 private void Chunk(string line, Match match)
 {
     in_del   = oldStart = int.Parse(match.Groups[1].Value);
     oldLines = match.Groups[2].Success ? int.Parse(match.Groups[2].Value) : 0;
     in_add   = newStart = int.Parse(match.Groups[3].Value);
     newLines = match.Groups[4].Success ? int.Parse(match.Groups[4].Value) : 0;
     current  = new ChunkDiff(
         content: line,
         oldStart: oldStart,
         oldLines: oldLines,
         newStart: newStart,
         newLines: newLines
         );
     file.Chunks.Add(current);
 }
コード例 #2
0
        public static IEnumerable <FileDiff> Parse(string input, string lineEnding = "\n")
        {
            if (string.IsNullOrWhiteSpace(input))
            {
                return(Enumerable.Empty <FileDiff>());
            }

            var lines = input.Split(new[] { lineEnding }, StringSplitOptions.None);

            if (lines.Length == 0)
            {
                return(Enumerable.Empty <FileDiff>());
            }

            var files  = new List <FileDiff>();
            var in_del = 0;
            var in_add = 0;

            ChunkDiff current = null;
            FileDiff  file    = null;

            int oldStart, newStart;
            int oldLines, newLines;

            ParserAction start = (line, m) =>
            {
                file = new FileDiff();
                files.Add(file);

                if (file.To == null && file.From == null)
                {
                    var fileNames = parseFile(line);

                    if (fileNames != null)
                    {
                        file.From = fileNames[0];
                        file.To   = fileNames[1];
                    }
                }
            };

            ParserAction restart = (line, m) =>
            {
                if (file == null || file.Chunks.Count != 0)
                {
                    start(null, null);
                }
            };

            ParserAction new_file = (line, m) =>
            {
                restart(null, null);
                file.Type = FileChangeType.Add;
                file.From = "/dev/null";
            };

            ParserAction deleted_file = (line, m) =>
            {
                restart(null, null);
                file.Type = FileChangeType.Delete;
                file.To   = "/dev/null";
            };

            ParserAction index = (line, m) =>
            {
                restart(null, null);
                file.Index = line.Split(' ').Skip(1);
            };

            ParserAction from_file = (line, m) =>
            {
                restart(null, null);
                file.From = parseFileFallback(line);
            };

            ParserAction to_file = (line, m) =>
            {
                restart(null, null);
                file.To = parseFileFallback(line);
            };

            ParserAction chunk = (line, match) =>
            {
                in_del   = oldStart = int.Parse(match.Groups[1].Value);
                oldLines = match.Groups[2].Success ? int.Parse(match.Groups[2].Value) : 0;
                in_add   = newStart = int.Parse(match.Groups[3].Value);
                newLines = match.Groups[4].Success ? int.Parse(match.Groups[4].Value) : 0;
                current  = new ChunkDiff(
                    content: line,
                    oldStart: oldStart,
                    oldLines: oldLines,
                    newStart: newStart,
                    newLines: newLines
                    );
                file.Chunks.Add(current);
            };

            ParserAction del = (line, match) =>
            {
                current.Changes.Add(new LineDiff(type: LineChangeType.Delete, index: in_del++, content: line));
                file.Deletions++;
            };

            ParserAction add = (line, m) =>
            {
                current.Changes.Add(new LineDiff(type: LineChangeType.Add, index: in_add++, content: line));
                file.Additions++;
            };

            const string noeol = "\\ No newline at end of file";

            Action <string> normal = line =>
            {
                if (file == null)
                {
                    return;
                }

                current.Changes.Add(new LineDiff(
                                        oldIndex: line == noeol ? 0 : in_del++,
                                        newIndex: line == noeol ? 0 : in_add++,
                                        content: line));
            };

            var schema = new Dictionary <Regex, ParserAction>
            {
                { new Regex(@"^diff\s"), start },
                { new Regex(@"^new file mode \d+$"), new_file },
                { new Regex(@"^deleted file mode \d+$"), deleted_file },
                { new Regex(@"^index\s[\da-zA-Z]+\.\.[\da-zA-Z]+(\s(\d+))?$"), index },
                { new Regex(@"^---\s"), from_file },
                { new Regex(@"^\+\+\+\s"), to_file },
                { new Regex(@"^@@\s+\-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@"), chunk },
                { new Regex(@"^-"), del },
                { new Regex(@"^\+"), add }
            };

            Func <string, bool> parse = line =>
            {
                foreach (var p in schema)
                {
                    var m = p.Key.Match(line);
                    if (m.Success)
                    {
                        p.Value(line, m);
                        return(true);
                    }
                }

                return(false);
            };

            foreach (var line in lines)
            {
                if (!parse(line))
                {
                    normal(line);
                }
            }

            return(files);
        }
コード例 #3
0
ファイル: FileDiff.cs プロジェクト: jkingry/ParseDiff
        public static IEnumerable<FileDiff> Parse(string input, string lineEnding = "\n")
        {
            if (string.IsNullOrWhiteSpace(input)) return Enumerable.Empty<FileDiff>();

            var lines = input.Split(new[] { lineEnding }, StringSplitOptions.None);

            if (lines.Length == 0) return Enumerable.Empty<FileDiff>();

            var files = new List<FileDiff>();
            var in_del = 0;
            var in_add = 0;

            ChunkDiff current = null;
            FileDiff file = null;

            int oldStart, newStart;
            int oldLines, newLines;

            ParserAction start = (line, m) => {
                file = new FileDiff();
                files.Add(file);

                if (file.To == null && file.From == null)
                {
                    var fileNames = parseFile(line);

                    if (fileNames != null)
                    {
                        file.From = fileNames[0];
                        file.To = fileNames[1];
                    }
                }
            };

            ParserAction restart = (line, m) => {
                if (file == null || file.Chunks.Count != 0)
                    start(null, null);
            };

            ParserAction new_file = (line, m) => {
                restart(null, null);
                file.Type = FileChangeType.Add;
                file.From = "/dev/null";
            };

            ParserAction deleted_file = (line, m) => {
                restart(null, null);
                file.Type = FileChangeType.Delete;
                file.To = "/dev/null";
            };

            ParserAction index = (line, m) => {
                restart(null, null);
                file.Index = line.Split(' ').Skip(1);
            };

            ParserAction from_file = (line, m) => {
                restart(null, null);
                file.From = parseFileFallback(line);
            };

            ParserAction to_file = (line, m) => {
                restart(null, null);
                file.To = parseFileFallback(line);
            };

            ParserAction chunk = (line, match) => {
                in_del = oldStart = int.Parse(match.Groups[1].Value);
                oldLines = match.Groups[2].Success ? int.Parse(match.Groups[2].Value) : 0;
                in_add = newStart = int.Parse(match.Groups[3].Value);
                newLines = match.Groups[4].Success ? int.Parse(match.Groups[4].Value) : 0;
                current = new ChunkDiff(
                    content: line,
                    oldStart: oldStart,
                    oldLines: oldLines,
                    newStart: newStart,
                    newLines: newLines
                );
                file.Chunks.Add(current);
            };

            ParserAction del = (line, match) => {
                current.Changes.Add(new LineDiff(type: LineChangeType.Delete, index: in_del++, content: line));
                file.Deletions++;
            };

            ParserAction add = (line, m) => {
                current.Changes.Add(new LineDiff(type: LineChangeType.Add, index: in_add++, content: line));
                file.Additions++;
            };

            const string noeol = "\\ No newline at end of file";

            Action<string> normal = line => {
                if (file == null) return;

                current.Changes.Add(new LineDiff(
                    oldIndex: line == noeol ? 0 : in_del++,
                    newIndex: line == noeol ? 0 : in_add++,
                    content: line));
            };

            var schema = new Dictionary<Regex, ParserAction>
            {
                    { new Regex(@"^diff\s"), start },
                    { new Regex(@"^new file mode \d+$"), new_file },
                    { new Regex(@"^deleted file mode \d+$"), deleted_file },
                    { new Regex(@"^index\s[\da-zA-Z]+\.\.[\da-zA-Z]+(\s(\d+))?$"), index },
                    { new Regex(@"^---\s"), from_file },
                    { new Regex(@"^\+\+\+\s"), to_file },
                    { new Regex(@"^@@\s+\-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@"), chunk },
                    { new Regex(@"^-"), del },
                    { new Regex(@"^\+"), add }
            };

            Func<string, bool> parse = line => {
                foreach (var p in schema)
                {
                    var m = p.Key.Match(line);
                    if (m.Success)
                    {
                        p.Value(line, m);
                        return true;
                    }
                }

                return false;
            };

            foreach (var line in lines)
                if (!parse(line))
                    normal(line);

            return files;
        }