読者です 読者をやめる 読者になる 読者になる

weblog of key_amb

主にIT関連の技術メモ

"clenv" というシェルスクリプトのモジュール管理ツールを引き続き作っている

keyamb.hatenablog.com

上の記事を書いたのが3ヶ月前ですね。
趣味で作っているのでだいぶ波があるのですが、初コミットからは5ヶ月ほど経ちました。

"clenv" って何?

https://github.com/key-amb/clenv です。

説明は上の記事に書きましたが、一応こちらでもかんたんに。

私が趣味で作っているツールで、シェルスクリプトの実行ファイルやライブラリをモジュール化して管理できるようにしてくれるものです。
名前はお察しの通り、rbenv など 〜env が由来です。

"version" という語ではなく "environment" という語を使っています。
"version" だと異なるバージョンのシェルをビルドしてインストールして…のようなことを連想されそうだな、と思いまして。
そういうのをできるツールがあってもいいとは思いますが、それをやる気はない。

"clam" モジュール

これも冒頭の記事に書いたのですが、clenv で使うモジュールを "clam" モジュールと呼ぶことにしました。
git の URL か、ローカルのファイルシステムからインストールできます。

モジュール側では clam.spec というファイルを用意しておく必要があります。
これのファイル形式が v0.3 で少し変わりました*1

まあ、詳しくは README や脚注の PR をご覧くださいということで。

NEW - "cload" コマンドと "cllib" 関数

v0.2 で導入しました。
. or source 相当ですが、 CLOAD_PATH という環境変数の path を見て、そこからの相対パスで読み込めるものです。
これで rubyperl の require 相当のことができる、と考えました。

面倒なのは、これをシェルの関数で提供しなければならないことです。
スクリプティングにおいては、シェル関数を読み込むコードを一行足すか、 eval 実行する必要があります。

使い方としては、下のようになります。

# 例1
eval $(cload "mylib")
eval $(cload "mylib/foo")

# 例2
eval $(cload -)
cllib "mylib"
cllib "mylib/foo"

ここで、 cllib が "cload" のシェル関数版です。

eval $(cload -) をやってくれるラッパーコマンドを作ればいいじゃないか、と思う人もいるかもしれませんが、そうすると実行スクリプト. または source して実行せざるを得なくなる気がします。
ので、厳しそう。

NEW - shims/ に shim を置くことにした

v0.2 までは、 shims => environments/$CLENV_ENVIRONMENT/bin と symlink していただけですが、 rbenv を参考にランチャーとなるシェルスクリプトの実体を置くことにしました。
clam install するときに、下のようなファイルを実行ファイルと同じ名前で shims/ 以下にコピーしています。

#!/usr/bin/env bash

set -euo pipefail
[[ ${CLENV_DEBUG:-} ]] && set -x

program="${0##*/}"

exec "${CLENV_ROOT}/bin/clenv" exec "$program" "$@"

だいたい rbenv や plenv と同様で、clenv exec で対象のコマンドを探して exec します。

Travis CI で継続的にテストできるようにした

シェルスクリプトでどうやるのかな、と思っていたところ、 b4b4r07/enhancdTravis が設定されていたので、参考になりました。

手前味噌ですが、 shove でテストを書いています。*2

実行ファイル系は Bash 前提で書いていますが、シェル関数で機能提供するものは POSIX シェルで動くように書いています。
ので、 make test タスクもそんな感じで書いています。

いま CI 環境 だと、Ubuntu v12.04 のコンテナで sh, bash, dash で CI が走っています。

あらゆる環境で動作保証するものではないけど、まあ、だいたい動くんじゃないかな、というところ。

※テスト足りてないところは色々あります。

clenv 環境で使える Bash 用の Logger モジュールを書いてみた

https://github.com/key-amb/bash-logger

これです。これ自体は bash スクリプト1枚なので、これだけダウンロードして単独で使うこともできます。

clenv 環境にインストールするには clam https://github.com/key-amb/bash-logger.git で。

clenv 環境でこれを使うサンプルコードは下のようになります。

# myapp.bash
eval $(cload logger.bashrc)

log.info "foo"
log.warn "warn"

実行すると下のようになります。

% ./myapp.bash
2016-09-19 08:47:35 [INFO] foo
2016-09-19 08:47:35 [WARN] warn

(本当はログレベルに応じて色が変わります。)

まあ、こういうことがやりたいわけです。
つまり、再利用性のあるライブラリを書いて、再利用して楽にスクリプティングしたい。

今後

shims/ 以下は実体を置くことができたのですが、 environments/$env/{bin,lib} 以下がまだインストールした module への symlink になっているので、それも実体にしないと、ライブラリ同士のディレクトリ構成に依存関係があるときに上手く行きません。

解決する方法は2通りあります。

  1. bin/, lib/ 以下にも中身をコピーする
    • uninstall できるように、何をコピーしたか記録しておかなければなりません
  2. bin/, lib/ 以下に実体は置かない。 cload 時に任意のモジュールについて environments/$env/$module/ 以下の path を CLOAD_PATH に追加して解決する

後者は RubyGems が行っている戦略ですね。*3

前者は clam install/uninstall で頑張る。後者は cload で頑張る感じ。
後者にしても、 bin/ 以下には RubyGems で言うところの binstub 相当を置かないといけないですが、それでも uninstall はだいぶ楽になりそうです。
また、後者にすると同一モジュールでも複数バージョンインストールできるようになったりと、(ニーズはさておき)夢が広がりそうです。

趣味でやっているので、いつになるかわかりませんが、ご興味ありましたら、完成までは気長にお待ちください。

現時点でも上に書いたようなことや、冒頭の記事で書いたような実行ファイルの管理に使えると思います。というか、使っています。

…が、今後、互換性のない変更が入る可能性はありますので、ご注意ください。

脚注