Skip to content

Instantly share code, notes, and snippets.

@303248153
Created April 27, 2018 02:31
Show Gist options
  • Save 303248153/0e3945d4ce50d6162a717d80418c232f to your computer and use it in GitHub Desktop.
Save 303248153/0e3945d4ce50d6162a717d80418c232f to your computer and use it in GitHub Desktop.
Find function author and last changed date from git blame
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace ConsoleApp1
{
public class Program
{
[ProvideSourceLocation]
public static void A()
{
int a = 0;
a += 1;
}
public static void Main(string[] args)
{
var methodInfo = typeof(Program).GetMethod("A");
var sourceLocation = methodInfo.GetCustomAttributes().OfType<ProvideSourceLocation>().First();
var processInfo = new ProcessStartInfo();
processInfo.WorkingDirectory = Path.GetDirectoryName(sourceLocation.File);
processInfo.FileName = "git.exe";
processInfo.Arguments = $"blame \"{Path.GetFileName(sourceLocation.File)}\"";
processInfo.UseShellExecute = false;
processInfo.LoadUserProfile = false;
processInfo.RedirectStandardInput = true;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
var process = Process.Start(processInfo);
process.StandardInput.Flush();
process.StandardInput.Close();
var blameResult = "";
while (!process.StandardOutput.EndOfStream)
{
var chunk = process.StandardOutput.ReadToEnd();
blameResult += chunk;
}
process.WaitForExit();
var sourceInfos = blameResult
.Split('\n')
.Select(x => x.Trim())
.Where(x => x != "")
.Select(x => new SourceInfo(x))
.ToList();
var sourceIndex = sourceInfos.FindIndex(x => x.LineNumber == sourceLocation.Line);
var functionBegin = sourceIndex;
var functionEnd = 0;
var braceLevel = 0;
while (true)
{
++sourceIndex;
var sourceLine = sourceInfos[sourceIndex].SourceLine.Trim();
if (sourceLine == "{")
{
++braceLevel;
}
else if (sourceLine == "}")
{
--braceLevel;
if (braceLevel == 0)
{
functionEnd = sourceIndex;
break;
}
}
}
var functionInfos = sourceInfos.Skip(functionBegin).Take(functionEnd - functionBegin + 1).ToList();
foreach (var functionInfo in functionInfos)
{
Console.WriteLine(functionInfo);
}
Console.WriteLine();
Console.WriteLine("last change:");
var lastChange = functionInfos
.Where(x => x.Author != "Not Committed Yet")
.OrderByDescending(x => x.Date)
.FirstOrDefault();
Console.WriteLine(lastChange?.Date);
Console.WriteLine(lastChange?.Author);
}
}
public class SourceInfo
{
public string Author { get; set; }
public int LineNumber { get; set; }
public DateTime Date { get; set; }
public string SourceLine { get; set; }
public SourceInfo(string line)
{
var braceBegin = line.IndexOf('(');
var braceEnd = line.IndexOf(')');
var braceText = line.Substring(braceBegin + 1, braceEnd - braceBegin - 1);
var columns = braceText.Split(' ', StringSplitOptions.RemoveEmptyEntries);
Author = string.Join(" ", columns.Take(columns.Length - 4));
LineNumber = int.Parse(columns.Last());
Date = DateTime.Parse(string.Join(" ", columns.Skip(columns.Length - 4).Take(3)));
SourceLine = line.Substring(braceEnd + 1);
}
public override string ToString()
{
return $"{Author} {LineNumber} {Date}: {SourceLine}";
}
}
/// <summary>
/// https://stackoverflow.com/questions/126094/how-to-get-the-source-file-name-and-the-line-number-of-a-type-member
/// </summary>
public class ProvideSourceLocation : Attribute
{
public readonly string File;
public readonly string Member;
public readonly int Line;
public ProvideSourceLocation(
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0)
{
File = file;
Member = member;
Line = line;
}
public override string ToString() { return File + "(" + Line + "):" + Member; }
}
}
@303248153
Copy link
Author

output:

aaa 12 2018/4/27 9:40:30:          [ProvideSourceLocation]
aaa 13 2018/4/27 9:40:30:          public static void A()
aaa 14 2018/4/27 9:40:30:          {
Not Committed Yet 15 2018/4/27 10:31:53:              int a = 0;
Not Committed Yet 16 2018/4/27 10:31:53:              a += 1;
aaa 17 2018/4/27 9:40:30:          }

last change:
2018/4/27 9:40:30
aaa

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment