$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

sbtが依存管理に使っているivyのローカルレポジトリやキャッシュについて調べた

自作のScalaライブラリをpublishLocalしながら手元でリリース前に最終確認する - $shibayu36->blog; で、手元で自作ライブラリの最終確認をするにはpublishLocalすれば良いことを書いた。この時にsbtが依存管理に使っているivyについてもついでに調べたので、調べたことについてメモしておく。コードをちゃんと追いかけているわけではないので、もし間違っていたら教えてください。

ivyとは

ivyとは依存管理のライブラリ。sbtも依存管理にはivyを使っているようだ。

ただし、sbtはivyにパッチを当てて使っていそうに見えたので、これは注意かもしれない。

なぜローカルのivyレポジトリを参照してくれるのか

これはデフォルトでsbtが参照先に~/.ivy2/localがresolverを追加しているからっぽい。Resolverについては https://www.scala-sbt.org/1.x/docs/Resolvers.html あたりを参照。sbtでshow fullResolversすると、何がresolverに追加されているか分かる。

sbt:joda-time-fake> show fullResolvers
[info] * Raw(ProjectResolver(inter-project, mapped: ))
[info] * FileRepository(local, Patterns(ivyPatterns=Vector(${ivy.home}/local/[organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)([branch]/)[revision]/[type]s/[artifact](-[classifier]).[ext]), artifactPatterns=Vector(${ivy.home}/local/[organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)([branch]/)[revision]/[type]s/[artifact](-[classifier]).[ext]), isMavenCompatible=false, descriptorOptional=false, skipConsistencyCheck=false), FileConfiguration(true, None))
[info] * public: https://repo1.maven.org/maven2/

このFileRepositoryの部分がローカルのivyレポジトリを参照するための設定。ivyPatternsあたりを見ると${ivy.home}/local/[organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)([branch]/)[revision]/[type]s/[artifact](-[classifier]).[ext]と書いてある。実際のjarファイルが置いてある場所の~/.ivy2/local/com.github.shibayu36/joda-time-fake_2.11/0.0.3-SNAPSHOT/jars/joda-time-fake_2.11.jarとくらべてみると

  • com.github.shibayu36が[organisation]にマッチ
  • joda-time-fake_2.11が[module]にマッチ
  • (scala_[scalaVersion])はマッチしないけど括弧で包まれているので問題ない
  • (sbt_[sbtVersion]/)も同様にマッチしない
  • ([branch]/)も同様にマッチしない
  • 0.0.3-SNAPSHOTが[revision]にマッチ
  • [type]sがjarsにマッチ
  • joda-time-fake_2.11.jarが[artifact](-[classifier]).[ext]にマッチ

ということで、ちゃんと使われるということなのかな?このPatternについてはhttps://ant.apache.org/ivy/history/latest-milestone/concept.html#patterns あたりも参考になった。

ivyのキャッシュについて

ivyは毎回アーティファクトをダウンロードに使わないためにキャッシュしているようなので、このあたりについても調べた。sbt利用上のIvyに関するハマりポイント - たけぞう瀕死ブログが参考になった。

まずキャッシュのディレクトリは~/.ivy2/cache/以下にある。先程のjoda-time-fakeのキャッシュを見てみると、以下のようになっている。

$ tree ~/.ivy2/cache/com.github.shibayu36/joda-time-fake_2.11/
/Users/shibayu36/.ivy2/cache/com.github.shibayu36/joda-time-fake_2.11/
├── ivy-0.0.1-SNAPSHOT.xml
├── ivy-0.0.1.xml
├── ivy-0.0.2.xml
├── ivy-0.0.2.xml.original
├── ivy-0.0.3-SNAPSHOT.xml
├── ivydata-0.0.1-SNAPSHOT.properties
├── ivydata-0.0.1.properties
├── ivydata-0.0.2.properties
├── ivydata-0.0.3-SNAPSHOT.properties
└── jars
    └── joda-time-fake_2.11-0.0.2.jar


まずリモートレポジトリからfetchしてきたものに関しては、jars以下にjarファイル自体をキャッシュしているようだ。なのでjars以下にjoda-time-fake_2.11-0.0.2.jarが存在している。またivydata-0.0.2.propertiesというファイルを眺めてみると

ivydata-0.0.2.properties

