Goで怒りのコマンドラインツール作成
業務でgitを使っていると色々あって、時には.gitignore
をignoreしてリポジトリに全ファイルがpushされているなんて事態に出くわすこともあります。
諸々の事情により新しくリポジトリを作成し直すことができなかったため、気合のgit rm --cached
を繰り返そうとしたのですが。。。
(写真は別で準備したリポジトリです)
ちょっと手作業だと事故を起こしそうな数だったので、練習がてらgoでコマンド作ってみました。備忘録も兼ねてまとめていきます。
何してるの
中身はシンプルで、
- 引数で
.gitignore
へのpathを受け取る .gitignore
ファイルを1行ずつ読み込む- 1行ごとに
git rm --cached
を実行する
くらいしかしていません。
引数で.gitignore
へのpathを受け取る
pathは引数で受け取ることにしました。
flag
パッケージを使いたくなるところですが、今回のpathはrequiredのため、optionにしちゃいけないなと。素直にos.Args()
でいきます。
flag - The Go Programming Language
os - The Go Programming Language
引数の数と、ちゃんと.gitignore
を指定してるかどうかだけちゃんと見てあげています。
// validate arguments amount if len(os.Args) != 2 { log.Fatal("1 argument should be given.") } // get argument path := os.Args[1] ignorePath := filepath.Clean(path) if filepath.Base(ignorePath) != ".gitignore" { log.Fatal("arg should specify .gitignore file.") }
.gitignore
ファイルを1行ずつ読み込む
まずはファイルを開きます。defer
で閉じてあげるのを忘れずに。
f, err := os.Open(ignorePath) if err != nil { log.Fatal(err) } defer f.Close()
次に、ファイルの内容を読み込んであげます。bufio.NewScanner()
でいきましょう。
bufio - The Go Programming Language
s := bufio.NewScanner(f) for s.Scan() { ... } if s.Err() != nil { log.Fatal(s.Err()) }
1行ごとにgit rm --cached
を実行する
最後の段階です。前の章で読み取った1行分の.gitignore
を使ってコマンドを実行してあげたいのですが、そのまえにちょっと整形が必要です。
.gitignore
からコメントアウトされた行と、改行のみの行を省いてあげます。
str := strings.TrimSpace(s.Text()) if isLineValid(str) { // execute command } ... func isLineValid(line string) bool { if line == "" { return false } return !strings.HasPrefix(line, "#") }
いよいよラスト、コマンドを実行してあげます。goでの外部コマンドの実行はexec.Command()
を使用します。
exec - The Go Programming Language
err := exec.Command("git", "rm", "--cached", str).Run() if err != nil { fmt.Println(err) }
以上です。buildして実行してあげましょう。
exit status 128 exit status 128 exit status 128 exit status 128 exit status 128 exit status 128 exit status 128 exit status 128 exit status 128 exit status 128 exit status 128 REGNORE: 2 files are ignored.
大量のエラーメッセージを吐いてますが、これは既にignoreに追加済みのファイルに対してコマンドを実行した際のものです。ここのエラー処理はお好みに合わせて各位よろしくおねがいします。
おわりに
やっぱりGoはコマンド作るのめちゃくちゃ簡単ですね。。。最後のバイナリ生成の部分、サラッと流してますけど素晴らしいです。
今回はかなりやっつけで書いてますが、もうちょっと公開するに向けてREADME
やhelpオプションなどと整えていきたいです。