我們計算增量代碼覆寫率的基礎,就是要找出兩個版本代碼的差異,在Git環境下,我們可以很友善的通過Git腳本來擷取這些資料。
Git擷取diff資訊
git diff指令可以使用如下格式,用來對比不同commit(或分支)間的增量代碼:
git diff [<options>] <commit> <commit>
複制
其中commit可以是分支名,也可以是commit的id,對比分支間的差異,可以簡寫為 git diff targetBranchName,表示對比目前分支與目标分支間的代碼差異。
下面這張圖,就是通過git diff指令擷取的一段更新diff資訊,如下所示。
git diff HEAD~1 HEAD
複制
輸出如下:
image-20210621155525706
diff指令,一定會有兩個輸入,即A和B,圖中第一行,就标記了A和B檔案。
對于版本A,它的符号是一個減号(「-」);而對于版本B ,它會使用一個加号(「+」)。
圖中的第三四行,就是被标記的兩個檔案,針對這個标記,存在下面幾種情況。
- diff檔案是新增檔案,則---後面是/dev/null
- diff檔案被删除,則+++後面是/dev/null
- diff發生修改,則---和+++後面都有檔案名
通過這個,就可以區分檔案狀态。
Chunk Header
git diff的每個修改,都會生成一個Chunk Header,對應圖中的「@@」和「@@」符号之間。
@@ -31,21 +31,25 @@
複制
這裡表示,從A版本的第31行開始,變更了21行,B版本從31行開始,變更了25行。
但是,我隻是加了4行log啊,這是什麼鬼??
其實git diff指令不僅僅會給出變更行,而且還會帶上前後預設3行的修改資訊,作為上下文,是以才會有這麼多的修改。
是以,我們需要再利用git的一個指令:
--unified=<n>,簡寫為-U<n>
複制
來指定上下文關聯的代碼行數,這裡設定為-U0,表示隻關心實際的變更。
加上這個參數後,輸出如下:
image-20210625145214250
加了這個參數後,Chunk Header同樣會有三種情況:
- -/+号後面隻有一個數字,設為N,那麼表示增加(+)、删除(-)了1行,行号為N,例如+34,就是第34行,增加了1行。
- -/+号後面有兩個數字,第1個數字設為N,且第二個數字為0,那麼表示第N行沒有變化,增加(+)、删除(-)了0行,這有啥意義呢?其實這就表示該内容是新增的。
- -/+号後面有兩個數字,第1個數字設為N,第二個數字為M,那麼表示從N行開始,增加(+)、删除(-)了M行,這用于标記多行的修改。
那麼有了這樣一個認知後,就可以通過正則來檢出這些資料。
git diff HEAD~1 HEAD -U0 | ggrep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)'
複制
借助這樣一個正規表達式和grep,就可以從diff資訊中找出修改的檔案和行号,執行如下:
app/src/main/java/com/yw/qdcoverage/MainActivity.kt
34
40
46
52
複制
這裡要注意,Mac下grep是用的2.5.1-FreeBSD版本,是以不支援 -P指令,需要安裝GNU Grep,通過brew install grep來安裝即可,安裝好之後,通過ggrep來調用GNU Grep(如果是Linux的話,那麼可以直接使用grep)。
如果在腳本中,可以借助正規表達式來擷取。
Pattern.compile("^@@ -(\\d+),?(\\d+)? \\+(\\d+),?(\\d+)? @@.*");
複制
這樣通過下面的代碼就可以擷取新檔案的修改行:
matcher.group(3)
matcher.group(4)
複制
以上就是我們擷取增量資訊的基礎,借助git的這些指令,我們就為後續JaCoco探針的插入,提供了Diff的資訊,進而可以實作增量探針機制。
向大家推薦下我的網站 https://xuyisheng.top/ 點選原文一鍵直達
專注 Android-Kotlin-Flutter 歡迎大家通路