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

opamp_sando's blog

クソザコが割りと適当なことを書くためにある備忘録です。あとたまに普通の日記も書きます

quicklispでプライベートなリポジトリを作る試み

とりあえずタイトル通り、quicklispでユーザープライベートなリポジトリ(dists)を作る。ずっと作れないと思ってたが作れるようなのでメモ。

※一応できたが一部よくわからない場所をゴリ押しているので注意
 後日何か分かり次第修正・変更します。

環境の準備

今回はサーバードメインexample.comとする。また、httpで通信できるWebサーバーを動かしておく必要がある(今回はlighttpdを使った)

また、これ以降今回作成するプライベートなリポジトリ(dist)のルートディレクトリを$DROOTと表すことにする。また、$DROOTは必ずしもWebサーバーのドキュメントルートである必要はなく、UserDir以下とかでも大丈夫なようだ。
今回の例では$DROOTはドキュメントルートと同じとする。

テスト用のプロジェクトの用意

とりあえず実際にquicklispでインストールしてみるプロジェクトをvtestという名前で用意した。

(cl-project:make-project #p"vtest")

で、quicklisp本家のdistを参考にしたところgitベースで管理していることもあってか日付毎にディレクトリやファイル名を分けて管理しているようなのでそれを真似して、vtestプロジェクトを配布用にvtest-20150617-gitという風にrenameして圧縮した。

$ cp -r vtest vtest-20150617-git
$ tar cfvz vtest-20150617-git.tgz

で、このtarballを$DROOT/archive/vtest/2015-06-17/以下に配置した。

releases.txtを作成

$DROOT/dist/examplecom/2015-06-17/releases.txtを作成する。

# project url size file-md5 content-sha1 prefix [system-file1..system-fileN]
vtest http://example.com/archive/vtest/2015-06-17/vtest-20150617-git.tgz 10818 1c0827c819b2ab8ec95ae74c5b5a8bb6 3aa2f73886cac23db4bce179166cc4f03e3f8e78 vtest-20150617-git vtest.asd

この1行目のシャープで始まる行はHeaderというらしく無いとエラーになったのでコピペしてつけるようにしよう。

URLは名前の通りhttpアクセスした場合の先ほどのファイルのURLを記述する。sizeの大きさはlsのlオプションで確認できるファイルサイズでいいようだ。ちなみにこの値を間違うと失敗する。

$ ls -l

で、file-md5は名前の通りtarballのmd5sumで良いようだ。

$ md5sum vtest-20150617.tgz

問題は次のcontent-sha1で、これがよくわからない。上記の値はとりあえず適当に書いた値だが、それでもちゃんと動いた。
本家distsのreleases.txtの一番はじめにある1amというプロジェクトで試したところ、どうやら名前通り本当にプロジェクト中のファイルをすべて連結したもののsha1sumの値のようだが、どのような順番で連結したものなのかだとか、ディレクトリが含まれる場合はどうすればよいのかは不明。

prefixにはアーカイブ化したプロジェクトのディレクトリ名を記述すれば良いはず。 そして、最後にasdファイルを指定する。

これでreleases.txtは終了。

systems.txtを記述

systems.txtを記述する。同様に$DROOT/dist/examplecom/2015-06-17/systems.txtとして配置する。
今回のvtestは依存関係がないので単純な中身になる。

# project system-file system-name [dependency1..dependencyN]
vtest vtest vtest

依存関係がある場合、この後に列挙していけば良いようだ。

distinfoの記述

このあたりもよくわからないことが多いのだが、とりあえず本家の真似をして作ってみる。
$DROOT/dist/examplecom/2015-06-17/distinfo.txtをまずは作成。

name: examplecom
version: 2015-06-17
system-index-url: http://example.com/dist/examplecom/2015-06-17/systems.txt
release-index-url: http://example.com/dist/examplecom/2015-06-17/releases.txt
archive-base-url: http://example.com/
canonical-distinfo-url: http://example.com/dist/examplecom/2015-06-17/distinfo.txt
distinfo-subscription-url: http://example.com/dist/examplecom.txt

で、作ったら$DROOT/dist/examplecom.txtとしてシンボリックリンクを作成

$ ln -s $DROOT/dist/examplecom/2015-06-17/distinfo.txt $DROOT/dist/examplecom.txt

注意として、どうやらこのファイルのパースはスペースを区切りとして1行をsplitしてパースしているようなので余計なスペースを入れると後々失敗する。

quicklisp-clientの設定

ql-dist:install-distを使う方法

ql-dist:install-distを使うことで先ほどサーバー上に配置したdistinfo.txtをダウンロードして自動で設定できるようだ。

* (ql-dist:install-dist "http://example.com/dist/examplecom/2015-06-17/distinfo.txt")  

とする。

直接設置する方法

ql-dist:install-distを使わずに手動で配置する場合は次のようにする。
ローカルのquicklispのdistsディレクトリの中に、今回作る自作のexamplecomという名前のディレクトリを作成する。

$ mkdir ~/quicklisp/dists/examplecom

人によってはquicklispのprefixを変えているかもしれないが、今回はデフォルトの場合のコマンド。

で、このディレクトリ以下にdistinfo.txtファイルを作って先ほどサーバー側に作ったファイルと同じものを作成する。
つまり以下のやつ。

name: examplecom
version: 2015-06-17
system-index-url: http://example.com/dist/examplecom/2015-06-17/systems.txt
release-index-url: http://example.com/dist/examplecom/2015-06-17/releases.txt
archive-base-url: http://example.com/
canonical-distinfo-url: http://example.com/dist/examplecom/2015-06-17/distinfo.txt
distinfo-subscription-url: http://example.com/dist/examplecom.txt

で、これが配置できたらREPLに入って以下を実行する。

(ql-dist:enable (ql-dist:dist "examplecom"))

これでTが返ってきたらおk。

vtestをインストール

これで準備ができたのでvtestをインストールしてみる。

(ql:quickload 'vtest)

これでvtestがロードされれば成功。

まとめ

quicklispの内部の仕組みが少しだけわかった気がするが、依然として不明な場所が多い。今回の場合distinfo.txtをローカルでも手動で作成したが、サーバーでも作成しているのだからサーバーだけ指定して取ってくるquicklispの関数か何かがあるかもしれない?
quicklisp-clientのコードを読んでいたらql-dist:install-dist関数があったのでこれを利用できた。

あと、cannonical-distinfo-urlとdistinfo-subscription-urlの2つを指定する意味がよくわからないのもある。 これはソースを読んだわけじゃないからまだはっきりとしないが、おそらくdist本体のアップデートの為のものじゃないかと思う。はっきりしたらまた追記・修正する。

後はcontent-sha1は本当にコードを読まないとどうやって生成するのかも何に使われてるかもイマイチわからない。 content-sha1は名前通りパッケージ内部のファイルをすべて連結したもののsha1sumだった。これにはドットで始まるドットファイルも含まれる。結合させる順番は単純にlsで表示されるアルファベット順で、ディレクトリなら再帰的に内部のファイルを連結させる。ただ、適当な値を使ってもやっぱりパッケージはquickloadできるのは謎。

だがとりあえず、スクリプトか何かでasdf準拠のプロジェクトをパッケージ化してarchive以下に適当に配置、releases.txtとsystems.txtを生成して新しいdistを生成、examplecom.txtのリンクを更新という作業を自動化することができればそれなりに運用していけそうな気がする。まだまだ謎は多いから他人に使わせるのはちょっとまだ無理な気がするが。

あと、Common LispにはRubygemsclojarsのようなユーザーがPONと自作のパッケージを簡単に公開できるサービスがない(知らないだけ?)けど、quicklispはプライベートなリポジトリを作れるのならquicklispを利用する形で作れなくはなさそう?

Firefox ブラウザ無料ダウンロード