Mavenリポジトリを検索してPOMとかGrape用形式で出力できるスクリプトを書いてみた

はじめに

Groovyで、GrapeというIvyベースのツールがあって鼻水ちょちょぎれるほど便利(ry
というわけで、最近はちょくちょくMavenリポジトリを検索することがあります。


Groovyのコードを書くときはscreen+vimでやってるんですけど、そうなると、一々Webブラウザ経由で検索しに行くのがおっくうになってくるわけです。


というわけで、プログラマの三大美徳である「無精(Laziness)」の名の下に、Mavenリポジトリを検索するGroovyでスクリプトを書いてみました。ハイル、無精!


もちろん、Maven2のPOM形式と、GroovyのGrape形式で結果を出力できるオプション付きです。


なんかよく考えると既にたくさん前例がありそうですが、車輪の再発明上等です。
楽しいから作ったんだ、何か文句あるかこの野郎。です。すいませんです。

インストール

実行に必要なソースコード類一式はgithub上に置いてあります。


実行にはGroovy1.7以上が必要です。別途インストールして下さい。ダウンロードはこちら。


普通に↓な感じでどこかにcloneした後、PATHを通してください。

$ cd $INSTALL_DIR
$ git clone git://github.com/nobeans/maven-tools.git
$ export PATH=$PATH:$INSTALL_DIR/maven-tools/bin


動作確認としてヘルプを表示してみてください。こんな感じです。

$ mvn-search -h
usage: mvn-search [OPTIONS] KEYWORD..[KEYWORD]
 -g,--format-grape   print Groovy Grape format
 -h,--help           print this help message
 -p,--format-pom     print Maven2 pom format
 -u,--with-url       with URL of the artifact in mvnsearch.com
 -v,--with-version   with retrieved versions (HEAVY)

使ってみる

品揃えをざっくりと確認する

まずは欲しいプロダクトを見つけるための検索です。
結果は1アーティファクトにつき1行で表示されます。

$ mvn-search commons-io
Commons IO - commons-io:commons-io
Commons IO - org.apache.commons:commons-io
Wrappers - Apache Commons I/O - com.kenai.nbpwr:org-apache-commons-io
yac-io - net.sf.yac-io:yac-io
Sulky I/O - de.huxhorn.sulky:de.huxhorn.sulky.io
リリース済みバージョンを確認する

最新バージョンはなんだっけ?というときに便利です。

$ mvn-search -v commons-io 
------------------------------------------------------------
>> Commons IO
Commons IO - commons-io:commons-io
versions: [1.4, 1.3.2, 1.3.1, 1.3, 1.2, 1.1, 1.0, 0.1, 20030203.000550]
------------------------------------------------------------
>> Commons IO
Commons IO - org.apache.commons:commons-io
versions: [1.3.2]
...(省略)...
POMファイルにすぐ貼れるXML形式で出力する

よさげな検索キーワードが見つかって、検索結果がうざくない程度に絞り込めたら、その検索キーワードを使って、POMファイルの断片形式で出力してみます。

$ mvn-search -pvu commons-io
------------------------------------------------------------
>> Commons IO
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>1.4</version>
</dependency>
versions: [1.4, 1.3.2, 1.3.1, 1.3, 1.2, 1.1, 1.0, 0.1, 20030203.000550]
http://mvnrepository.com/artifact/commons-io/commons-io
------------------------------------------------------------
>> Commons IO
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-io</artifactId>
  <version>1.3.2</version>
</dependency>
versions: [1.3.2]
http://mvnrepository.com/artifact/org.apache.commons/commons-io
...(省略)...

こんな感じ。オプションの-pがPOM形式出力を指定してます。

-vをつけると、リリース済みバージョン一覧を取得して、かつ、その先頭のバージョンを最新バージョンとみなして、pom形式のXML内に展開してくれます。
-uは、mvnrepository.com上のアーティファクトの詳細ページへのURLを出力するオプションです。


-vと-uを外してみると、こんな感じ。

$ mvn-search -p commons-io
------------------------------------------------------------
>> Commons IO
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
</dependency>
------------------------------------------------------------
>> Commons IO
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-io</artifactId>
</dependency>
...(省略)...

バージョンとURLが出力されてませんね。
pomにこれをコピペした場合、バージョン指定が省略されたことになり、その時点の最新バージョンを使うという指定になります。

Groovyスクリプトにすぐ貼れるGrape形式で出力する

もちろん我らがGrapeの@Grab記法でも出力できます。

$ mvn-search -guv commons-io
------------------------------------------------------------
>> Commons IO
@Grab("commons-io:commons-io:1.4")
versions: [1.4, 1.3.2, 1.3.1, 1.3, 1.2, 1.1, 1.0, 0.1, 20030203.000550]
http://mvnrepository.com/artifact/commons-io/commons-io
------------------------------------------------------------
>> Commons IO
@Grab("org.apache.commons:commons-io:1.3.2")
versions: [1.3.2]
http://mvnrepository.com/artifact/org.apache.commons/commons-io
...(省略)...

-vと-uを外してみると、こんな感じ。

$ mvn-search -g commons-io 
------------------------------------------------------------
>> Commons IO
@Grab("commons-io:commons-io:*")
------------------------------------------------------------
>> Commons IO
@Grab("org.apache.commons:commons-io:*")
...(省略)...

コピペで楽々ですね。


注意事項

検索のクセ

なお、mvnrepository.comの検索に100%依存しているので、指定した文字列に対して何がヒットするかは、ちょっと直感的ではない部分がありますがご了承ください。

  • 例)
    • 単語の一部だけを指定してもヒットしない("groo"と指定して"groovy"系プロダクトはヒットしない)
    • 空白区切りで複数のキーワードを指定するとOR検索っぽい
-vオプションはサーバ負荷が高い

-vオプションを指定した場合のみ、検索して見つかったアーティファクトごとに個別に詳細情報を取得しに行くので、アーティファクト数が多いとサーバに高負荷がかかります。
意図せずにDoS攻撃になってしまうのはまずいので、現状では一度に10個のアーティファクトまでしかバージョン解決ができないようになっています。
mvnsearch.groovy内の定数を変更することで緩和できますが、mvnrepository.comの人にDoS攻撃とみなされてしまっても当方では責任は負いかねます。自己責任でお願いします。

割とどうでも良いかもしれない技巧について

  • CliBuilderによるパラメータ処理
    • ちょっと融通が利かないところもあるけど、このくらいのスクリプトでさらっと使うには非常に便利。
  • JavaScriptでよくやる高階関数っぽい記法
    • printArtifactクロージャのとことか。
    • 必然性はたぶん、ないです。書いてみたかっただけ。
  • Gparsを利用してマルチスレッド化
    • シングルスレッド直列だと遅かったので。
    • ActorとかAsynchronizerは慣れてくると便利。
    • これも多重度あげすぎるとサーバ負荷がまずいので、現状では5スレッドにしてあります。

おわりに

個人的にはすごく使えるツールになっていい感じです。

githubのWikiにはちょっとだけ書いてありますが、とあるツールを使うとgroovyが爆速になって最高なんですが、それは"あとで書く"。