#ivy cached data file for com.github.shibayu36#joda-time-fake_2.11;0.0.2
#Sun Mar 25 08:46:10 JST 2018
artifact\:ivy\#ivy\#xml\#742964223.is-local=false
artifact\:joda-time-fake_2.11\#jar\#jar\#1850426835.is-local=false
artifact\:ivy\#ivy\#xml\#742964223.location=https\://repo1.maven.org/maven2/com/github/shibayu36/joda-time-fake_2.11/0.0.2/joda-time-fake_2.11-0.0.2.pom
artifact\:joda-time-fake_2.11\#jar\#jar\#1850426835.location=https\://repo1.maven.org/maven2/com/github/shibayu36/joda-time-fake_2.11/0.0.2/joda-time-fake_2.11-0.0.2.jar
artifact\:joda-time-fake_2.11\#pom.original\#pom\#-791977799.is-local=false
artifact\:joda-time-fake_2.11\#jar\#jar\#1850426835.exists=true
artifact\:joda-time-fake_2.11\#pom.original\#pom\#-791977799.location=https\://repo1.maven.org/maven2/com/github/shibayu36/joda-time-fake_2.11/0.0.2/joda-time-fake_2.11-0.0.2.pom
artifact\:ivy\#ivy\#xml\#742964223.exists=true
artifact\:joda-time-fake_2.11\#pom.original\#pom\#-791977799.exists=true

となっており、

みたいなことが書いてある。なるほど。


続いてpublishLocalしたレポジトリから取ってきた、0.0.3-SNAPSHOTのほうを見てみると

ivydata-0.0.3-SNAPSHOT.properties

#ivy cached data file for com.github.shibayu36#joda-time-fake_2.11;0.0.3-SNAPSHOT
#Sun Mar 25 10:06:08 JST 2018
artifact\:joda-time-fake_2.11\#jar\#jar\#679424103.is-local=true
artifact\:ivy\#ivy.original\#xml\#1006386850.exists=true
artifact\:joda-time-fake_2.11\#jar\#jar\#679424103.location=/Users/shibayu36/.ivy2/local/com.github.shibayu36/joda-time-fake_2.11/0.0.3-SNAPSHOT/jars/joda-time-fake_2.11.jar
artifact\:joda-time-fake_2.11\#doc\#jar\#-517561348.exists=true
artifact\:joda-time-fake_2.11\#doc\#jar\#-517561348.is-local=true
artifact\:joda-time-fake_2.11\#doc\#jar\#-517561348.location=/Users/shibayu36/.ivy2/local/com.github.shibayu36/joda-time-fake_2.11/0.0.3-SNAPSHOT/docs/joda-time-fake_2.11-javadoc.jar
artifact\:ivy\#ivy.original\#xml\#1006386850.location=/Users/shibayu36/.ivy2/local/com.github.shibayu36/joda-time-fake_2.11/0.0.3-SNAPSHOT/ivys/ivy.xml
artifact\:ivy\#ivy\#xml\#-428038509.exists=true
artifact\:ivy\#ivy\#xml\#-428038509.location=/Users/shibayu36/.ivy2/local/com.github.shibayu36/joda-time-fake_2.11/0.0.3-SNAPSHOT/ivys/ivy.xml
artifact\:ivy\#ivy.original\#xml\#1006386850.is-local=true
artifact\:joda-time-fake_2.11\#src\#jar\#-1768464466.is-local=true
artifact\:joda-time-fake_2.11\#src\#jar\#-1768464466.location=/Users/shibayu36/.ivy2/local/com.github.shibayu36/joda-time-fake_2.11/0.0.3-SNAPSHOT/srcs/joda-time-fake_2.11-sources.jar
artifact\:ivy\#ivy\#xml\#-428038509.is-local=true
artifact\:joda-time-fake_2.11\#src\#jar\#-1768464466.exists=true
artifact\:joda-time-fake_2.11\#jar\#jar\#679424103.exists=true

となっており、

  • localである
  • ローカルのivyレポジトリのjarファイルへの参照も書いてある
    • artifact\:joda-time-fake_2.11\#jar\#jar\#679424103.location=/Users/shibayu36/.ivy2/local/com.github.shibayu36/joda-time-fake_2.11/0.0.3-SNAPSHOT/jars/joda-time-fake_2.11.jarあたり?

となっていた。なるほど〜。


これらの調査から、sbt利用上のIvyに関するハマりポイント - たけぞう瀕死ブログに書かれていた、

Ivyはローカルリポジトリに格納されているライブラリに対してはjarファイルを絶対パスで参照するメタファイルのみキャッシュします。上記ではライブラリは一度キャッシュされたら更新チェックは行われないと書きましたが、ローカルリポジトリのjarファイルについてはjarファイルそのものがキャッシュされているわけではなく、参照がキャッシュされているだけなのでpublish-localするだけで変更が反映されるということになります。

をなんとなくであるが理解することが出来たように思う。

キャッシュ周り、このあたり理解できてないとむっちゃハマりそうだな〜。

まとめ

今回はsbtが依存管理に使っているivyのローカルレポジトリやキャッシュについて調べて、その内容をメモした。自分で適当にライブラリを作ってみると、こういう感じで依存管理やビルドツールについても詳しくなれるので便利。