sbtの "~ compile" がファイル名変更や移動を検知してくれない件

sbtにissue作るかpull reqを出したいけれど
「誰が見ても明らかなバグで修正方法も明らか」
ではなく*1、少し議論の余地がありそうだけれど、そのあたりを英語でうまく説明する自信がないので、まずは日本語で書きだしてみるシリーズ(たぶん後でissue報告かpull reqします しました) *2

  • "~ compile" というのは、ファイルの変更を検知して、それをトリガーにして、コンパイル(やテストなどの指定した任意のコマンド)を実行してくれるもの。
  • 「ファイル名変更や移動を検知してくれない」というの、確かにそうなのだが、別にそれほど困ってない
  • ただ、以下のような構成になってるとき「rootで"~ compile"にしておいたとき、aからb(もしくはbからa)にファイルを移動しても、検知されない」というので、数ヶ月に一度くらいの頻度で困る
val a = project

val b = project.dependsOn(a)

val root = project.aggregate(a, b)
  • 「このファイルはやっぱりこっちのモジュールにあったほうがいいなー」と整理する際や「1つだったモジュールを2つに分ける際」に、たまにモジュールまたいだファイル移動を行うことがあるので
  • aからbや、bからaに移動だと、コンパイル結果全然異なるものになる場合がありえるので、できれば再コンパイルしてほしい
  • 一度 "~ compile" の状態を解除して、再びコンパイルすると、正常にコンパイルされるので、まぁそれほど大きな問題ではない
  • とりあえず修正はしてみたが、それで悩んでるのが何点か
    • 果たしてこういう動作にしてしまっていいのか?
    • かなり使われてる重要な機能なので、パフォーマンス劣化したらやばそう
    • Set[String]を保持して毎回比較するのは、速度やメモリ的にどうなのか?
    • こういう動作にしてしまって、なにかデメリットないか?
    • そもそも「プロジェクト間をまたいだファイル移動」だけを検知すればよい?(それは可能なのか?)
    • 過去にこの件に関する議論やissueはなかった気がするけど、あったらすみません
  • 動作を急に変更するのが怖いなら、この部分の動作を使う側がカスタマイズできるようにすべき?
    • どういう方法で?
    • Boolean型のKeyを1つ追加(今まで通りの動作か、自分が修正した動作か)
    • Key追加ではなく -D などで指定する?
    • Booleanではなく、たとえばWatchStrategyというようなものを作って汎用的にする(そんなことするほどのものか?)
  • ところで、こういうテストどうやって書くべきなのだろう。scripted-testだと書けない?


ここから追記


以下、よこたさんとのやりとり


というわけで、言われたとおりに、まず

  • 自分が最初に実装したSet[String]
  • ソートして List[String]
  • ソートして mkString して Hash(...) を計算して文字列に変換して sha1 同士で比較

を試す。

結果的に速度的に優位な差はでなかった(2割くらい差がでた場合もあったが、数割ではほとんど誤差の範囲?)

なので、とりあえず自分の最初のSet[String]での比較でいい気がした。
あと、「ScalaのコレクションよりJavaのコレクションのほうが速いことがある」というのを耳にした覚えがあったので、java.util.HashSetでも試したが、やはり変わらなかった。
あと、念のため、scalaのimmutableなHashSetの実装見てみたが、
https://github.com/scala/scala/blob/v2.10.4/src/library/scala/collection/GenSetLike.scala#L114-L123
まず最初にsizeを比較してたり、その後もべつにアルゴリズムのオーダー的にひどくなるようなことはしていなさそうだった。

実際の
「getCanonicalPathして、Set[String]生成して、それを以前のSet[String]と比較」
の速度だが、Scalaz、play2、sbt、で試した結果、自分の手元のPCでは遅くても20msから30ms程度だった。たぶんこれなら許容範囲のはず(?)

また、しばらく "~ compile" のままにしておいても「使用メモリがモリモリ増え続ける」とか「CPU使用率が以前より明らかに大幅に増加する」とかはなかったと思う。CPU使用率は少しだけ増えるかも?(これも、対して慎重に計測したわけではないので、誤差なのかどうなのか不明)


というわけで、最初のコードのままpull reqした

https://github.com/sbt/sbt/pull/1401

*1:そうだったらこんなことせずにpull reqしてる

*2:以前もgistかなにかにまとめて、eed3si9nさんに相談しつつ、結局その後自分がissue報告した覚え・・・

*3:通常、renameやmvだけをしても、更新日時は変更されないようだ