2020年4月29日水曜日

GoでSubversionからパッケージをgo getして実行する(自マシン内完結型)

社内や個人でSubversionを使ってGoコードを管理しているGopherには朗報!?Go 1.14から、goコマンドはmoduleモードでSubversionリポジトリーをサポートしました。

しかしながら、具体的な手順がなかなか見つかりませんでした。そこで「自マシン内のSubversionサーバーに登録されたGoの外部パッケージを、自マシン内で取得して実行する」ことを色々と目標に試してみました。実際に動作した時は心の中でガッツポーツ!q@w@p

Subversionサーバーの構築

自マシンに「Subversion」と「Apache HTTP Server」をインストールします。

Apache HTTP Serverには、Subversionと連動してHTTP/HTTPS通信でアクセスできる仕組みが用意されています。

今回は、諸事情によりno_ssl版のためHTTP通信でアクセスした場合の内容となっています。openssl版&HTTPS通信であればスマートに進められるはずです。

ちなみに、Subversionからの外部パッケージの取得には、svnコマンドが使用されます。

本筋ではないため、具体的なインストールやセットアップについては割愛します。

Subversionリポジトリーの作成

svnadmin createコマンドで新規リポジトリーを作成します。

リポジトリー内に、branches/、tags/、trunk/、の定番ディレクトリーを作成します。

ここでは以下のパス構成を想定しています。

svn://127.0.0.1/go/trunk/src/

本筋ではないため、具体的な手順は割愛します。

GOPROXYとGOSUMDBの無効化

今回は、諸事情により外部へのインターネット接続が制限されているため、moduleに関する2つの環境変数の値を無効化します。

GOPROXYとGOSUMDBの初期値を確認します。

$ go env GOPROXY
https://proxy.golang.org,direct

$ go env GOSUMDB
sum.golang.org

GOPROXYとGOSUMDBに無効値を設定します。

$ go env -w GOPROXY=direct
$ go env -w GOSUMDB=off

GOPATH上への移動

以降、GOPATH上で作業します。GOPATHは以下のコマンドで確認できます。

$ go env GOPATH

外部パッケージをSubversionに登録

外部パッケージとして、Add()関数を持つcalcパッケージを用意します。

calc/ディレクトリーを作成します。

$ mkdir calc

calc/ディレクトリー内に移動します。

$ cd calc

modの初期化を行います。

$ go mod init

作成されたgo.modファイルのmodule行をURLパスに修正します。

修正前:

module calc

go 1.14

修正後:

module 127.0.0.1/svn/go/trunk/src/calc.svn

go 1.14

calc.goを作成します。

$ vim calc.go

package calc

func Add(x, y int) int {
return x + y
}

calc/ディレクトリーをSubversionにチェックインします。
# 私はsvnコマンドではなく、Eclipseでチェックインしています m(__)m

svn://127.0.0.1/go/trunk/src/
|
+--calc/
   |
   +--calc.go
   +--go.mod

メイン パッケージの作成

test/ディレクトリーを作成します。

$ mkdir test

test/ディレクトリー内に移動します。

$ cd test

modの初期化を行います。

$ go mod init

main.goファイルを作成します。

$ vim main.go

package main

import (
"fmt"

calc "127.0.0.1/svn/go/trunk/src/calc.svn"
)

func main() {
fmt.Println(calc.Add(1, 2))
}

外部パッケージURLのホストが自マシンの場合、IPアドレス(ここでは127.0.0.1)で指定します。localhostで指定すると「import path does not begin with hostname」エラーになります。

通常でしたら、ここでmain.goファイルを実行します。

$ go run main.go

この時、import句の"127.0.0.1/svn/go/trunk/src/calc.svn"にHTTPS通信でアクセスして自動で外部パッケージが取得されます。

https://127.0.0.1/svn/go/trunk/src/calc.svn?go-get=1

しかし、今回はHTTP通信のためエラーとなります。そのため、go getコマンドを実行して手動で外部パッケージを取得します。

通常、go getするURLにはHTTPS通信でアクセスします。

$ go get 127.0.0.1/svn/go/trunk/src/calc.svn

今回はHTTP通信のため、-insecure オプションを付けてgo getします。

$ go get -insecure 127.0.0.1/svn/go/trunk/src/calc.svn

main.goファイルを実行すると、外部パッケージ「calc」のAdd(1, 2)が実行されて、結果の3が標準出力されます!

$ go run main.go
3

メイン パッケージのモジュール情報

go.sumファイルが作成されます。

$ vim -R go.sum

127.0.0.1/svn/go/trunk/src/calc.svn v0.0.0-YYYYMMDD... h1:...=
127.0.0.1/svn/go/trunk/src/calc.svn v0.0.0-YYYYMMDD.../go.mod h1:...=

go.modファイルに外部パッケージが追加されます。

$ vim -R go.mod

module test

go 1.14

require 127.0.0.1/svn/go/trunk/src/calc.svn v0.0.0-YYYYMMDD... // indirect

気づいた点など

go getではデフォルトでHTTPS通信が行われています。
→Subversionと連動させるApache HTTP Serverはopenssl版を使いましょう。

Subversionの外部パッケージURLの最後には「.svn」が必要です。
→GihHub経由に慣れていると、なかなか気付けない。

import句にて、Subversion経由の外部パッケージには別名を付けて使用します。
→本ページでは"127.0.0.1/svn/go/trunk/src/calc.svn"にcalcと別名付けています。

関連するGoのソースコード
→使われているsvnコマンドの引数とかがわかります。

0 件のコメント: