govendor vs dep

我的 ~/.gitconfig 裡面有這樣的設定

1
2
3
4
[url "git@github.com:"]
insteadOf = https://github.com/
[url "git@bitbucket.com:"]
insteadOf = https://bitbucket.org/

作用是存取 private repository 的時候,會自動換成 git+ssh. 本來不需要設定這個, 因為 git clone 的時候都會特別注意網址,只是為了方便使用 go get,因為它對這兩 個站預設只會用 https://,碰到 private repo 的時候就沒法自動了。

但剛才抓別人的 project 下來以後跑 govendor sync 卻發現它針對 bitbucket.org/private_team/private_repo 這樣的情況沒法處理:

1
2
3
$ govendor sync
Error: Remotes failed for:
Failed for "bitbucket.org/private_team/private_repo" (failed to ping remote repo): https://api.bitbucket.org/1.0/repositories/pilot_seals/quividisdk: 403 Forbidden

改為試著執行 golang 官方做的 dep,竟然會自己讀 govendor 用的 vendor/vendor.json 檔案來轉換,而且順利的下載了 private repo 執行完畢。

找了一下原因,發現 govendor 裡面用了官方建議的 golang.org/x/tools/go/vcs 來 處理 bitbucket 的 repo 類型判斷,然後 vcs 裡面會呼叫上面的 API 網址;但如果是 private 的,就連那網址都會 403,導致噴錯。奇怪的是,dep 就沒有這個問題。看了看 程式碼,發現它用的不是官方那份 vcs,而是來自 github.com/Masterminds/vcs 的另 外一份,說明寫說是基於 vcs 擴充而成的。看一下 bitbucket 相關程式碼,發現多了這 段:

1
2
3
4
5
6
7
8
9
10
// Fast path for ssh urls where we may not even be able to
// anonymously get details from the API.
if ul.User != nil {
un := ul.User.Username()
if un == "git" {
return Git, nil
} else if un == "hg" {
return Hg, nil
}
}

這也太黑心了,dep 自己沒用官方那份,這樣 govendor 豈不是死得不明不白…

2018/07/24 補充

golang.org/x/tools/go/vcs 是從 cmd/go/internal/get copy 出來的,而 upstream 已解掉此問題:#5375,程式碼在 vcs.gogovendor 本身的 issue 在 #151.