2016-03-30 34 views
6

Potrzebuję programowo uzyskać ostatniego autora określonej linii w historii Git z C#. Próbowałem za pomocą libgit2sharp:Programowo zrobić "Git winy-w" w C#

var repo = new LibGit2Sharp.Repository(gitRepositoryPath); 
string relativePath = MakeRelativeSimple(filename); 
var blameHunks = repo.Blame(relativePath); 
// next : find the hunk which overlap the desired line number 

Ale to odpowiednik polecenia

git blame <file>

I faktycznie muszę

git blame -w <file> (ignorować spacje przy porównywaniu)

Libgit2sharp nie ustawiaj przełącznika -w i nie udostępniaj żadnego parametru/opcji do ustawienia. Jakie są moje opcje? Czy znasz inną bibliotekę kompatybilną z przełącznikiem -w polecenia blame?

+0

Wystarczy, że wyjaśnisz, że próbowałeś NGit? –

+0

@Jeremy: wcale nie, nie znałem NGit. Spędziłem tak dużo czasu na tym pytaniu, które wolałem prosić o opinie. – JYL

+0

Fajnie, jest to naprawdę dobra propozycja funkcji dla zespołu deweloperów LibGit2Sharp :) Jeśli poprosisz ich uprzejmie o link do tego Q, możesz zachęcić jednego z głównych członków zespołu lub współtwórcę do dodania go, podczas gdy ten Q ma aktywną nagrodę w załączeniu ... W przeciwnym razie Evk powinien to zrobić (+1). Przekreślone palce wystarczą, aby przekonać, ponieważ wtedy nie musiałbyś polegać na 2 bibliotekach. –

Odpowiedz

2

Kiedy uderzam w podobne zaawansowane scenariusze, w których git lib go nie tnie, po prostu wypalam używając procesu startowego do prawdziwej linii poleceń git. To nie jest seksowne, ale jest bardzo skuteczne.

+0

Chociaż o tym wcześniej, ale muszę to zrobić dla około 2000 plików w moim rozwiązaniu i obawiać się wydajności. Spróbuję tego w ostateczności. – JYL

+0

Tak naprawdę jest to szybsze niż użycie libGit2Sharp w moim przypadku. Z repozytorium testowym zawierającym 818 plików (4570 zatwierdzeń), z winą na każdy plik: za pomocą procesu bezpośredniego: średnio 181 ms. za winę; za pomocą ligGit2Sharp: średnio 1235 ms na winę. – JYL

2

Może przy pomocy biblioteki NGIT pomoże. To jest bezpośredni (automatyczny) port biblioteki java JGIT. Instalacja za pomocą pakietu Nuget, a następnie:

static void Main() { 
     var git = Git.Init().SetDirectory("C:\\MyGitRepo").Call();    
     string relativePath = "MyFolder/MyFile.cs";    
     var blameHunks = git.Blame().SetFilePath(relativePath).SetTextComparator(RawTextComparator.WS_IGNORE_ALL).Call(); 
     blameHunks.ComputeAll(); 
     var firstLineCommit = blameHunks.GetSourceCommit(0); 
     // next : find the hunk which overlap the desired line number 
     Console.ReadKey(); 
    } 

Uwaga SetTextComparator (RawTextComparator.WS_IGNORE_ALL) części.

+0

Dzięki za odpowiedź, wypróbuję to w przyszłym tygodniu. – JYL

+0

Nie można tego zrobić. Niektóre poprawki są ładne, a niektóre inne są po prostu zerowe. Zwłaszcza, gdy istnieją różnice w odstępach. Nie wiem, czy mam złą lub brakującą opcję, czy też jest to spowodowane nieaktualnymi źródłami ngit (w porównaniu do jgit). Poddaję się, wracam do podstaw (rozwiązanie robricka). – JYL

+0

Niemniej jednak daję ci nagrodę, ponieważ odpowiedź jest teoretycznie poprawna i jest podawana z odpowiednią próbką kodu. Dzięki. – JYL

0

Niestety, libgit2sharp jest zbyt wolny przy wydobywaniu win, a używanie tej funkcji jest niepraktyczne w rzeczywistych sytuacjach. Najlepszym sposobem jest użycie skryptu Powershell, który użyje bazowego super-rodzimego gita. Następnie przekieruj wynik do aplikacji.

git blame -l -e -c {commit-sha} -- "{file-path}" | where { $_ -match '(?<sha>\w{40})\s+\(<(?<email>[\w\.\-][email protected][\w\-]+\.\w{2,3})>\s+(?<datetime>\d\d\d\d-\d\d-\d\d\s\d\d\:\d\d:\d\d\s-\d\d\d\d)\s+(?<lineNumber>\d+)\)\w*' } | 
foreach { new-object PSObject –prop @{ Email = $matches['email'];lineNumber = $matches['lineNumber'];dateTime = $matches['dateTime'];Sha = $matches['sha']}}