少し前にGoの勉強用で不要なブランチを削除するコマンドラインツールを作ったので簡単にまとめてみます。実際に作ったものはこちらです。
https://github.com/yuzoiwasaki/sweep
使い方
こんな感じで不要なブランチを削除できます。
masterブランチ以外を削除
$ git branch
* master
test1
test2
$ sweep
$ git branch
* master
test1ブランチ以外を削除
$ git branch
* master
test1
test2
$ sweep -v test1
$ git branch
* test1
test1ブランチとmasterブランチ以外を削除
$ git branch
* master
test1
test2
$ sweep -v test1 -v master
$ git branch
* master
test1
なぜ作ろうと思ったか
Goでコマンドラインツールを作ってみようと思った時に、せっかくなら自分がほしいものを作りたかったからです。
ブランチの削除自体はワンライナーでできますし、エイリアスに登録しておけば毎回わざわざ長いコマンドを入力する必要もないのですが、エイリアスも面倒なのでこういうツールがあっても良いのではないかと思いました。
なんにせよ、何かを作ろうと思った時に自分のほしいものを作るというのは良いモチベーションだと思います(自分がほしいということは、もしかしたら他の人もほしいかもしれないですし)
コード全体
コード全体としてはこんな感じのコードになります。コマンドラインから引数を受け取って処理した後、シェルコマンドを呼び出すシンプルな構造です。
package main
import (
"flag"
"fmt"
"os/exec"
)
type strslice []string
func (s *strslice) String() string {
return fmt.Sprintf("%v", multiflag)
}
func (s *strslice) Set(v string) error {
*s = append(*s, v)
return nil
}
var multiflag strslice
func main() {
flag.Var(&multiflag, "v", "Specify the branch you want to exclude")
flag.Parse()
if len(multiflag) == 0 {
multiflag = append(multiflag, "master")
}
var b, e string
for _, s := range multiflag {
b = s
e = e + " | grep -v " + s
}
cmdstr := "git checkout " + b + " && git branch" + e + " | xargs git branch -D"
err := exec.Command("sh", "-c", cmdstr).Run()
if err != nil {
fmt.Printf("Error! Failed to sweep branches.\n")
}
}
Goには flag
というコマンドラインオプションをパースできるパッケージがあるので、こちらを使って引数を受け取り処理をしています。
https://golang.org/pkg/flag/
また、最終的にはOS上でシェルコマンドを実行したかったため、合わせて os/exec
もインポートしています。
悩んだところ
flag
は便利なのですが、そのままでは同じオプションに対して複数の値を受け取ってパースすることができません。これを実現するためには、少し独自に拡張する必要があります。
flag
は flag.Var()
を使うことで独自型の変数をバインドすることができます。また flag
には Value
というインターフェースが定義されているため、このインターフェースを満たす形で型を定義してあげることで独自に拡張することができます。便利ですね。
you can create custom flags that satisfy the Value interface (with pointer receivers) and couple them to flag parsing by
flag.Var(&flagVal, "name", "help message for flagname")
・参考
https://qiita.com/hironobu_s/items/96e8397ec453dfb976d4
https://golang.org/pkg/flag/#Value
終わりに
以上、簡単ではありますがGoでコマンドラインツールを作ってみた紹介でした。もしよければ使ってみてください。
拙作ですが、同じように初めてGoでツールを作る人の参考になれば嬉しいです。今のところ仕事でGoを使う予定はないのですが、これからも趣味で触っていきたいと思います。