はじめに
普段自分はmotemenさんのghqを使ってリポジトリを管理しています.
これを用いた場合,通常は~/.ghq
以下の適当な位置にリポジトリが配置されます.
ところで最近,go言語に手を出したのですが,はじめに$GOPATH
を~/.go
と設定して作業し始めました.
しかしこの場合,ghq get
したリポジトリが$GOPATH/src
以下に配置されないことから,importやdepを使う際にエラーが生じました.
そのとき,この問題について検索すると様々な解決方法がヒットし,どの方法が最適解なのかわからずややハマってしまいました.
そこで今回はgo言語のリポジトリを扱う上でどの方法が良いのかまとめてみようと思います.
ghqを活用する上でgo言語のリポジトリをどのように扱うか
方法1 $GOPATH
を複数設定する
まずは$GOPATH
が設定されていないことが問題なのでそれを設定することを考えます.
以下のようにして$GOPATH
は複数設定することができます
# 例: ~/.bashrcに以下を記述
export GOPATH=$HOME/.go:$HOME/.ghq
このように$GOPATH
を複数指定した場合は,go get
した際はプライマリのパスが採用され,importやdepの際はセカンダリ以降のパスも見る仕様のようです.
あとは.ghq/github.com/...
となっている構造を.ghq/src/github.com/...
とすることで冒頭の問題は解決できます.
問題点
.ghq
以下が汚くなる
.ghq/src/github.com/...
にリポジトリを移動させないといけないため.ghq/
直下にsrc/
というディレクトリが作られ,決してきれいな構造であるとは言えません(きれいな構造とは).
またdep ensure
を走らせると.ghq/pkg/
も生成され,他の言語のリポジトリも管理している場合とても面倒です.ghq get
したあとにその都度.ghq/src/
に移動させるのも大変です.
方法2 $GOPATH/src/
以下もghq rootに含める
この方法ではgo言語のリポジトリは全てgo get
で取得し$GOPATH/src
以下で管理します.($GOPATH
は増やさない)
ただしこのままだとpecoなどを使っている人はghq list
としても対象のリポジトリが引っかからないため不都合が生じます.このため次の通りにします.
ghq list
はghq root
以下のリポジトリを表示してくれますが,このghq root
は.gitconfig
の記述に基づいて設定されています(何も記述しないと~/.ghq
に設定される).またこれは複数設定できるため以下のようにして$GOPATH/src
もrootに設定します.
# プライマリパスに`ghq get`でもってきたいディレクトリのパスを設定
git config --global --add ghq.root $HOME/.ghq
# $GOPATH以下も管理対象にする
git config --global --add ghq.root $GOPATH/src
# 確認
git config --global --get-all ghq.root
.gitconfigはこのようになります
(省略)
[ghq]
root = /home/{{your_name}}/.ghq
root = /home/{{your_name}}/go/src
問題点
"go get" と "ghq get" を使い分ける必要がある
go言語のリポジトリはgo get
でそれ以外のリポジトリはghq get
を使う必要があります.誤ってgo get
とするところをghq get
としてもcpを使えば大丈夫ですが,慣れるまでは使い分けが面倒に感じられるかもしれません.
リポジトリの位置が統一されない
go言語を用いたものは.go/
以下にそれ以外は.ghq/
以下になるため同一ディレクトリで管理したくてもそれができなくなります.しかしこの問題は普段,pecoを使ってディレクトリ移動をしている人には大した問題にはならないかと思われます.
方法3 ghq root を .go/src に設定する
この方法ではghq root
を.go/src
以下に設定することで解決を図ります.方法は2番目のとき同様に.gitconfig
にrootの場所を.go/src
として記述します.これによりgo get
,ghq get
どちらにしても同一の場所にリポジトリがクローンされます.
問題点
.goの中身は決してgoだけではない...という状況になる
go get
,ghq get
どちらも.goディレクトリ以下に配置されるためにgo以外の言語で書かれたものも全て,go/
内にあるという状況が生まれます.解決方法として.go
ではなく.repo
など(いい名前が思いつきませんでした...)に名前を変更してそれに応じてパスを書き換える手法が考えられますが,.repo/bin/
はgoのソースから生成されたバイナリしか配置されないことなどに違和感を感じる人もいるかもしれません(自分は違和感を感じた).
結局,自分はどうしたのか
自分は方法2を採用することにしました."go言語はプログラムの管理方法を含めてgoである"と(勝手に)捉えた上でgoは.go/
,それ以外は.ghq/
以下に配置して作業しています.
ところでgo 1.11で試験導入,1.12からは正式採用予定のvgo(go.mod)では$GOPATH
は不要になるようです.
将来的にはこのような問題も解消されるかもしれませんね.