Git'te treyler seçeneği - güzel seçeneği
Git log'dan katkıların bir özetini çıkarmaya ve bunun kısa bir özetini oluşturmaya ve raporları sunmak için ondan bir excel / csv oluşturmaya çalışıyordum.
Denedim
git log --after="2020-12-10" --pretty=format:'"%h","%an","%ae","%aD","%s","(trailers:key="Reviewed By")"'
ve CSV, sonunda boş bir CSV sütunu gibi görünür.
...
"7c87963cc","XYZ","[email protected]","Tue Dec 8 17:40:13 2020 +0000","[TTI] Add support for target hook in compiler.", ""
...
ve bir git log
şeye benziyor
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
Başarılı olamadığım şey Differential Revision
, (trailers:key="Reviewed By")
komutu kullanarak dizeyi ayıklamaktı .
Bunu nasıl çalıştıracağım konusunda pek bir şey bulamadım. Git kılavuzunu kontrol ettim ve açıkladığını denedim.
Bu komutta eksik olabileceğim bir şey var mı? Beklenen çıktı https://codereviews.com/DD8822
, yukarıdaki CVS çıktısının son konumunda metne sahip olmalıdır .
Yanıtlar
Emin değilim ama:
- römork anahtarlarının boşlukları olamaz (bu nedenle
Reviewed By
->Reviewed-By
veDifferential Revision
->Differential-Revision
); - fragmanlar yeni satırlarla sınırlandırılmamalı, ancak commit commit mesajından ayrılmalıdır (bu nedenle
Reviewed By
sorunuzdan fragman olarak kabul edilmez).
CSV kullanılmasını da önermem, bunun yerine TSV kullanılmasını tavsiye ederim: git output, CSV sözdiziminin farkında değil (noktalı virgül ve virgül kaçış), bu nedenle çıktı belgesi ayrıştırılamaz şekilde oluşturulabilir.
Kaydetme mesajlarınız şöyle görünüyorsa ( -
boşluk yerine, yeni satır sınırlayıcı yok):
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
O zaman aşağıdaki komut sizin için çalışacaktır:
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)'
sekmeyle ayrılmış değerler çıktınıza kısa kaydetme kimliği, yazar adı, yazar e-postası, tarih, yürütme mesajı, fragman Reviewed-By
ve fragman üretme Differential-Revision
.
Eğer tarih (o, yaşıtları tarafından çekilen, Yayınlandıktan araçlarınız işlemek yayınlanan sağlamalarının bağlıdırlar) bu iş için güvenli olmadığı için eski mesajları işlemek değiştiremez, o zaman işlemek zorunda git log
çıkışı ile sed
, awk
, perl
herhangi bir ya da Raporunuzu oluşturmak için başka bir metin dönüştürme aracı. Diyelim ki, (STX) ve EOF git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B'
arasındaki satırların bir ^B
şekilde analiz edilmesi (ilgilendiğiniz fragmanlar için filtrelenmesi), ardından ile başlayan grup satırlarına katılması ^B
ve ardından alan ve giriş ayırıcılarını değiştirmek için karakter değiştirmesi \t
ve hayır sırasıyla karakter.
Ancak yine de, kaydetme mesajı fragmanlarını düzelterek geçmişi düzenleyebilirseniz (bunun ne kadar etkileyebileceğinden emin değilseniz), bunu yapmanızı ve ardından, fragmanları işleyen ekstra komut dosyaları fikrini reddetmenizi git-interpret-trailers
ve basitçe düzeltmenizi öneririm . mesajları işlemek.
Düzenleme 1 (metin araçları)
Geçmişi yeniden yazmak bir seçenek değilse, bazı komut dosyalarını uygulamak size yardımcı olabilir. Güçlü sed
/ awk
/ perl
senaryolar yazmada oldukça zayıfım , ama deneyeyim.
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'
Nasıl çalışır:
git
Kaydetme mesajlarınızda (STX, RS ve US) böyle bir karakter olmadığını varsayarak standart C0 C1 kodlarıyla sınırlandırılmış verilerden oluşan bir günlük oluşturur (STX, RS ve US - bunları böyle kullanmak için iyi bir yer olup olmadığını ve bunları uygularsam gerçekten bilmiyorum anlamsal olarak doğru);gawk
STX ile başlatılan grupları ayrıştırmaya ve römorkları çıkarmaya çalışırken günlük çıktısını filtreler, "iki sıralı" çıktı (normal veriler için her tek satır, eksik römorklar için bile virgülle birleştirilmiş römork değerleri için her çift satır);sed
çiftler halinde tek ve çift satırları birleştirir (krediler Karoly Horvath'a gider );sed
STX ve RS'yi kaldırır;sed
US'nin yerini TAB ile değiştirir.
İşte trailers.awk
(yine bir awk
erkek değilim ve aşağıdaki komut dosyasının ne kadar deyimsel olduğu hakkında hiçbir fikrim yok, ama işe yarıyor gibi görünüyor):
#!/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()
}
awk
Senaryonun nasıl çalıştığı birkaç kelime :
- işlem gerektirmeyen kayıtların STX ile başladığını varsayar;
grep
birKey Name: Value
model için "STX" olmayan her satıra çalışır ve bulunan sonucu her kayıt için geçici bir diziyeTRAILERS
(Java'da olduğu gibi aslında bir çoklu harita olarak hizmet ederMap<String, List<String>>
) kaydeder;- her kayıt olduğu gibi yazılır, ancak fragmanlar ya yeni bir kayıt tespit edilmeden önce ya da EOF'de yazılır.
Edit 2 (daha iyi awk
)
Şey, gerçekten zayıfım awk
, bu yüzden awk
dahili değişkenler hakkında daha fazla okuduğumda , awk
betiğin tamamen yeniden uygulanabileceğini ve sed
veya ile herhangi bir son işlem yapmadan TSV benzeri bir çıktı üretebileceğini anladım perl
. Yani betiğin daha kısa ve geliştirilmiş versiyonu şu şekildedir:
#!/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: ")
}
Çok daha kısa, okunması, anlaşılması ve bakımı daha kolay.