2024-02-05 23:08:37 -08:00
|
|
|
|
using System;
|
2021-07-28 00:02:06 -07:00
|
|
|
|
using System.Collections.Generic;
|
2021-04-29 05:05:55 -07:00
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
|
|
|
|
namespace SourceGit.Commands {
|
|
|
|
|
public class Diff : Command {
|
|
|
|
|
private static readonly Regex REG_INDICATOR = new Regex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
private static readonly string PREFIX_LFS = " version https://git-lfs.github.com/spec/";
|
|
|
|
|
|
|
|
|
|
public Diff(string repo, Models.DiffOption opt) {
|
|
|
|
|
WorkingDirectory = repo;
|
|
|
|
|
Context = repo;
|
|
|
|
|
Args = $"diff --ignore-cr-at-eol --unified=4 {opt}";
|
2021-04-29 05:05:55 -07:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
public Models.DiffResult Result() {
|
2021-04-29 05:05:55 -07:00
|
|
|
|
Exec();
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
|
|
|
|
if (_result.IsBinary || _result.IsLFS) {
|
|
|
|
|
_result.TextDiff = null;
|
|
|
|
|
} else {
|
|
|
|
|
ProcessInlineHighlights();
|
|
|
|
|
|
|
|
|
|
if (_result.TextDiff.Lines.Count == 0) {
|
|
|
|
|
_result.TextDiff = null;
|
|
|
|
|
} else {
|
|
|
|
|
_result.TextDiff.MaxLineNumber = Math.Max(_newLine, _oldLine);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _result;
|
2021-04-29 05:05:55 -07:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
protected override void OnReadline(string line) {
|
|
|
|
|
if (_result.IsBinary) return;
|
2021-04-29 05:05:55 -07:00
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
if (_result.IsLFS) {
|
|
|
|
|
var ch = line[0];
|
|
|
|
|
if (ch == '-') {
|
|
|
|
|
line = line.Substring(1);
|
|
|
|
|
if (line.StartsWith("oid sha256:")) {
|
|
|
|
|
_result.LFSDiff.Old.Oid = line.Substring(11);
|
|
|
|
|
} else if (line.StartsWith("size ")) {
|
|
|
|
|
_result.LFSDiff.Old.Size = long.Parse(line.Substring(5));
|
|
|
|
|
}
|
|
|
|
|
} else if (ch == '+') {
|
|
|
|
|
line = line.Substring(1);
|
|
|
|
|
if (line.StartsWith("oid sha256:")) {
|
|
|
|
|
_result.LFSDiff.New.Oid = line.Substring(11);
|
|
|
|
|
} else if (line.StartsWith("size ")) {
|
|
|
|
|
_result.LFSDiff.New.Size = long.Parse(line.Substring(5));
|
|
|
|
|
}
|
|
|
|
|
} else if (line.StartsWith(" size ")) {
|
|
|
|
|
_result.LFSDiff.New.Size = _result.LFSDiff.Old.Size = long.Parse(line.Substring(6));
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_result.TextDiff.Lines.Count == 0) {
|
2021-04-29 05:05:55 -07:00
|
|
|
|
var match = REG_INDICATOR.Match(line);
|
|
|
|
|
if (!match.Success) {
|
2024-02-05 23:08:37 -08:00
|
|
|
|
if (line.StartsWith("Binary", StringComparison.Ordinal)) _result.IsBinary = true;
|
2021-04-29 05:05:55 -07:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_oldLine = int.Parse(match.Groups[1].Value);
|
|
|
|
|
_newLine = int.Parse(match.Groups[2].Value);
|
2024-02-27 05:13:52 -08:00
|
|
|
|
_result.TextDiff.Lines.Add(new Models.TextDiffLine(Models.TextDiffLineType.Indicator, line, 0, 0));
|
2021-04-29 05:05:55 -07:00
|
|
|
|
} else {
|
2021-05-27 00:35:45 -07:00
|
|
|
|
if (line.Length == 0) {
|
2024-02-05 23:08:37 -08:00
|
|
|
|
ProcessInlineHighlights();
|
2024-02-27 05:13:52 -08:00
|
|
|
|
_result.TextDiff.Lines.Add(new Models.TextDiffLine(Models.TextDiffLineType.Normal, "", _oldLine, _newLine));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_oldLine++;
|
|
|
|
|
_newLine++;
|
2021-05-27 00:35:45 -07:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 05:05:55 -07:00
|
|
|
|
var ch = line[0];
|
|
|
|
|
if (ch == '-') {
|
2024-02-27 05:13:52 -08:00
|
|
|
|
_deleted.Add(new Models.TextDiffLine(Models.TextDiffLineType.Deleted, line.Substring(1), _oldLine, 0));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_oldLine++;
|
2021-04-29 05:05:55 -07:00
|
|
|
|
} else if (ch == '+') {
|
2024-02-27 05:13:52 -08:00
|
|
|
|
_added.Add(new Models.TextDiffLine(Models.TextDiffLineType.Added, line.Substring(1), 0, _newLine));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_newLine++;
|
2021-04-29 05:05:55 -07:00
|
|
|
|
} else if (ch != '\\') {
|
2024-02-05 23:08:37 -08:00
|
|
|
|
ProcessInlineHighlights();
|
2021-04-29 05:05:55 -07:00
|
|
|
|
var match = REG_INDICATOR.Match(line);
|
|
|
|
|
if (match.Success) {
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_oldLine = int.Parse(match.Groups[1].Value);
|
|
|
|
|
_newLine = int.Parse(match.Groups[2].Value);
|
2024-02-27 05:13:52 -08:00
|
|
|
|
_result.TextDiff.Lines.Add(new Models.TextDiffLine(Models.TextDiffLineType.Indicator, line, 0, 0));
|
2021-04-29 05:05:55 -07:00
|
|
|
|
} else {
|
2024-02-05 23:08:37 -08:00
|
|
|
|
if (line.StartsWith(PREFIX_LFS)) {
|
|
|
|
|
_result.IsLFS = true;
|
|
|
|
|
_result.LFSDiff = new Models.LFSDiff();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-27 05:13:52 -08:00
|
|
|
|
_result.TextDiff.Lines.Add(new Models.TextDiffLine(Models.TextDiffLineType.Normal, line.Substring(1), _oldLine, _newLine));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_oldLine++;
|
|
|
|
|
_newLine++;
|
2021-04-29 05:05:55 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-05 00:54:00 -07:00
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
private void ProcessInlineHighlights() {
|
|
|
|
|
if (_deleted.Count > 0) {
|
|
|
|
|
if (_added.Count == _deleted.Count) {
|
|
|
|
|
for (int i = _added.Count - 1; i >= 0; i--) {
|
|
|
|
|
var left = _deleted[i];
|
|
|
|
|
var right = _added[i];
|
2021-07-28 00:26:41 -07:00
|
|
|
|
|
2021-07-29 01:47:30 -07:00
|
|
|
|
if (left.Content.Length > 1024 || right.Content.Length > 1024) continue;
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var chunks = Models.TextInlineChange.Compare(left.Content, right.Content);
|
2021-07-29 05:42:44 -07:00
|
|
|
|
if (chunks.Count > 4) continue;
|
2021-07-29 01:47:30 -07:00
|
|
|
|
|
2021-07-29 05:42:44 -07:00
|
|
|
|
foreach (var chunk in chunks) {
|
|
|
|
|
if (chunk.DeletedCount > 0) {
|
2024-02-05 23:08:37 -08:00
|
|
|
|
left.Highlights.Add(new Models.TextInlineRange(chunk.DeletedStart, chunk.DeletedCount));
|
2021-07-29 01:47:30 -07:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-29 05:42:44 -07:00
|
|
|
|
if (chunk.AddedCount > 0) {
|
2024-02-05 23:08:37 -08:00
|
|
|
|
right.Highlights.Add(new Models.TextInlineRange(chunk.AddedStart, chunk.AddedCount));
|
2021-07-29 01:47:30 -07:00
|
|
|
|
}
|
2021-07-28 00:02:06 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_result.TextDiff.Lines.AddRange(_deleted);
|
|
|
|
|
_deleted.Clear();
|
2021-07-28 00:02:06 -07:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
if (_added.Count > 0) {
|
|
|
|
|
_result.TextDiff.Lines.AddRange(_added);
|
|
|
|
|
_added.Clear();
|
2021-07-28 00:02:06 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
|
|
|
|
private Models.DiffResult _result = new Models.DiffResult() { TextDiff = new Models.TextDiff() };
|
|
|
|
|
private List<Models.TextDiffLine> _deleted = new List<Models.TextDiffLine>();
|
|
|
|
|
private List<Models.TextDiffLine> _added = new List<Models.TextDiffLine>();
|
|
|
|
|
private int _oldLine = 0;
|
|
|
|
|
private int _newLine = 0;
|
2021-04-29 05:05:55 -07:00
|
|
|
|
}
|
|
|
|
|
}
|