星際原始碼 -20181203
ipfs的御用包管理器 gx入門指南
何為 gx
原始碼位置:ping/gx%7C" target="_blank" rel="nofollow,noindex">https://github.com/whyrusleeping/gx|
官方稱其為一個通用包管理器,構建於 IPFS 之上,gx 最初的設計靈感來自 nodejs 的 npm ,用來處理 golang 專案中的依賴包。如果從原始碼來欣賞 IPFS 並且心存二次開發的願望,那麼對 gx 的掌握還是非常有必要的。
本人在年初學習 IPFS (v0.4.12)時並沒有重視 gx 這個工具,甚至還在二次開發的過程中放棄了 gx 而改用 govendor 來進行 deps 的管理,這在後期升級 libp2p 時簡直就是一場災難。由於工作需要現在又需要使用 go-libp2p 來做一個 p2p 應用,所以下定決心一定要征服 gx
想要了解更多需要仔細閱讀原始碼的 README,此處用來簡要說明這個工具的使用方法,希望對使用 go-ipfs 和 go-libp2p 的同學能起到一些幫助的作用
工具要求
使用 gx 前本地一定要先啟動 ipfs daemon ,版本也是有要求的,用最新版 ipfs 總是沒錯的。
如果沒有啟動 ipfs 那麼 gx 會從 ipfs.io 這個公共閘道器獲取資源,在國內這個閘道器幾乎是不可用的。
安裝 gx
$ go get -u github.com/whyrusleeping/gx
前提是已經安裝和配置了最新版的 golang
工具會安裝在
$GOPATH/src/github.com/whyrusleeping/gx
並且會 install 到
$GOPATH/bin
不要忘記把 bin 目錄放到 PATH 中哦
使用 gx
建立和釋出一個包:
$ gx init $ gx publish
建立一個 golang 的工程,並在工程工程根目錄gx init 後,會生成一個 package.json 檔案用來描述你的庫,執行 gx publish 後將會得到一個 hash 值,這是與你當前庫的版本相對應的唯一ID,以後匯入包時需要使用。
安裝 gx包
當你在 github 上 clone 了一個 gx 包時,這個包很可能用 gx 管理了本地的依賴,所以你要通過 gx install 或者 gx i 這個子命令來進行安裝,此時依賴包也會一併被安裝到 GOPATH$/src/gx/ipfs 這個目錄中。
匯入依賴
匯入一個依賴非常簡單,只要知道 hash 通過 import 即可完成匯入
$ gx import QmaDFJvcHAnxpnMwcEh6VStYN4v4PB4S16j4pAuC2KSHVr
gx 會去 ipfs 中下載這個 hash 對應的包並且這個包的 hash、版本、名字 都會出現在你的 package.json 中
$ gx deps go-log QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52 1.2.0 go-libp2p-peer QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p 2.0.4 ......
檢視直接依賴,還可以通過 -r -s 來檢視全部依賴
$ gx deps -r -s go-base58QmT8rehPR3F6bmwL6zjUN8XpiDBFFpMP2myPdC6ApsWfJf 0.0.0 go-cryptoQme1boxspcQWR8FBzMxeppqug2fYgYc15diNWmqgDVnvn2 0.0.0 go-datastore QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU 1.0.0 go-ipfs-util QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1 1.0.0 go-keyspaceQmUusaX99BZoELh7dmPgirqRQ1FAmMnmnBn3oiqDFGBUSc 1.0.0 go-libp2p-crypto QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ 1.0.4 go-libp2p-peer QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p 2.0.4 go-libp2p-peerstore QmYkwVGkwoPbMVQEbf6LonZg4SsCxGP3H7PBEtdNCNRyxD 1.2.5 ......
還可以通過 --tree 選項來檢視完整的依賴樹
$ gx deps --tree ├─ go-base58 QmT8rehPR3F6bmwL6zjUN8XpiDBFFpMP2myPdC6ApsWfJf 0.0.0 ├─ go-multihashQmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku 0.0.0 │ ├─ go-base58QmT8rehPR3F6bmwL6zjUN8XpiDBFFpMP2myPdC6ApsWfJf 0.0.0 │ └─ go-cryptoQme1boxspcQWR8FBzMxeppqug2fYgYc15diNWmqgDVnvn2 0.0.0 ├─ go-ipfs-utilQmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1 1.0.0 │ ├─ go-base58QmT8rehPR3F6bmwL6zjUN8XpiDBFFpMP2myPdC6ApsWfJf 0.0.0 │ └─ go-multihash QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku 0.0.0 ......
全部顯示出來通常不是我檢視依賴的需求,更常用的是針對某個庫進行檢查,gx 同時提供了 --highlight 選項來過濾感興趣的內容
$ gx deps --tree --highlight=go-crypto ├─ go-multihashQmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku 0.0.0 │ └─ go-cryptoQme1boxspcQWR8FBzMxeppqug2fYgYc15diNWmqgDVnvn2 0.0.0 ├─ go-ipfs-utilQmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1 1.0.0 │ └─ go-multihash QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku 0.0.0 │└─ go-crypto Qme1boxspcQWR8FBzMxeppqug2fYgYc15diNWmqgDVnvn2 0.0.0 ......
這個過濾後的樹是前一個樹的子集,而且僅顯示出現在葉子節點上的 highlight 包
-
gx deps 還有兩個自命令 'dupes' 和 'stats' 。
gx deps dupes 用來幫助我們檢視重複匯入的庫,例如相同的庫在不同位置匯入了不同的 hash。
gx deps stats 用來輸出關於依賴的狀態資訊,包括 Total Import Count、Unique Import Count 、Average Import Depth ,可以大概用來了解依賴關係的複雜度。
注意:gx import這個操作會去修改我們已經寫好的程式碼,例如:
我們在沒有使用 gx 時,匯入了 go-lightrpc/rpcserver
import "github.com/cc14514/go-lightrpc/rpcserver"
之後我們將 go-lightrpc 通過gx publish
釋出得到QmYaVXmXZNpWs6owQ1rk5VAiwNinkTh2cYZuYx1JDSactL
這個 hash
執行gx import QmYaVXmXZNpWs6owQ1rk5VAiwNinkTh2cYZuYx1JDSactL
import "gx/ipfs/QmYaVXmXZNpWs6owQ1rk5VAiwNinkTh2cYZuYx1JDSactL/go-lightrpc/rpcserver"
檢視程式碼時你會發現工程中所有匯入了 go-lightrpc 的地方都被替換了
依賴關係的設計原則
設計程式依賴時儘量遵循以下原則:
1、依賴關係深度最小化
2、儘量讓依賴樹的廣度最小化,但是不要以犧牲深度作為代價
更新
使用 gx 更新依賴非常簡單
$ gx update mypkg QmbH7fpAV1FgMp6J7GZXUV6rj6Lck5tDix9JJGBSjFPgUd
其中 mypkg 指依賴包的 name ,可以在 package.json 中找到要更新的 mypkg ,也可以通過 gx deps 來找到對應的 mypkg.
也可以只提供要更新的包的 hash
$ gx update QmbH7fpAV1FgMp6J7GZXUV6rj6Lck5tDix9JJGBSjFPgUd
這樣做時 gx 會去下載這個 hash 後檢查名稱並更新專案中對應的名稱。
這裡要順便說一句,看過官方文件你會發現還有一個叫 gx-go 的工具,可以幫你自動把 gx 依賴匯入 govendor 來管理,現在是動盪期,這個工具暫時就不推薦使用了,不出意外的話我們很快就要像送別 godeps 一樣送別 govendor 了。
其實gx update 還有一個很讓人期待的選項 '--with-deps',顧名思義,他會幫助我們深度更新依賴的依賴,但遺憾的是這個功能尚不能達到生產級別,可以跟隨gx每個版本的更新來體驗其可用性,現在還是實驗階段。
Publishing and Releasing
如果你要 publish 一個庫,但是並沒有修改版本號,那麼預設是不允許的,可以通過 '-f' 選項來強制釋出。版本號記錄在 package.json 中,升級版本號可以通過gx version
這個子命令來完成
$ gx version 5.11.4
版本號的格式通常遵循 : major.minor.patch 原則,所以可以直接用下面方式更新
$ gx version patch updated version to: 5.11.5 $ gx version minor updated version to: 5.12.0 $ gx version major updated version to: 6.0.0
使用 gx 更新工程時通常會做如下操作:
$ gx version minor updated version to: 6.1.0 $ gx publish package whys-awesome-package published with hash: QmaoaEi6uNMuuXKeYcXM3gGUEQLzbDWGcFUdd3y49crtZK $ git commit -a -m "gx publish 6.1.0" [master 5c4d36c] gx publish 6.1.0 2 files changed, 3 insertions(+), 2 deletions(-)
為了自動執行以上指令碼,可以使用release
子命令gx release <version>
將會自動幫你執行 version update 和 publish ,隨後會執行你在 package.json 中通過releaseCmd
設定的指令,例如去獲取你設定的git commit -a -m \"gx publish $VERSION\"
,執行時 gx 會用 version 來覆蓋 $VERSION 變數。
忽略:Ignoring files from a publish
可以通過.gxignore
檔案來指定 gx 要在 publish 中忽略的檔案,和.gitignore
的作用類似,同時 gx 也遵守.gitignore
約定。
中央庫:Repos
gx 可以像 maven 一樣來指定中央庫,不過因為 ipfs 的網路多是以不穩定的 pc 機組成,所以新增一個 node 作為中央庫也未必可靠,除非這個庫就是你自己部署的,如果是臨時的就不建議添加了。
如果你想在本地開發測試,在伺服器上執行編譯和執行,那麼伺服器上也至少要執行一個 ipfs daemon 了,此時你直接把本地 ipfs 連到伺服器上,如 'ipfs swarm connect 伺服器ipfsid' ,當然你也可以選擇交叉編譯,go 提供的交叉編譯能力還是很讓人滿意的。
- 新增一個新的中央庫
$ gx repo add myrepo /ipns/QmPupmUqXHBxikXxuptYECKaq8tpGNDSetx1Ed44irmew3
- 列出本地已經新增的中央庫
$ gx repo list myrepo/ipns/QmPupmUqXHBxikXxuptYECKaq8tpGNDSetx1Ed44irmew3
- 列出指定中央庫中包含的庫
$ gx repo list myrepo events QmeJjwRaGJfx7j6LkPLjyPfzcD2UHHkKehDPkmizqSpcHT smalltreeQmRgTZA6jGi49ipQxorkmC75d3pLe69N6MZBKfQaN6grGY stumpQmebiJS1saSNEPAfr9AWoExvpfGoEK4QCtdLKCK4z6Qw7U
- 從指定的中央庫匯入一個庫
$ gx repo import events