GeekFactory

int128.hatenablog.com

Gradle SSH Plugin/Groovy SSH 2.0.0をリリースした

Gradle SSH Plugin 2.0.0、Groovy SSH 2.0.0をリリースしました。

github.com

github.com

2.0.0の変更点

executeSudo メソッドでsudoコマンドに与えるパスワードをデフォルト(SSH接続時のパスワード)から変更できるようにしました。また、sudoコマンドのパスを変更できるようにしました。この機能追加は@johnjaylward、@ashrafmrからいただいたIssueをベースにしています。

2.0.0になりましたが、既存ユーザの混乱を避けるため後方互換性が失われる変更はありません。では、なぜ2.0.0にしたのかというと、リファクタリングで内部構造を大幅に変更したためです。Groovy SSHではSSH接続やコマンド実行で細かい設定を与えることができるのですが、設定を1つのクラスに入れてしまうと見通しが悪くなってしまうため、複数のクラスを @Delegate で集約する方式で実装しています。以下のような感じです。

class ConnectionSettings {
    String user
    String password
    //...
}

class SudoSettings {
    //...
}

class CompositeSettings {
    @Delegate
    ConnectionSettings connectionSettings = new ConnectionSettings()
    @Delegate
    SudoSettings sudoSettings = new SudoSettings()
}

@Delegate による方式はいくつか問題点がありました。まず、委譲するクラスのプロパティが重複するとうまく動きません。例えば、上記でConnectionSettingsSudoSettingsが同じプロパティを持っていた場合、実体は2つあるのにgetter/setterはCompositeSettingsの中で後から定義した方が勝つようです。それから、プロパティの一覧を取得すると@Delegate付きのプロパティも取れてしまうため、例えばプロパティ一覧をtoString()するような場合は再帰的に処理しないようにひと工夫が必要です。

そこで、traitで設定を継承する方式に変更しました。以下のような感じです。

trait ConnectionSettings {
    String user
    String password
    //...
}

trait SudoSettings {
    //...
}

trait CompositeSettings implements ConnectionSettings, SudoSettings {
}

これであれば、プロパティが重複しても実体は1つに集約されます。また、@Delegate付きのプロパティがないためプロパティ一覧に余計なものが出てこなくなります。

traitによる設定継承の設計にはずいぶんと時間がかかってしまいました。さらに、Groovy 2.4でコンパイルしたコードがGroovy 1.8(Gradle 1.x)でうまく動作しない問題には頭を悩まされました。Groovy 1.8で実行すると propertiesmetaClass が取れてしまい、知らない間にMetaClassが書き換えられていて動作がおかしいとか。

Stream Interactionのリファクタリングはまだ時間が掛かりそうなので、2.1.0もしくは2.0.1でリリースする予定です。