sourcegit/src/Commands/Blame.cs

97 lines
2.8 KiB
C#
Raw Normal View History

using System;
using System.Text;
2021-04-29 05:05:55 -07:00
using System.Text.RegularExpressions;
namespace SourceGit.Commands
{
public partial class Blame : Command
{
2024-03-16 02:09:27 -07:00
[GeneratedRegex(@"^\^?([0-9a-f]+)\s+.*\((.*)\s+(\d+)\s+[\-\+]?\d+\s+\d+\) (.*)")]
private static partial Regex REG_FORMAT();
private static readonly DateTime UTC_START = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime();
public Blame(string repo, string file, string revision)
{
WorkingDirectory = repo;
Context = repo;
2021-04-29 05:05:55 -07:00
Args = $"blame -t {revision} -- \"{file}\"";
RaiseError = false;
_result.File = file;
2021-04-29 05:05:55 -07:00
}
public Models.BlameData Result()
{
var succ = Exec();
if (!succ)
{
return new Models.BlameData();
}
2023-08-23 22:39:49 -07:00
if (_needUnifyCommitSHA)
{
foreach (var line in _result.LineInfos)
{
if (line.CommitSHA.Length > _minSHALen)
{
line.CommitSHA = line.CommitSHA.Substring(0, _minSHALen);
2023-08-23 22:39:49 -07:00
}
}
}
_result.Content = _content.ToString();
return _result;
2021-04-29 05:05:55 -07:00
}
protected override void OnReadline(string line)
{
if (_result.IsBinary)
return;
if (string.IsNullOrEmpty(line))
return;
2021-04-29 05:05:55 -07:00
if (line.IndexOf('\0', StringComparison.Ordinal) >= 0)
{
_result.IsBinary = true;
_result.LineInfos.Clear();
2021-04-29 05:05:55 -07:00
return;
}
2024-03-16 02:09:27 -07:00
var match = REG_FORMAT().Match(line);
if (!match.Success)
return;
2021-04-29 05:05:55 -07:00
_content.AppendLine(match.Groups[4].Value);
var commit = match.Groups[1].Value;
var author = match.Groups[2].Value;
var timestamp = int.Parse(match.Groups[3].Value);
var when = UTC_START.AddSeconds(timestamp).ToString("yyyy/MM/dd");
2021-04-29 05:05:55 -07:00
var info = new Models.BlameLineInfo()
{
IsFirstInGroup = commit != _lastSHA,
CommitSHA = commit,
Author = author,
Time = when,
};
_result.LineInfos.Add(info);
_lastSHA = commit;
2023-08-23 22:39:49 -07:00
if (line[0] == '^')
{
_needUnifyCommitSHA = true;
_minSHALen = Math.Min(_minSHALen, commit.Length);
}
2021-04-29 05:05:55 -07:00
}
private readonly Models.BlameData _result = new Models.BlameData();
private readonly StringBuilder _content = new StringBuilder();
private string _lastSHA = string.Empty;
private bool _needUnifyCommitSHA = false;
private int _minSHALen = 64;
2021-04-29 05:05:55 -07:00
}
}