Opcja zwiastunów w opcji git --pretty
Próbowałem wyodrębnić podsumowanie wkładów z dziennika git i stworzyć zwięzłe podsumowanie tego i utworzyć z niego plik excel / csv do prezentowania raportów.
Próbowałem
git log --after="2020-12-10" --pretty=format:'"%h","%an","%ae","%aD","%s","(trailers:key="Reviewed By")"'
a CSV wygląda jak z pustą kolumną CSV na końcu.
...
"7c87963cc","XYZ","[email protected]","Tue Dec 8 17:40:13 2020 +0000","[TTI] Add support for target hook in compiler.", ""
...
i git log
wygląda jakoś
commit 7c87963cc
Author: XYZ <[email protected]>
Date: Tue Dec 8 17:40:13 2020 +0000
[TTI] Add support for target hook in compiler.
This adds some code in the TabeleGen ...
This is my body of commit.
Reviewed By: Sushant
Differential Revision: https://codereviews.com/DD8822
Nie udało mi się wyodrębnić Differential Revision
ciągu za pomocą (trailers:key="Reviewed By")
polecenia.
Nie mogłem znaleźć wiele na temat tego, jak to działa. Sprawdziłem podręcznik gita i spróbowałem tego, co wyjaśnia.
Czy jest coś, czego może mi brakować w tym poleceniu? Oczekiwany wynik powinien mieć tekst https://codereviews.com/DD8822
na ostatniej pozycji w powyższym wyjściu CVS.
Odpowiedzi
Nie jestem pewien, ale:
- Klucze przyczepy nie mogą mieć białych znaków (w związku z tym
Reviewed By
->Reviewed-By
iDifferential Revision
->Differential-Revision
); - zwiastuny nie powinny być oddzielane nowymi wierszami, ale oddzielone od komunikatu o zatwierdzeniu (dlatego
Reviewed By
z twojego pytania nie jest uważany za zwiastun).
Nie polecałbym również używania CSV, ale zamiast tego używam TSV: wyjście git nie jest świadome składni CSV (średniki i przecinki ze znakami ucieczki), dlatego dokument wyjściowy może być generowany jako niemożliwy do przeanalizowania.
Jeśli twoje komunikaty o zmianach wyglądałyby tak ( -
zamiast spacji, bez nowych ograniczników linii):
commit 7c87963cc
Author: XYZ <[email protected]>
Date: Tue Dec 8 17:40:13 2020 +0000
[TTI] Add support for target hook in compiler.
This adds some code in the TabeleGen ...
This is my body of commit.
Reviewed-By: Sushant
Differential-Revision: https://codereviews.com/DD8822
Wtedy zadziała dla ciebie następujące polecenie:
git log --pretty=format:'%h%x09%an%x09%ae%x09%aD%x09%s%x09%(trailers:key=Reviewed-By,separator=%x20,valueonly)%x09%(trailers:key=Differential-Revision,separator=%x20,valueonly)'
tworzenie identyfikatora krótkiego zatwierdzenia, nazwiska autora, adresu e-mail autora, daty, komunikatu dotyczącego zmiany, zwiastuna Reviewed-By
i zwiastuna Differential-Revision
do danych wyjściowych wartości rozdzielonych tabulatorami.
Jeśli nie mogą zmienić stary popełnić wiadomości, gdyż historia nie jest bezpieczne dla tej operacji (nie jest to opublikowane, ciągnięty przez rówieśników, Twoje narzędzia są związane z opublikowanymi popełnić skrótów), potem trzeba przetworzyć git log
wyjście z sed
, awk
, perl
, lub dowolny inne narzędzie do przekształcania tekstu w celu wygenerowania raportu. Powiedzmy, przetwórz coś takiego, jak git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B'
gdzie linie między ^B
(STX) a EOF powinny być w jakiś sposób przeanalizowane (przefiltrowane pod kątem zwiastunów, które Cię interesują), a następnie dołączone do ich linii grupowych zaczynających się od ^B
, a następnie zastąpione znakami, aby zastąpić separatory pól i wpisów z \t
i nie znak odpowiednio.
Ale znowu, jeśli możesz edytować historię, naprawiając zwiastuny komunikatów o zmianach (nie jesteś pewien, jak bardzo może to wpłynąć), radziłbym to zrobić, a następnie odrzucić pomysł dodatkowych skryptów przetwarzających zwiastuny, które nie są rozpoznawane przez git-interpret-trailers
i po prostu naprawić komunikaty o zmianach.
Edytuj 1 (narzędzia tekstowe)
Jeśli przepisywanie historii nie wchodzi w grę, może pomóc zaimplementowanie niektórych skryptów. Jestem dość słaby w pisaniu potężnych sed
/ awk
/ perl
skryptów, ale pozwól mi spróbować.
git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B' \
| gawk -f trailers.awk \
| sed '$!N;s/\n/\x1F/' \
| sed 's/[\x02\x1E]//g' \
| sed 's/\x1F/\x09/g'
Jak to działa:
git
generuje log złożony z danych rozdzielonych standardowymi kodami C0 C1 przy założeniu, że nie ma takich znaków w twoich komunikatach o zmianach (STX, RS i US - nie wiem, czy to dobre miejsce, aby ich tak używać i czy je zastosuję semantycznie poprawne);gawk
filtruje dane wyjściowe dziennika próbując przeanalizować grupy uruchomione przez STX i wyodrębnić zwiastuny, generując „dwuwierszowe” wyjście (każda nieparzysta linia dla zwykłych danych, każda parzysta linia dla wartości końcowych połączonych przecinkami, nawet dla brakujących zwiastunów);sed
łączy parami linie nieparzyste i parzyste (kredyty należą do Karoly Horvath );sed
usuwa STX i RS;sed
zastępuje US na TAB.
Oto trailers.awk
(znowu nie jestem awk
facetem i nie mam pojęcia, jak idiomatyczny jest następujący skrypt, ale wydaje się, że działa):
#!/usr/bin/awk -f
BEGIN {
FIRST = 1
delete TRAILERS
}
function print_joined_array(array) {
if ( !length(array) ) {
return
}
for ( i in array ) {
if ( i > 0 ) {
printf(",")
}
printf("%s", array[i])
}
printf("\x1F")
}
function print_trailers() {
if ( FIRST ) {
FIRST = 0
return
}
print_joined_array(TRAILERS["Reviewed By"])
print_joined_array(TRAILERS["Differential Revision"])
print ""
}
/^\x02/ {
print_trailers()
print $0
delete TRAILERS
}
match($0, /^([-_ A-Za-z0-9]+):\s+(.*)\s*/, M) {
TRAILERS[M[1]][length(TRAILERS[M[1]])] = M[2]
}
END {
print_trailers()
}
Kilka słów, jak awk
działa skrypt:
- zakłada, że rekordy, które nie wymagają przetwarzania, zaczynają się od STX;
- próbuje
grep
znaleźćKey Name: Value
wzorzec w każdej linii innej niż „STX” i zapisuje znaleziony wynik w tymczasowej tablicyTRAILERS
(która służy w rzeczywistości jako multimapa, jakMap<String, List<String>>
w Javie) dla każdego rekordu; - każdy rekord jest zapisywany tak, jak jest, ale zwiastuny są zapisywane albo przed wykryciem nowego rekordu, albo podczas EOF.
Edycja 2 (lepsza awk
)
Cóż, jestem naprawdę słaby awk
, więc kiedy przeczytałem więcej o awk
zmiennych wewnętrznych, doszedłem do wniosku, że awk
skrypt można całkowicie zreimplementować i stworzyć gotowy do użycia wynik podobny do TSV bez żadnego przetwarzania końcowego za pomocą sed
lub perl
. Tak więc krótsza i ulepszona wersja skryptu to:
#!/bin/bash
git log --pretty=format:'%x1E%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%B%x1E' \
| gawk -f trailers.awk
#!/usr/bin/awk -f
BEGIN {
RS = "\x1E"
FS = "\x1F"
OFS = "\x09"
}
function extract(array, trailer_key, __buffer) {
for ( i in array ) {
if ( index(array[i], trailer_key) > 0 ) {
if ( length(__buffer) > 0 ) {
__buffer = __buffer ","
}
__buffer = __buffer substr(array[i], length(trailer_key))
}
}
return __buffer
}
NF > 1 {
split($6, array, "\n")
print $1, $2, $3, $4, $5, extract(array, "Reviewed By: "), extract(array, "Differential Revision: ")
}
O wiele bardziej zwięzłe, łatwiejsze do odczytania, zrozumienia i utrzymania.