sourcegit/src/Commands/Blame.cs

78 lines
2.5 KiB
C#
Raw Normal View History

2021-04-29 05:05:55 -07:00
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace SourceGit.Commands {
/// <summary>
/// 逐行追溯
/// </summary>
public class Blame : Command {
private static readonly Regex REG_FORMAT = new Regex(@"^\^?([0-9a-f]+)\s+.*\((.*)\s+(\d+)\s+[\-\+]?\d+\s+\d+\) (.*)");
private static readonly DateTime UTC_START = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime();
2021-04-29 05:05:55 -07:00
private Data data = new Data();
2023-08-23 22:39:49 -07:00
private bool needUnifyCommitSHA = false;
private int minSHALen = 0;
2021-04-29 05:05:55 -07:00
public class Data {
public List<Models.BlameLine> Lines = new List<Models.BlameLine>();
public bool IsBinary = false;
}
public Blame(string repo, string file, string revision) {
Cwd = repo;
Args = $"blame -t {revision} -- \"{file}\"";
}
public Data Result() {
Exec();
2023-08-23 22:39:49 -07:00
if (needUnifyCommitSHA) {
foreach (var line in data.Lines) {
if (line.CommitSHA.Length > minSHALen) {
line.CommitSHA = line.CommitSHA.Substring(0, minSHALen);
}
}
}
2021-04-29 05:05:55 -07:00
return data;
}
public override void OnReadline(string line) {
if (data.IsBinary) return;
if (string.IsNullOrEmpty(line)) return;
if (line.IndexOf('\0') >= 0) {
data.IsBinary = true;
data.Lines.Clear();
return;
}
var match = REG_FORMAT.Match(line);
if (!match.Success) return;
var commit = match.Groups[1].Value;
var author = match.Groups[2].Value;
var timestamp = int.Parse(match.Groups[3].Value);
var content = match.Groups[4].Value;
var when = UTC_START.AddSeconds(timestamp).ToString("yyyy/MM/dd");
2021-04-29 05:05:55 -07:00
var blameLine = new Models.BlameLine() {
LineNumber = $"{data.Lines.Count + 1}",
2021-04-29 05:05:55 -07:00
CommitSHA = commit,
Author = author,
Time = when,
Content = content,
};
2023-08-23 22:39:49 -07:00
if (line[0] == '^') {
needUnifyCommitSHA = true;
if (minSHALen == 0) minSHALen = commit.Length;
else if (commit.Length < minSHALen) minSHALen = commit.Length;
}
2021-04-29 05:05:55 -07:00
data.Lines.Add(blameLine);
}
}
}