ハイパーマッスルエンジニア

Vim、ShellScriptについてよく書く

fzfでAuthorを指定して編集ファイル一覧を出力する

優秀だなと思った人のソースは全部読みたい

自社開発や大規模なプロジェクトで開発しているとたまに「ああなんてわかりやすいコードを書くんや...」と思うことがある。
とりあえずgit blameして誰が書いたのか特定したはいいものの「もっとこの人の書いたコード見たいぞ」となった時、いい感じのコマンドがなかったので作った。

github.com

必要なもの

  • fzf
  • ag

別にagはgrepでもいいけどね。GNU版と分けるのが面倒だったのでagで書いた。

インストール

$ brew tap rasukarusan/gitblamer
$ brew install gitblamer

初めて自作スクリプトをHomebrewでインストールできるようにしてみたが、なかなか楽で良い。

動作

demo.gif

fzfでユーザーを指定するとその人が書いたソースファイル名が表示される。
ファイル名出力後にfzfに食わせて選択したらvimで開くってやってもよかったがやりすぎ感が否めないので出力するまでにした。
-l 追加した行数でXX行以上追加したファイルだけ表示というオプションもつけた。(ってかこれないとファイル出力されすぎ問題)

流れ

  1. ユーザー一覧を取得
  2. ユーザーが編集したファイルを取得

easyですね。

ユーザー一覧を取得

# ユーザー一覧取得   
authors=`git log --no-merges | ag 'Author:' | ag -o '(?<=: ).*(?= \<)' | sort -u`  

これはgitでコマンドあるのかなと思ったが、調べた限りなかった。
なのでagの正規表現でごそっと取得する形に。

git log --no-merges | ag 'Author:'で以下のような形で取得できる。

$ git log --no-merges | ag 'Author:'  
Author: Tanaka Naoto <XXXXXX@YYYYY.co.jp>  
Author: yamada taro <XXXXXX@YYYYY.co.jp>  
...  

後はag -o '(?<=: ).*(?= \<)'の「後読み/先読み」で指定して抜き取った。

$ git log --no-merges | ag 'Author:' | ag -o '(?<=: ).*(?= \<)' | sort -u  
Tanaka Naoto   
yamada taro  
...  

指定したユーザーの編集したファイルを取得

# 指定したユーザーの編集したファイルを取得  
files=`git -C ${gitDir} log --no-merges --numstat --author="${author}" | ag '[0-9]?\t'  | awk -v filter_add_line=${FILTER_ADD_LINE} -v gitTop=${gitTop} '{if($1>filter_add_line)print gitTop"/"$3}' | sort -u`   

git log --no-merges --numstat --author='Author名'で編集したファイル名が取得できる。

1つ目数字が追加行数、2つ目が削除行数を表している。

$ git log --no-merges --numstat --author='Tanaka Naoto'  
  
commit 1debf84c3dccd577a64664b599cb5d9b991c75fc (origin/tanaka_40416, tanaka_deploy_test, tanaka_40416)  
Author: Tanaka Naoto <XXXXXX@YYYYYY.co.jp>  
Date:   Tue May 8 01:08:41 2018 +0900  
  
    passとpasswordで表記揺れしていたのを修正  
  
    refs #tanaka_40416  
  
2   2   README.md  
9   10  web/lib/config/Config.php  
1   1   web/lib/session/clients/RedisClient.php  

見てわかるように[数字][タブ][ファイル名]というフォーマットなので、これをキーにファイル名を抜き出した。ここで「XX行以上追加したファイルだけ」というフィルタリングも行ってる。

ag '[0-9]?\t'  | awk -v filter_add_line=${FILTER_ADD_LINE} '{if($1>filter_add_line)print $3}  

まとめ

別にお披露目するものでもないが、せっかくだからアウトプットしておこうと思うよ。
でも最近shellに飽きてきたので、次はこういうスクリプト系を違う言語で書いてみようかな。